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

Если у вас есть java.io.InputStreamобъект, как вы должны обработать этот объект и создать String?


Предположим, у меня есть InputStreamтекст, содержащий текстовые данные, и я хочу преобразовать его в Stringфайл, поэтому, например, я могу записать его в файл журнала.

Какой самый простой способ взять InputStreamи преобразовать его в String?

public String convertStreamToString(InputStream is) {
    // ???
}
21.11.2008 16:47:40
Ответы на этот вопрос только работу , если вы хотите , чтобы прочитать содержимое потока , в полной мере (пока она не будет закрыта). Так как это не всегда предусмотрено (запросы http с сохраняющим соединение соединением не будут закрыты), эти вызовы метода блокируются (без предоставления вам содержимого).
f1sh 14.07.2010 13:32:19
Вам необходимо знать и указывать кодировку символов для потока, иначе у вас будут ошибки кодировки символов, поскольку вы будете использовать произвольно выбранную кодировку в зависимости от того, на какой машине / операционной системе / платформе или ее версии выполняется ваш код. То есть не используйте методы, которые зависят от кодировки платформы по умолчанию.
Christoffer Hammarström 17.12.2010 13:50:11
Просто чтобы повеселиться с моим собственным комментарием от 9 лет назад, в эти дни я использую Groovy "String s = new File (" SomeFile.txt "). Text", чтобы прочитать весь файл сразу, и это прекрасно работает. Я доволен использованием groovy для моего непроизводственного (скриптового) кода и, честно говоря, заставляю вас иметь дело с кодированием и очень длинными файлами, как это делает java, в любом случае это действительно хорошая идея для производственного кода, так что он работает для своих целей, Groovy работает для быстрых сценариев, в которых java не очень хорош - просто используйте подходящий инструмент для работы, и все получится.
Bill K 1.11.2017 23:58:59
Просто ByteArrayOutputStream outputBytes = new ByteArrayOutputStream(); for(byte[] b = new byte[512]; 0 < inputStream.read(b); outputBytes.write(b)); return new String(outputBytes.toByteArray(), StandardCharsets.UTF_8);
Felypp Oliveira 13.12.2017 15:21:39
@BillK с Java 11, вы можете использовать то же, String s = Files.readString​(Path.of("SomeFile.txt"));что и язык, который никогда не будет поддерживать такие магические преобразования типов, как описанные вами.
Holger 24.07.2019 10:56:10
30 ОТВЕТОВ
РЕШЕНИЕ

Хороший способ сделать это - использовать Apache Commons 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если вы не хотите смешивать свои потоки и пишущие

2513
21.05.2018 13:09:50
Для разработчиков Android кажется, что Android не поставляется с IOUtils от Apache. Таким образом, вы можете рассмотреть возможность обращения к другим ответам.
Chris.Zou 1.08.2014 03:57:25
На данный момент это невероятно старый вопрос (он был задан в 2008 году). Это стоит вашего времени, чтобы прочитать более современные ответы. Некоторые используют собственные вызовы из библиотеки Java 8.
Shadoninja 28.03.2016 03:13:11
Этот ответ сильно устарел, и его нужно пометить как таковой (к сожалению, это невозможно).
codepleb 20.04.2016 13:00:11
IOUtils.toString () давно устарел. Этот ответ определенно больше не рекомендуется.
Roshan 15.02.2019 16:08:42
затем отредактируйте его, чтобы объяснить, почему он устарел, чтобы помочь будущим читателям.
Jean-François Fabre♦ 3.04.2019 20:23:31

Принимая во внимание файл, нужно сначала получить 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();
}
298
15.07.2015 10:23:45
Это решение использует многобайтовые символы. В этом примере используется кодировка UTF-8, которая позволяет выражать весь диапазон Unicode (включая китайский). Замена «UTF-8» другой кодировкой позволит использовать эту кодировку.
Paul de Vrieze 9.12.2011 23:11:01
@ User1 - мне нравится использовать библиотеки в своем коде, чтобы быстрее выполнять свою работу. Это здорово, когда твои менеджеры говорят: «Ух ты, Джеймс! Как ты так быстро справился ?!». Но когда нам приходится тратить время на то, чтобы заново изобрести колесо только потому, что мы потеряли представление о том, как включить обычную, пригодную для повторного использования, опробованную и протестированную утилиту, мы теряем время, которое могли бы потратить на достижение целей нашего проекта. Когда мы изобретаем велосипед, мы работаем вдвое больше, но гораздо позже добираемся до финиша. Когда мы доберемся до финиша, никто не сможет нас поздравить.
jmort253 20.01.2012 01:05:48
Извините, после перечитывания моего комментария, он выглядит немного высокомерно. Я просто думаю, что важно иметь вескую причину, чтобы избегать библиотек, и эта причина является допустимой, что вполне может быть :)
jmort253 20.01.2012 01:35:57
@ jmort253 Мы заметили снижение производительности после нескольких обновлений библиотеки в нашем продукте. К счастью, мы создаем и продаем наш собственный продукт, поэтому у нас нет так называемых сроков. К сожалению, мы создаем продукт, который доступен на многих JVM, базах данных и серверах приложений во многих операционных системах, поэтому мы должны думать о пользователях, использующих некачественные машины ... А оптимизация строковых операций может улучшить производительность на 30 ~ 40%. И исправление: In our product, I even replacedдолжно быть «мы даже заменили».
coolcfan 9.05.2012 08:39:51
@ jmort253 Если вы уже используете Apache Commons, я бы сказал, пойти на это. В то же время использование библиотек сопряжено с большими издержками (как показывает распространение зависимостей во многих Java-библиотеках Apache). Если это будет единственное использование библиотеки, было бы излишне использовать библиотеку. С другой стороны, определяя размер собственного буфера (ов), вы можете настроить баланс использования памяти и процессора.
Paul de Vrieze 22.05.2012 09:16:37

Apache Commons позволяет:

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

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

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

847
5.01.2019 10:29:32
Также есть метод, который принимает аргумент inputStream только в том случае, если вы нашли кодировку по умолчанию.
Guillaume Coté 3.02.2011 16:07:37
@Guillaume Coté Я предполагаю, что сообщение заключается в том, что с кодировкой по умолчанию у вас никогда не должно быть «хорошо», поскольку вы не можете быть уверены в том, что это такое, в зависимости от платформы, на которой выполняется код Java.
Per Wiklander 3.02.2011 21:54:26
@Per Wiklander Я не согласен с вами. Код, который будет работать на одном, вполне может быть уверен, что кодировка по умолчанию будет в порядке. Для кода, который открывает только локальный файл, разумно попросить их закодировать в кодировке платформы по умолчанию.
Guillaume Coté 4.02.2011 15:56:01
Для того, чтобы спасти кого - либо хлопот Googling - <зависимость> <идентификатор_группы> org.apache.commons </ идентификатор_группы> <артефакта> Обще-ю </ артефакта> <версия> 1.3.2 </ версия> </ зависимость>
Chris 9.03.2012 12:04:03
Также незначительным улучшением было бы использование константы apache io (или другой) для кодировки символов вместо использования простого строкового литерала - например: IOUtils.toString (myInputStream, Charsets.UTF_8);
user1018711 13.01.2014 12:35:27

Использование:

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();
}
66
5.01.2019 10:30:05
@ DanielDeLeón Нет, это не так. Это BufferedInputStream. Основное чтение составляет 8192 байта за раз.
user207421 24.02.2017 00:07:40
@EJP Я обнаружил, что это медленнее, чем использование BufferedInputStream и чтение в буфер байтового массива вместо одного байта за раз. Пример: 200 мс против 60 мс при чтении файла размером 4,56 МБ.
jk7 17.03.2017 23:13:46
Странно, что никто не указал на другую серьезную проблему (да, чтение побайтового содержимого расточительно, даже с буферизацией): оно полагается на то, что считается «кодировкой по умолчанию» - это редко хороший способ. Вместо этого обязательно передайте кодировку в качестве аргумента buf.toString().
StaxMan 24.01.2019 06:55:44
@ jk7 Время чтения файла размером 4,56 МБ настолько мало, что различия не могут быть значительными.
user207421 23.04.2019 23:21:25

Если вы не можете использовать 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
5.01.2019 10:31:01
Чтобы заставить ваш код работать, я должен был использовать this.getClass (). GetClassLoader (). GetResourceAsStream () (используя Eclipse с проектом maven)
greuze 24.01.2012 12:27:09

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

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

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

173
30.01.2013 16:35:54
@harschware: задан вопрос: «Если у вас есть объект java.io.InputStream, как вы должны обработать этот объект и создать строку?» Я предположил, что поток уже присутствует в ситуации.
Sakuraba 13.04.2011 09:41:11
Вы не очень хорошо объяснили свой ответ и имели посторонние переменные; user359996 сказал то же самое, что и вы, но гораздо понятнее.
Uronym 1.09.2011 22:10:38
+1 для гуавы, -1 для не указания кодировки входного потока. например. новый InputStreamReader (поток, "UTF-8")
andras 6.07.2012 11:01:04
@Chris Noldus С другой стороны, некоторые люди, как и я, уже имеют в своем проекте гуаву и думают, что это решение более элегантно, чем версия только для SDK.
CorayThan 27.09.2013 17:20:16
@Vadzim этот ответ такой же, как этот - оба используют CharStreams.toString
Tom 26.08.2014 20:02:58

Вот способ использования только стандартной библиотеки Java (обратите внимание, что поток не закрыт, ваш пробег может отличаться).

static String convertStreamToString(java.io.InputStream is) {
    java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
    return s.hasNext() ? s.next() : "";
}

Я узнал этот трюк из статьи "Трюки со сканером" . Это работает потому, что Scanner перебирает токены в потоке, и в этом случае мы разделяем токены, используя «начало входной границы» (\ A), что дает нам только один токен для всего содержимого потока.

Обратите внимание: если вам нужно быть конкретным в отношении кодировки входного потока, вы можете предоставить конструктору второй аргумент, Scannerкоторый указывает, какой набор символов использовать (например, «UTF-8»).

Наконечник шляпы идет также к Джейкобу , который однажды указал мне на упомянутую статью.

2302
5.01.2019 10:33:54
Спасибо, для моей версии этого я добавил блок finally, который закрывает поток ввода, так что пользователю не нужно, так как вы закончили чтение ввода. Значительно упрощает код вызывающего абонента.
user486646 21.04.2012 17:07:21
@PavelRepin @Patrick, в моем случае, пустой inputStream вызвал NPE при создании сканера. Я должен был добавить if (is == null) return "";прямо в начале метода; Я считаю, что этот ответ необходимо обновить, чтобы лучше обрабатывать нулевые inputStreams.
CFL_Jeff 9.08.2012 13:36:49
Для Java 7 вы можете закрыть на пробу с: try(java.util.Scanner s = new java.util.Scanner(is)) { return s.useDelimiter("\\A").hasNext() ? s.next() : ""; }
earcam 13.06.2013 05:24:36
К сожалению, это решение, похоже, идет и теряет исключения, выданные в моей базовой реализации потока.
Taig 16.07.2013 07:59:37
К сведению, блоки hasNext в потоках ввода консоли (см. Здесь ). (Просто столкнулся с этой проблемой прямо сейчас.) В противном случае это решение работает нормально ... просто на голову.
Ryan 24.02.2014 05:36:26

Использование:

InputStream in = /* Your InputStream */;
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String read;

while ((read=br.readLine()) != null) {
    //System.out.println(read);
    sb.append(read);
}

br.close();
return sb.toString();
247
5.01.2019 10:35:00
Дело в том, что вы сначала разбиваетесь на строки, а затем удаляете это. Проще и быстрее читать произвольные буферы.
Paul de Vrieze 20.04.2012 18:36:54
Кроме того, readLine не различает \ n и \ r, поэтому вы не можете снова воспроизвести точный поток.
María Arias de Reyna Domínguez 10.09.2012 08:08:02
очень неэффективно, так как readLineчитать символ за символом, чтобы искать EOL. Кроме того, если в потоке нет разрыва строки, это не имеет смысла.
njzk2 18.04.2014 18:05:10
@Gops AB: Если вы попробуете это, и в вашем образце будут новые строки, вы увидите, что способ создания этого цикла с использованием readline () и StringBuilder.append () на самом деле не сохраняет новые строки.
Russ Bateman 4.01.2016 22:01:13
Это не лучший ответ, потому что он не является строго байтовым. Читатель разбивает новые строки, поэтому вы должны быть осторожны, чтобы поддерживать их.
Jeffrey Blattman 18.01.2016 19:16:38

Я провел несколько тестов времени, потому что время имеет значение, всегда.

Я попытался получить ответ в строку 3 разными способами. (показано ниже)
Я упустил блоки try / catch для удобства чтения.

Чтобы дать контекст, это предыдущий код для всех 3 подходов:

   String response;
   String url = "www.blah.com/path?key=value";
   GetMethod method = new GetMethod(url);
   int status = client.executeMethod(method);

1)

 response = method.getResponseBodyAsString();

2)

InputStream resp = method.getResponseBodyAsStream();
InputStreamReader is=new InputStreamReader(resp);
BufferedReader br=new BufferedReader(is);
String read = null;
StringBuffer sb = new StringBuffer();
while((read = br.readLine()) != null) {
    sb.append(read);
}
response = sb.toString();

3)

InputStream iStream  = method.getResponseBodyAsStream();
StringWriter writer = new StringWriter();
IOUtils.copy(iStream, writer, "UTF-8");
response = writer.toString();

Итак, после запуска 500 тестов для каждого подхода с одинаковыми данными запроса / ответа, вот цифры. Опять же, это мои выводы, и ваши выводы могут не совпадать, но я написал это, чтобы дать понять другим различия в эффективности этих подходов.

Ранги:
Подход № 1
Подход № 3 - на 2,6% медленнее, чем # 1
Подход № 2 - на 4,3% медленнее, чем # 1

Любой из этих подходов является подходящим решением для получения ответа и создания из него строки.

34
17.10.2017 08:55:23
2) содержит ошибку, она всегда добавляет «ноль» в конец строки, так как вы всегда делаете еще один шаг, чем необходимо. В любом случае, производительность будет такой же. Это должно работать: String read = null; StringBuffer sb = new StringBuffer (); while ((read = br.readLine ())! = null) {sb.append (read); }
LukeSolar 21.10.2011 13:32:39
Следует отметить, что GetMethod является частью org.apache.commons.httpclient, а не стандартной Java
jk7 24.02.2017 21:29:51
Подход № 2 будет использовать '\ n', если файл имеет много строк, это не должно быть ответом
Ninja 24.12.2017 12:22:53

Если вы испытываете приключения, вы можете смешать Scala и Java и получить следующее:

scala.io.Source.fromInputStream(is).mkString("")

Смешивание Java и Scala-кода и библиотек имеет свои преимущества.

Смотрите полное описание здесь: Идиоматический способ преобразования InputStream в строку в Scala

24
23.05.2017 12:18:29
В настоящее время просто это прекрасно работает:Source.fromInputStream(...).mkString
KajMagnus 30.07.2015 23:32:14

Вот более или менее ответ сампата, который немного очищен и представлен в виде функции:

String streamToString(InputStream in) throws IOException {
  StringBuilder out = new StringBuilder();
  BufferedReader br = new BufferedReader(new InputStreamReader(in));
  for(String line = br.readLine(); line != null; line = br.readLine()) 
    out.append(line);
  br.close();
  return out.toString();
}
26
12.09.2012 18:31:12

Это лучшее решение на чистой Java, которое идеально подходит для Android и любой другой JVM.

Это решение работает на удивление хорошо ... оно простое, быстрое и работает с маленькими и большими потоками одинаково !! (см. контрольный показатель выше. № 8 )

public String readFullyAsString(InputStream inputStream, String encoding)
        throws IOException {
    return readFully(inputStream).toString(encoding);
}

public byte[] readFullyAsBytes(InputStream inputStream)
        throws IOException {
    return readFully(inputStream).toByteArray();
}

private ByteArrayOutputStream readFully(InputStream inputStream)
        throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int length = 0;
    while ((length = inputStream.read(buffer)) != -1) {
        baos.write(buffer, 0, length);
    }
    return baos;
}
124
23.07.2019 20:38:45
Хорошо работает на Android по сравнению с другими ответами, которые работают только в корпоративной Java.
vortexwolf 14.01.2013 19:30:26
Сбой в Android с ошибкой OutOfMemory в строке «.write» каждый раз для коротких строк.
Adam 15.04.2013 17:18:54
Я добавил кодировку. как примечание: оригинальный метод readFully, который я имею в своем коде, не возвращает String, он возвращает byte [] для более универсальной функциональности. Реализация новой строки (...) с кодировкой является обязанностью пользователя, использующего API!
TacB0sS 18.08.2013 10:50:07
Краткое примечание: объем памяти, который это занимает, увеличивается 2*n, где n - размер потока в соответствии с ByteArrayInputStreamавтоматически растущей системой.
njzk2 18.04.2014 18:07:12
Излишне удваивает использование памяти, что очень ценно на мобильных устройствах. Вам лучше использовать InputStreamReader и добавить в StringReader, преобразование байта в символ будет выполнено на лету, а не навалом в конце.
Oliv 22.01.2015 08:33:58

Быстро и просто:

String result = (String)new ObjectInputStream( inputStream ).readObject();
-9
19.07.2012 17:33:39
Я получаюjava.io.StreamCorruptedException: invalid stream header
XXL 20.07.2012 11:13:33
ObjectInputStreamРечь идет о десериализации, и поток должен соблюдать протокол сериализации для работы, что не всегда верно в контексте этого вопроса.
Brice 3.04.2013 14:17:13
Объяснение будет в порядке.
Peter Mortensen 5.01.2019 10:37:24

Код ниже работал для меня.

URL url = MyClass.class.getResource("/" + configFileName);
BufferedInputStream bi = (BufferedInputStream) url.getContent();
byte[] buffer = new byte[bi.available() ];
int bytesRead = bi.read(buffer);
String out = new String(buffer);

Обратите внимание, что в соответствии с документацией Java этот available()метод может не работать, InputStreamно всегда работает BufferedInputStream. Если вы не хотите использовать available()метод, мы всегда можем использовать приведенный ниже код

URL url = MyClass.class.getResource("/" + configFileName);
BufferedInputStream bi = (BufferedInputStream) url.getContent();
File f = new File(url.getPath());
byte[] buffer = new byte[ (int) f.length()];
int bytesRead = bi.read(buffer);
String out = new String(buffer);

Я не уверен, будут ли какие-либо проблемы с кодировкой. Пожалуйста, прокомментируйте, если будут какие-либо проблемы с кодом.

4
16.12.2015 09:23:34
Весь смысл использования в InputStreamтом, что а) вы не знаете длину полного потока (который вываливается что - либо в зависимости от available) и б) поток может быть любым - файл, сокет - то внутреннее (который вываливается что-нибудь на основе File.size()). Относительно available: Это будет отрезать данные, если поток длиннее, чем размер буфера.
A.H. 24.07.2012 10:26:07
Существует предупреждение в Javadoc specificaly против того , как вы используете available(), и нет ничего в спецификации , read()которая гарантирует , что заполняет буфер: поэтому он возвращает число чтения.
user207421 24.02.2017 00:09:46

Вот как это сделать, используя только JDK, используя буферы байтового массива. Вот как IOUtils.copy()все методы commons-io работают. Вы можете заменить byte[]на, char[]если вы копируете с Readerвместо InputStream.

import java.io.ByteArrayOutputStream;
import java.io.InputStream;

...

InputStream is = ....
ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
byte[] buffer = new byte[8192];
int count = 0;
try {
  while ((count = is.read(buffer)) != -1) {
    baos.write(buffer, 0, count);
  }
}
finally {
  try {
    is.close();
  }
  catch (Exception ignore) {
  }
}

String charset = "UTF-8";
String inputStreamAsString = baos.toString(charset);
14
13.08.2014 04:30:09
Пожалуйста, дайте описание того, что вы пытаетесь достичь.
Ragunath Jawahar 2.11.2012 12:58:53

Не забудьте закрыть потоки в конце, если вы используете потоковые ридеры

private String readStream(InputStream iStream) throws IOException {
    //build a Stream Reader, it can read char by char
    InputStreamReader iStreamReader = new InputStreamReader(iStream);
    //build a buffered Reader, so that i can read whole line at once
    BufferedReader bReader = new BufferedReader(iStreamReader);
    String line = null;
    StringBuilder builder = new StringBuilder();
    while((line = bReader.readLine()) != null) {  //Read till end
        builder.append(line);
        builder.append("\n"); // append new line to preserve lines
    }
    bReader.close();         //close all opened stuff
    iStreamReader.close();
    //iStream.close(); //EDIT: Let the creator of the stream close it!
                       // some readers may auto close the inner stream
    return builder.toString();
}

РЕДАКТИРОВАТЬ: В JDK 7+, вы можете использовать конструкцию try-with-resources.

/**
 * Reads the stream into a string
 * @param iStream the input stream
 * @return the string read from the stream
 * @throws IOException when an IO error occurs
 */
private String readStream(InputStream iStream) throws IOException {

    //Buffered reader allows us to read line by line
    try (BufferedReader bReader =
                 new BufferedReader(new InputStreamReader(iStream))){
        StringBuilder builder = new StringBuilder();
        String line;
        while((line = bReader.readLine()) != null) {  //Read till end
            builder.append(line);
            builder.append("\n"); // append new line to preserve lines
        }
        return builder.toString();
    }
}
18
24.02.2017 19:28:51
Вы правы насчет закрытия потоков, однако ответственность за закрытие потоков обычно лежит на конструкторе потоков (завершите то, что вы начали). Таким образом, iStreamдействительно должен быть закрыт вызывающим, потому что создатель вызывающий iStream. Кроме того, закрытие потоков должно выполняться в finallyблоке или, что еще лучше, в операторе try-with-resources в Java 7. В вашем коде, когда readLine()бросает IOExceptionили builder.append()бросает OutOfMemoryError, потоки остаются открытыми.
Christian Hujer 31.01.2016 22:01:32

Вот самое элегантное решение на основе чистой Java (без библиотеки), которое я придумал после некоторых экспериментов:

public static String fromStream(InputStream in) throws IOException
{
    BufferedReader reader = new BufferedReader(new InputStreamReader(in));
    StringBuilder out = new StringBuilder();
    String newLine = System.getProperty("line.separator");
    String line;
    while ((line = reader.readLine()) != null) {
        out.append(line);
        out.append(newLine);
    }
    return out.toString();
}
63
7.12.2013 16:39:30
@TorbenKohlmeier, читатели и буферы не нужно закрывать. Предоставленное InputStreamдолжно быть закрыто звонящим.
Drew Noakes 3.06.2013 11:37:34
Не забудьте упомянуть, что в InputStreamReader есть более предпочтительный конструктор, который принимает CharSet.
jontejj 27.06.2013 12:36:57
почему люди продолжают использовать readLine? если вы не используете строки как таковые, что это хорошо (кроме того, что очень медленно?)
njzk2 18.04.2014 18:07:54
Не читать по строкам. Что если одна строка такая длинная, чтобы она не помещалась в кучу?
voho 7.08.2014 09:29:00
@voho, если одна строка такая длинная, то нет никакого способа выделить возвращаемое значение в любом случае, которое должно быть равно или больше по размеру этой строке. Если вы имеете дело с файлами такого большого размера, вы должны передавать их в потоковом режиме. Есть много вариантов использования для загрузки небольших текстовых файлов в память.
Drew Noakes 7.08.2014 12:16:27

Ну, вы можете запрограммировать это для себя ... Это не сложно ...

String Inputstream2String (InputStream is) throws IOException
    {
        final int PKG_SIZE = 1024;
        byte[] data = new byte [PKG_SIZE];
        StringBuilder buffer = new StringBuilder(PKG_SIZE * 10);
        int size;

        size = is.read(data, 0, data.length);
        while (size > 0)
        {
            String str = new String(data, 0, size);
            buffer.append(str);
            size = is.read(data, 0, data.length);
        }
        return buffer.toString();
    }
4
5.01.2019 10:38:08
Поскольку вы используете bufferпеременную локально без возможности совместного использования в нескольких потоках, вам следует рассмотреть возможность изменения ее типа на StringBuilder, чтобы избежать издержек (бесполезной) синхронизации.
user246645 8.11.2013 10:27:29
Это хороший момент, Алекс! Я считаю, что мы оба согласны, что этот метод не является многопоточным. Даже операции ввода потока не являются потокобезопасными.
Victor 8.11.2013 16:19:44
Если поток содержит символ UTF-8, который охватывает несколько строк, этот алгоритм может разрезать символ на две части, разрывая строку.
Vlad Lifliand 8.08.2014 22:47:45
@VladLifliand Как именно персонаж UTF-8 сможет охватить несколько строк? Это невозможно по определению. Вы, вероятно, имели в виду что-то еще.
Christian Hujer 31.01.2016 22:05:01
@ChristianHujer Он, вероятно, имеет в виду, buffersа не lines. Кодовые точки / символы UTF-8 могут быть многобайтовыми.
ᴠɪɴᴄᴇɴᴛ 17.03.2019 20:07:31
  InputStream IS=new URL("http://www.petrol.si/api/gas_prices.json").openStream();   

  ByteArrayOutputStream BAOS=new ByteArrayOutputStream();
  IOUtils.copy(IS, BAOS);
  String d= new String(BAOS.toByteArray(),"UTF-8");           

System.out.println(d);
-3
10.05.2013 17:25:15
См. Комментарий ChristofferHammarström в ответе HarryLime.
Reinstate Monica - M. Schröder 15.05.2013 15:23:32
В этом вопросе нет ничего, что отдаленно указывало бы на то, в какую кодировку конвертировать или что решение должно быть защищено от любой кодировки.
FK386 27.01.2017 16:06:06
Объяснение будет в порядке.
Peter Mortensen 5.01.2019 10:38:39
InputStreamReader i = new InputStreamReader(s);
BufferedReader str = new BufferedReader(i);
String msg = str.readLine();
System.out.println(msg);

Здесь s ваш InputStreamобъект, который будет преобразован вString

2
16.12.2015 09:24:30
это будет работать, если последние 2 строки вставлены в do-whileцикл?
KNU 7.04.2014 11:34:26
В вопросе о строках ничего нет.
user207421 24.02.2017 00:10:05

Ответ JDK 7/8, который закрывает поток и по-прежнему генерирует IOException:

StringBuilder build = new StringBuilder();
byte[] buf = new byte[1024];
int length;
try (InputStream is = getInputStream()) {
  while ((length = is.read(buf)) != -1) {
    build.append(new String(buf, 0, length));
  }
}
4
5.12.2013 17:53:07

Вы можете использовать Apache Commons.

В IOUtils вы можете найти метод toString с тремя полезными реализациями.

public static String toString(InputStream input) throws IOException {
        return toString(input, Charset.defaultCharset());
}

public static String toString(InputStream input) throws IOException {
        return toString(input, Charset.defaultCharset());
}

public static String toString(InputStream input, String encoding)
            throws IOException {
        return toString(input, Charsets.toCharset(encoding));
}
3
5.01.2019 10:51:02
В чем разница между первыми 2 методами?
rkosegi 3.10.2018 19:13:57

Попробуйте эти 4 утверждения ..

В соответствии с пунктом, напомнимым Фредом, не рекомендуется добавлять оператор Stringwith, +=поскольку каждый раз, когда новое charдобавляется к существующему, снова Stringсоздается новый Stringобъект и присваивается его адрес, в stто время как старый stобъект становится мусором.

public String convertStreamToString(InputStream is)
{
    int k;
    StringBuffer sb=new StringBuffer();
    while((k=fin.read()) != -1)
    {
        sb.append((char)k);
    }
    return sb.toString();
}

Не рекомендуется, но это также способ

public String convertStreamToString(InputStream is) { 
    int k;
    String st="";
    while((k=is.read()) != -1)
    {
        st+=(char)k;
    }
    return st;
}
3
16.12.2015 09:26:12
Конкатенация строк в цикле с +=оператором не очень хорошая идея. Лучше использовать StringBuilderили StringBuffer.
Fred 20.02.2014 15:24:34

Этот фрагмент был найден в \ sdk \ samples \ android-19 \ connectivity \ NetworkConnect \ NetworkConnectSample \ src \ main \ java \ com \ example \ android \ networkconnect \ MainActivity.java, который лицензирован по лицензии Apache, версия 2.0 и написан Google ,

/** Reads an InputStream and converts it to a String.
 * @param stream InputStream containing HTML from targeted site.
 * @param len Length of string that this method returns.
 * @return String concatenated according to len parameter.
 * @throws java.io.IOException
 * @throws java.io.UnsupportedEncodingException
 */
private String readIt(InputStream stream, int len) throws IOException, UnsupportedEncodingException {
    Reader reader = null;
    reader = new InputStreamReader(stream, "UTF-8");
    char[] buffer = new char[len];
    reader.read(buffer);
    return new String(buffer);
}
0
20.02.2014 15:28:59

Я написал класс, который делает именно это, поэтому я решил поделиться им со всеми. Иногда вы не хотите добавлять Apache Commons только для одной цели и хотите что-то более глупое, чем Scanner, который не проверяет содержимое.

Использование заключается в следующем

// Read from InputStream
String data = new ReaderSink(inputStream, Charset.forName("UTF-8")).drain();

// Read from File
data = new ReaderSink(file, Charset.forName("UTF-8")).drain();

// Drain input stream to console
new ReaderSink(inputStream, Charset.forName("UTF-8")).drainTo(System.out);

Вот код для ReaderSink:

import java.io.*;
import java.nio.charset.Charset;

/**
 * A simple sink class that drains a {@link Reader} to a {@link String} or
 * to a {@link Writer}.
 *
 * @author Ben Barkay
 * @version 2/20/2014
 */
public class ReaderSink {
    /**
     * The default buffer size to use if no buffer size was specified.
     */
    public static final int DEFAULT_BUFFER_SIZE = 1024;

    /**
     * The {@link Reader} that will be drained.
     */
    private final Reader in;

    /**
     * Constructs a new {@code ReaderSink} for the specified file and charset.
     * @param file      The file to read from.
     * @param charset   The charset to use.
     * @throws FileNotFoundException    If the file was not found on the filesystem.
     */
    public ReaderSink(File file, Charset charset) throws FileNotFoundException {
        this(new FileInputStream(file), charset);
    }

    /**
     * Constructs a new {@code ReaderSink} for the specified {@link InputStream}.
     * @param in        The {@link InputStream} to drain.
     * @param charset   The charset to use.
     */
    public ReaderSink(InputStream in, Charset charset) {
        this(new InputStreamReader(in, charset));
    }

    /**
     * Constructs a new {@code ReaderSink} for the specified {@link Reader}.
     * @param in    The reader to drain.
     */
    public ReaderSink(Reader in) {
        this.in = in;
    }

    /**
     * Drains the data from the underlying {@link Reader}, returning a {@link String} containing
     * all of the read information. This method will use {@link #DEFAULT_BUFFER_SIZE} for
     * its buffer size.
     * @return  A {@link String} containing all of the information that was read.
     */
    public String drain() throws IOException {
        return drain(DEFAULT_BUFFER_SIZE);
    }

    /**
     * Drains the data from the underlying {@link Reader}, returning a {@link String} containing
     * all of the read information.
     * @param bufferSize    The size of the buffer to use when reading.
     * @return  A {@link String} containing all of the information that was read.
     */
    public String drain(int bufferSize) throws IOException {
        StringWriter stringWriter = new StringWriter();
        drainTo(stringWriter, bufferSize);
        return stringWriter.toString();
    }

    /**
     * Drains the data from the underlying {@link Reader}, writing it to the
     * specified {@link Writer}. This method will use {@link #DEFAULT_BUFFER_SIZE} for
     * its buffer size.
     * @param out   The {@link Writer} to write to.
     */
    public void drainTo(Writer out) throws IOException {
        drainTo(out, DEFAULT_BUFFER_SIZE);
    }

    /**
     * Drains the data from the underlying {@link Reader}, writing it to the
     * specified {@link Writer}.
     * @param out           The {@link Writer} to write to.
     * @param bufferSize    The size of the buffer to use when reader.
     */
    public void drainTo(Writer out, int bufferSize) throws IOException {
        char[] buffer = new char[bufferSize];
        int read;
        while ((read = in.read(buffer)) > -1) {
            out.write(buffer, 0, read);
        }
    }
}
4
20.02.2014 17:46:18

