InputStream для экспортера CSV

1

У меня есть следующий метод:

public String exportAsCsv(CqlQuery query) {
    Iterator<String> result = queryService.execute(.....);
    StringBuilder buf = new StringBuilder();
    for (String nextLine : result) {
       buf.append(nextLine);
    }
    return buf.toString();
}

Он выполняет некоторый запрос, который возвращает Iterator<String> - он содержит гигабайты данных, поэтому добавление его в StringBuilder - не лучшая идея...

Я хотел бы изменить свой метод так, чтобы он возвращал InputStream.

Это может быть одна возможная реализация (псевдокод):

public InputStream exportAsCsv(CqlQuery query) {
    final Iterator<String> result = queryService.execute(query,false);
    return new MagicalInputStream(){
            @Overwrite
            byte[] readNext() {
                if(!result.hasNext()) { 
                   return null; 
                 } else { 
                   return result.next().getBytes();
                 }
            }       
    }
}

Я ищу InputStream где мне нужно реализовать абстрактный метод (например, byte[] readNext()), который будет использоваться для чтения блоков данных - один за другим. Таким образом, этот входной поток должен буферизовать фрагмент чтения, передать его обратно, а когда его буфер пуст, он должен прочитать следующий фрагмент. Идея состоит в том, что я читаю следующие элементы из Итератора ТОЛЬКО, когда "клиент" рад следующим байтам от входного потока.

Или может быть другая возможность изменить мой метод, чтобы он возвращал InputStream вместо String - любые идеи?

Теги:
io

1 ответ

2
Лучший ответ

Вся реализация InputStream можно было бы избежать, если вы позволите вашему методу принять java.io.Writer. Вместо добавления строк в StringBuilder вы добавляете их в предоставленный Writer.

public void exportAsCsv(CqlQuery query, Writer writer) {
    Iterator<String> result = queryService.execute(.....);
    for (String nextLine : result) {
        writer.append(nextLine);
    }
}   

Если вы действительно хотите InputStream, вы можете попробовать что-то вроде этого:

public InputStream exportAsCsv(CqlQuery query) {
    Iterator<String> result = queryService.execute(.....);
    return new SequenceInputStream(asStreamEnum(result));
}   

private Enumeration<InputStream> asStreamEnum(final Iterator<String> it) {
    return new Enumeration<InputStream>() {

        @Override
        public boolean hasMoreElements() {
            return it.hasNext();
        }

        @Override
        public InputStream nextElement() {
            try {
                return new ByteArrayInputStream(it.next().getBytes("UTF-8"));
            } catch (UnsupportedEncodingException ex) {
                throw new RuntimeException(ex);
            }
        }

    };
}

Я еще не проверял этот подход, поэтому будьте предупреждены; концептуально, однако, я думаю, что это то, что вам нужно.

  • 0
    Вы правы - но .... Я хотел бы иметь InputStream;)
  • 0
    Справедливо. Я отредактировал ответ.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню