io to android - Как читать / конвертировать InputStream в String в Java?





15 Answers

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

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

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

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

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

EDITED: благодаря предложению Patrick , эта функция стала более надежной при обработке пустого потока ввода. Еще одно редактирование: смешение try / catch, путь Патрика более лаконичен.

how get from

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

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

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

public String convertStreamToString(InputStream is) { 
    // ???
}



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

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

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

Также см .: ( Docs )




Как насчет этого?

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();



Это мое чистое решение для Java и Android, хорошо работает ...

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;
}



Вот самое изящное, чисто-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();
}



Я бы использовал некоторые трюки 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.
    }
}

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




Чистое решение Java с использованием Stream s работает с Java 8.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.stream.Collectors;

// ...
public static String inputStreamToString(InputStream is) throws IOException {
    try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
        return br.lines().collect(Collectors.joining(System.lineSeparator()));
    }
}

Как упоминалось Кристоффером Хаммарстремом ниже другого ответа, более безопасно явно указывать Charset . Т.е. конструктор InputStreamReader может быть изменен следующим образом:

new InputStreamReader(is, Charset.forName("UTF-8"))



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

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();
}



Если вы не можете использовать 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);
    }
}

или, если вы хотите получить необработанную скорость, я бы предложил вариант, предложенный Paul De Vrieze (который избегает использования 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);
    }
}



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

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();
}

EDIT: в 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();
    }
}



Вот как это сделать, используя только JDK с использованием буферов массива байтов. Это на самом деле то, как все коммерческие IOUtils.copy()методы все работают. Вы можете заменить 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);



Пользователи Kotlin просто делают:

println(InputStreamReader(is).readText())

в то время как

readText()

это встроенный метод расширения стандартной библиотеки Kotlin.




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

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

Для чего?

public static String convertStreamToString(InputStream is) {
   if (is == null) return null;
   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));
   } catch (Throwable t) {}
   return sb.toString();
}



Самый простой способ в JDK состоит в следующем: snipplets кода.

String convertToString(InputStream in){
    String resource = new Scanner(in).useDelimiter("\\Z").next();
    return resource;
}



Примечание. Это, вероятно, не очень хорошая идея. Этот метод использует рекурсию:

public String read (InputStream is) {
    byte next = is.read();
    return next == -1 ? "" : next + read(is); // Recursive part: reads next byte recursively
}

Пожалуйста, не уменьшайте это только потому, что это плохой выбор; это было главным образом творческим :)




Related