Вот полный метод для преобразования InputStreamв Stringбез использования какой - либо сторонней библиотеки. Используйте StringBuilderдля однопоточной среды, иначе используйте StringBuffer.

public static String getString( InputStream is) throws IOException {
    int ch;
    StringBuilder sb = new StringBuilder();
    while((ch = is.read()) != -1)
        sb.append((char)ch);
    return sb.toString();
}
15
16.12.2015 09:20:36
В этом методе кодировка не применяется. Допустим, данные, полученные из InputStream, кодируются с использованием UTF-8, и результат будет неправильным. Чтобы это исправить, вы можете использовать in = new InputStreamReader(inputStream)и (char)in.read().
Frederic Leitenberger 4.11.2014 12:21:46
и память неэффективна; Мне кажется, я пытался использовать это раньше на большом входе, и
gengkev 18.11.2014 03:37:29
Есть другой аналогичный ответ, который использует буфер char [], более эффективен и заботится о charset.
Guillaume Perrot 27.04.2015 21:39:42

У меня был доступен log4j, поэтому я смог использовать org.apache.log4j.lf5.util.StreamUtils.getBytes, чтобы получить байты, которые я смог преобразовать в строку с помощью String ctor

String result = new String(StreamUtils.getBytes(inputStream));
-1
12.05.2014 18:04:39
-1. То, что что-то доступно, не означает, что его следует использовать. Когда вы переключаете провайдера регистрации, вам придется заменить это. Кроме того, похоже, что он внутренний и не должен использоваться вне log4j.
robinst 14.08.2014 05:51:51

Это хорошо, потому что:

  • Это безопасно обрабатывает Charset.
  • Вы контролируете размер буфера чтения.
  • Вы можете указать длину компоновщика, и она не должна быть точной.
  • Свободен от библиотечных зависимостей.
  • Для Java 7 или выше.

Как это сделать?

public static String convertStreamToString(InputStream is) throws IOException {
   StringBuilder sb = new StringBuilder(2048); // Define a size if you have an idea of it.
   char[] read = new char[128]; // Your buffer size.
   try (InputStreamReader ir = new InputStreamReader(is, StandardCharsets.UTF_8)) {
     for (int i; -1 != (i = ir.read(read)); sb.append(read, 0, i));
   }
   return sb.toString();
}

Для JDK 9

public static String inputStreamString(InputStream inputStream) throws IOException {
    try (inputStream) {
        return new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
    }
}
18
20.06.2019 05:57:28
На catch (Throwable)самом деле не должно быть пустым, если это рабочий код.
Christian Hujer 31.01.2016 22:03:01
что положить в этот броский оператор?
alex 18.06.2019 14:13:01

Я бы использовал некоторые трюки с Java 8.

public static String streamToString(final InputStream inputStream) throws Exception {
    // buffering optional
    try
    (
        final BufferedReader br
           = new BufferedReader(new InputStreamReader(inputStream))
    ) {
        // parallel optional
        return br.lines().parallel().collect(Collectors.joining("\n"));
    } catch (final IOException e) {
        throw new RuntimeException(e);
        // whatever.
    }
}

По сути, такой же, как некоторые другие ответы, за исключением более кратких.

41
15.07.2015 11:03:54
Будет ли это return nullкогда-либо называться? Либо br.lines...возврат, либо исключение.
Holloway 23.07.2014 09:13:37
@ Khaled A Khunaifer: да, довольно уверен ... может быть, вы должны посмотреть здесь: docs.oracle.com/javase/tutorial/essential/exceptions/… . То, что вы ошибочно отредактировали, это утверждение "попробуй с ресурсами".
jamp 5.02.2015 13:13:58
Почему вы звоните parallel()в потоке?
robinst 20.04.2015 05:13:20
Это не привело бы к честной копии данных, если бы исходный поток использовал окончания строк Windows, поскольку все в \r\nконечном итоге было бы преобразовано в \n...
Lucas 13.08.2015 18:30:50
Вы можете использовать, System.lineSeparator()чтобы использовать соответствующий зависимый от платформы конец строки.
Steve K 28.09.2015 23:25:18

Это ответ, адаптированный из org.apache.commons.io.IOUtils исходного кода , для тех, кто хочет иметь реализацию apache, но не хочет всей библиотеки.

private static final int BUFFER_SIZE = 4 * 1024;

public static String inputStreamToString(InputStream inputStream, String charsetName)
        throws IOException {
    StringBuilder builder = new StringBuilder();
    InputStreamReader reader = new InputStreamReader(inputStream, charsetName);
    char[] buffer = new char[BUFFER_SIZE];
    int length;
    while ((length = reader.read(buffer)) != -1) {
        builder.append(buffer, 0, length);
    }
    return builder.toString();
}
18
10.10.2015 04:37:28