Как мне прочитать / преобразовать InputStream в строку в Java?

Итак, с функциональной шляпой, это выглядит тривиально .... но в C # есть некоторые существенные недостатки.

вы, вероятно, рассмотрите это как разворот IEnumerable (google it and you Вероятно, в некоторых документах Haskell, возможно, есть некоторые вещи F #, если вы знаете F #, косоглазие в документах Haskell, и это будет иметь смысл).

Unfold относится к fold ( «aggregate»), за исключением повторения через входной IEnumerable, он выполняет итерацию через выходные структуры данных (это аналогичная связь между IEnumerable и IObservable, на самом деле я думаю, что IObservable реализует «разворачивающийся», называемый generate ...)

в любом случае сначала вам нужен метод разворачивания, я думаю, что это работает;

    static IEnumerable<T> Unfold<T, U>(Func<U, IEnumerable<Tuple<U, T>>> f, U seed)
    {
        var maybeNewSeedAndElement = f(seed);

        return maybeNewSeedAndElement.SelectMany(x => new[] { x.Item2 }.Concat(Unfold(f, x.Item1)));
    }

это немного тупо, потому что C # не реализует некоторые из функций, которые функциональные langauges принимают как должное ... но он в основном принимает семя, а затем генерирует ответ «Maybe» следующего элемента в IEnumerable и следующем семестре (возможно, не существует в C #, поэтому мы использовали IEnume (я не могу ругаться, чтобы подделать его), и конкатенирует остальную часть ответа (я не могу ручаться за сложность этого «O (n?)».

Как только вы это сделали,

    static IEnumerable<IEnumerable<T>> Batch<T>(IEnumerable<T> xs, int n)
    {
        return Unfold(ys =>
            {
                var head = ys.Take(n);
                var tail = ys.Skip(n);
                return head.Take(1).Select(_ => Tuple.Create(tail, head));
            },
            xs);
    }

все выглядит довольно чистым ... вы берете «n» элементы как «следующий» элемент в IEnumerable, а «tail» - это остальная часть необработанного списка.

, если в голове ничего нет ... вы закончили ... вы возвращаете «Nothing» (но поддельно как пустой IEnumerable>) ... иначе вы возвращаете элемент головы и хвост для обработки.

вы, вероятно, можете сделать это с помощью IObservable, вероятно, существует уже такой «пакетный» метод, и вы, вероятно, можете его использовать.

Если риск переполнения стека вызывает беспокойство (вероятно, он должен ), тогда вы должны реализовать в F # (и, вероятно, уже есть такая библиотека F # (FSharpX?)).

(Я только сделал некоторые рудиментарные тесты этого, так что могут быть нечетные ошибки в там).

3763
задан Peter Mortensen 5 January 2019 в 10:28
поделиться

7 ответов

Хороший способ сделать это использует свободное городское население Apache IOUtils для копирования InputStream в StringWriter... что-то как

StringWriter writer = new StringWriter();
IOUtils.copy(inputStream, writer, encoding);
String theString = writer.toString();

, или даже

// NB: does not close inputStream, you'll have to use try-with-resources for that
String theString = IOUtils.toString(inputStream, encoding); 

, С другой стороны, Вы могли использовать ByteArrayOutputStream, если Вы не хотите смешивать свои Потоки и Писателей

2377
ответ дан Marko Zajc 5 January 2019 в 10:28
поделиться
  • 1
    Поскольку, что it' s ценность, кто-то прокрутил универсальный браузер каталога HTTP в issues.apache.org/jira/browse/VFS-199 . В моем случае веб-сервер требуется, чтобы следовать за структурой каталогов, которую я определяю так I' m собирающийся должен прокручивать соответствующую Реализацию тракта. Спасибо за помощь мне понять, почему пользовательская реализация необходима. – Gili 9 January 2012 в 04:14

Принятие во внимание регистрирует, нужно сначала добраться java.io.Reader экземпляр. Это может тогда быть считано и добавлено к StringBuilder (нам не нужно StringBuffer, если мы не получаем доступ к нему в нескольких потоках, и StringBuilder быстрее). Прием здесь - то, что мы работаем в блоках, и как таковой не нуждаются в других потоках буферизации. Размер блока параметризован для оптимизации производительности во время выполнения.

public static String slurp(final InputStream is, final int bufferSize) {
    final char[] buffer = new char[bufferSize];
    final StringBuilder out = new StringBuilder();
    try (Reader in = new InputStreamReader(is, "UTF-8")) {
        for (;;) {
            int rsz = in.read(buffer, 0, buffer.length);
            if (rsz < 0)
                break;
            out.append(buffer, 0, rsz);
        }
    }
    catch (UnsupportedEncodingException ex) {
        /* ... */
    }
    catch (IOException ex) {
        /* ... */
    }
    return out.toString();
}
288
ответ дан 11 revs, 8 users 39% 5 January 2019 в 10:28
поделиться

Apache палата общин позволяет:

String myString = IOUtils.toString(myInputStream, "UTF-8");

, Конечно, Вы могли выбрать другие кодировки символов помимо UTF-8.

Также см.: ( документация )

831
ответ дан Peter Mortensen 5 January 2019 в 10:28
поделиться
  • 1
    Я уже делаю это со всеми моими проектами. Проблема все еще происходит. – Reid Main 9 May 2014 в 20:11

Во-первых, вы должны знать кодировку строки, которую вы хотите преобразовать. Поскольку java.io.InputStream оперирует базовым массивом байтов, однако строка состоит из массива символов, который требует кодировки, например, UTF-8, JDK примет кодировку по умолчанию это взято из

System.getProperty("file.encoding","UTF-8"); 

byte[] bytes=new byte[inputStream.available()];
inputStream.read(bytes);
String s = new String(bytes);

. Если массив байтов inputStream очень велик, вы можете сделать это в цикле.

-3
ответ дан 3 October 2019 в 21:03
поделиться

Используйте:

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;

public static String readInputStreamAsString(InputStream in)
    throws IOException {

    BufferedInputStream bis = new BufferedInputStream(in);
    ByteArrayOutputStream buf = new ByteArrayOutputStream();
    int result = bis.read();
    while(result != -1) {
      byte b = (byte)result;
      buf.write(b);
      result = bis.read();
    }
    return buf.toString();
}
64
ответ дан 17 December 2019 в 16:00
поделиться

Если вы не можете использовать Commons IO (FileUtils/IOUtils/CopyUtils), вот пример использования BufferedReader для чтения файла построчно:

public class StringFromFile {
    public static void main(String[] args) /*throws UnsupportedEncodingException*/ {
        InputStream is = StringFromFile.class.getResourceAsStream("file.txt");
        BufferedReader br = new BufferedReader(new InputStreamReader(is/*, "UTF-8"*/));
        final int CHARS_PER_PAGE = 5000; //counting spaces
        StringBuilder builder = new StringBuilder(CHARS_PER_PAGE);
        try {
            for(String line=br.readLine(); line!=null; line=br.readLine()) {
                builder.append(line);
                builder.append('\n');
            }
        } 
        catch (IOException ignore) { }

        String text = builder.toString();
        System.out.println(text);
    }
}

Или, если вам нужна высокая скорость, я бы предложил вариант, предложенный Полом де Вризом (который позволяет избежать использования StringWriter (который внутри использует StringBuffer)):

public class StringFromFileFast {
    public static void main(String[] args) /*throws UnsupportedEncodingException*/ {
        InputStream is = StringFromFileFast.class.getResourceAsStream("file.txt");
        InputStreamReader input = new InputStreamReader(is/*, "UTF-8"*/);
        final int CHARS_PER_PAGE = 5000; //counting spaces
        final char[] buffer = new char[CHARS_PER_PAGE];
        StringBuilder output = new StringBuilder(CHARS_PER_PAGE);
        try {
            for(int read = input.read(buffer, 0, buffer.length);
                    read != -1;
                    read = input.read(buffer, 0, buffer.length)) {
                output.append(buffer, 0, read);
            }
        } catch (IOException ignore) { }

        String text = output.toString();
        System.out.println(text);
    }
}
21
ответ дан 17 December 2019 в 16:00
поделиться

Если вы используете Google-Collections / Guava, вы можете сделать следующее:

InputStream stream = ...
String content = CharStreams.toString(new InputStreamReader(stream, Charsets.UTF_8));
Closeables.closeQuietly(stream);

Обратите внимание, что второй параметр (например, Charsets.UTF_8) для InputStreamReader не является обязательным, но обычно рекомендуется указывать кодировку, если вы ее знаете (что вам следует! )

172
ответ дан 17 December 2019 в 16:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: