Как мне прочитать / преобразовать InputStream в строку в Java? - PullRequest
3675 голосов
/ 21 ноября 2008

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


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

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

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

Ответы [ 60 ]

3 голосов
/ 07 февраля 2014

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

В соответствии с точкой, вызванной Фредом, не рекомендуется добавлять String с оператором +=, поскольку каждый раз, когда новый 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 голосов
/ 07 апреля 2018

с Окио:

String result = Okio.buffer(Okio.source(inputStream)).readUtf8();
2 голосов
/ 30 мая 2013
InputStreamReader i = new InputStreamReader(s);
BufferedReader str = new BufferedReader(i);
String msg = str.readLine();
System.out.println(msg);

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

2 голосов
/ 11 сентября 2014

Следующее не относится к первоначальному вопросу, а скорее к некоторым ответам.

Несколько ответов предлагают петли вида

String line = null;
while((line = reader.readLine()) != null) {
  // ...
}

или

for(String line = reader.readLine(); line != null; line = reader.readLine()) {
    // ...
}

Первая форма загрязняет пространство имен охватывающей области, объявляя переменную «read» во вложенной области, которая не будет использоваться ни для чего вне цикла for. Вторая форма дублирует вызов readline ().

Вот гораздо более понятный способ написания такого рода цикла в Java. Оказывается, первое предложение в цикле for не требует фактического значения инициализатора. Это сохраняет область действия переменной "line" внутри тела цикла for. Гораздо элегантнее! Я нигде не видел, чтобы кто-нибудь использовал эту форму (я случайно обнаружил ее один день назад), но я использую ее все время.

for (String line; (line = reader.readLine()) != null; ) {
    //...
}
2 голосов
/ 08 ноября 2018

ISO-8859-1

Вот очень эффективный способ сделать это, если вы знаете, что кодировка вашего входного потока - ISO-8859-1 или ASCII. Он (1) избегает ненужной синхронизации, присутствующей во внутреннем StringBuffer StringWriter, (2) избегает накладных расходов InputStreamReader и (3) минимизирует количество раз char внутреннего массива StringBuilder должен быть скопирован.

public static String iso_8859_1(InputStream is) throws IOException {
    StringBuilder chars = new StringBuilder(Math.max(is.available(), 4096));
    byte[] buffer = new byte[4096];
    int n;
    while ((n = is.read(buffer)) != -1) {
        for (int i = 0; i < n; i++) {
            chars.append((char)(buffer[i] & 0xFF));
        }
    }
    return chars.toString();
}

UTF-8

Та же общая стратегия может использоваться для потока, закодированного с помощью UTF-8:

public static String utf8(InputStream is) throws IOException {
    StringBuilder chars = new StringBuilder(Math.max(is.available(), 4096));
    byte[] buffer = new byte[4096];
    int n;
    int state = 0;
    while ((n = is.read(buffer)) != -1) {
        for (int i = 0; i < n; i++) {
            if ((state = nextStateUtf8(state, buffer[i])) >= 0) {
                chars.appendCodePoint(state);
            } else if (state == -1) { //error
                state = 0;
                chars.append('\uFFFD'); //replacement char
            }
        }
    }
    return chars.toString();
}

где функция nextStateUtf8() определяется следующим образом:

/**
 * Returns the next UTF-8 state given the next byte of input and the current state.
 * If the input byte is the last byte in a valid UTF-8 byte sequence,
 * the returned state will be the corresponding unicode character (in the range of 0 through 0x10FFFF).
 * Otherwise, a negative integer is returned. A state of -1 is returned whenever an
 * invalid UTF-8 byte sequence is detected.
 */
static int nextStateUtf8(int currentState, byte nextByte) {
    switch (currentState & 0xF0000000) {
        case 0:
            if ((nextByte & 0x80) == 0) { //0 trailing bytes (ASCII)
                return nextByte;
            } else if ((nextByte & 0xE0) == 0xC0) { //1 trailing byte
                if (nextByte == (byte) 0xC0 || nextByte == (byte) 0xC1) { //0xCO & 0xC1 are overlong
                    return -1;
                } else {
                    return nextByte & 0xC000001F;
                }
            } else if ((nextByte & 0xF0) == 0xE0) { //2 trailing bytes
                if (nextByte == (byte) 0xE0) { //possibly overlong
                    return nextByte & 0xA000000F;
                } else if (nextByte == (byte) 0xED) { //possibly surrogate
                    return nextByte & 0xB000000F;
                } else {
                    return nextByte & 0x9000000F;
                }
            } else if ((nextByte & 0xFC) == 0xF0) { //3 trailing bytes
                if (nextByte == (byte) 0xF0) { //possibly overlong
                    return nextByte & 0x80000007;
                } else {
                    return nextByte & 0xE0000007;
                }
            } else if (nextByte == (byte) 0xF4) { //3 trailing bytes, possibly undefined
                return nextByte & 0xD0000007;
            } else {
                return -1;
            }
        case 0xE0000000: //3rd-to-last continuation byte
            return (nextByte & 0xC0) == 0x80 ? currentState << 6 | nextByte & 0x9000003F : -1;
        case 0x80000000: //3rd-to-last continuation byte, check overlong
            return (nextByte & 0xE0) == 0xA0 || (nextByte & 0xF0) == 0x90 ? currentState << 6 | nextByte & 0x9000003F : -1;
        case 0xD0000000: //3rd-to-last continuation byte, check undefined
            return (nextByte & 0xF0) == 0x80 ? currentState << 6 | nextByte & 0x9000003F : -1;
        case 0x90000000: //2nd-to-last continuation byte
            return (nextByte & 0xC0) == 0x80 ? currentState << 6 | nextByte & 0xC000003F : -1;
        case 0xA0000000: //2nd-to-last continuation byte, check overlong
            return (nextByte & 0xE0) == 0xA0 ? currentState << 6 | nextByte & 0xC000003F : -1;
        case 0xB0000000: //2nd-to-last continuation byte, check surrogate
            return (nextByte & 0xE0) == 0x80 ? currentState << 6 | nextByte & 0xC000003F : -1;
        case 0xC0000000: //last continuation byte
            return (nextByte & 0xC0) == 0x80 ? currentState << 6 | nextByte & 0x3F : -1;
        default:
            return -1;
    }
}

Автоопределение кодировки

Если ваш входной поток был закодирован с использованием ASCII или ISO-8859-1 или UTF-8, но вы не уверены, какой, мы можем использовать метод, аналогичный последнему, но с дополнительным компонентом обнаружения кодирования для автоопределение кодировки перед возвратом строки.

public static String autoDetect(InputStream is) throws IOException {
    StringBuilder chars = new StringBuilder(Math.max(is.available(), 4096));
    byte[] buffer = new byte[4096];
    int n;
    int state = 0;
    boolean ascii = true;
    while ((n = is.read(buffer)) != -1) {
        for (int i = 0; i < n; i++) {
            if ((state = nextStateUtf8(state, buffer[i])) > 0x7F)
                ascii = false;
            chars.append((char)(buffer[i] & 0xFF));
        }
    }

    if (ascii || state < 0) { //probably not UTF-8
        return chars.toString();
    }
    //probably UTF-8
    int pos = 0;
    char[] charBuf = new char[2];
    for (int i = 0, len = chars.length(); i < len; i++) {
        if ((state = nextStateUtf8(state, (byte)chars.charAt(i))) >= 0) {
            boolean hi = Character.toChars(state, charBuf, 0) == 2;
            chars.setCharAt(pos++, charBuf[0]);
            if (hi) {
                chars.setCharAt(pos++, charBuf[1]);
            }
        }
    }
    return chars.substring(0, pos);
}

Если ваш входной поток имеет кодировку, которая не является ни ISO-8859-1, ни ASCII, ни UTF-8, то я откладываю на другие ответы, уже присутствующие.

2 голосов
/ 06 августа 2017

Вы можете использовать Cactoos :

String text = new TextOf(inputStream).asString();

Кодировка UTF-8 используется по умолчанию. Если вам нужен еще один:

String text = new TextOf(inputStream, "UTF-16").asString();
1 голос
/ 17 ноября 2015

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

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

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

1 голос
/ 28 июня 2018

Я создал этот код, и он работает. Не требуется никаких внешних плагинов.

Есть преобразовать строку в поток и поток в строку ...

import java.io.ByteArrayInputStream;
import java.io.InputStream;

public class STRINGTOSTREAM {

    public static void main(String[] args)
    {
        String text = "Hello Bhola..!\nMy Name Is Kishan ";

        InputStream strm = new ByteArrayInputStream(text.getBytes());    // Convert String to Stream

        String data = streamTostring(strm);

        System.out.println(data);
    }

    static String streamTostring(InputStream stream)
    {
        String data = "";

        try
        {
            StringBuilder stringbuld = new StringBuilder();
            int i;
            while ((i=stream.read())!=-1)
            {
                stringbuld.append((char)i);
            }
            data = stringbuld.toString();
        }
        catch(Exception e)
        {
            data = "No data Streamed.";
        }
        return data;
    }
1 голос
/ 20 февраля 2014

Этот фрагмент был найден в \ sdk \ samples \ android-19 \ connectivity \ NetworkConnect \ NetworkConnectSample \ src \ main \ java \ com \ example \ android \ networkconnect \ MainActivity.java, который распространяется по лицензии Apache License, версии 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);
}
1 голос
/ 20 января 2018

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

String theString = IOUtils.toString(inputStream, encoding);
...