如何在Java中读取/转换输入流到字符串中?InputStream into a String

How do I read / convert an InputStream into a String in Java?

如果您有一个java.io.InputStream对象,您应该如何处理该对象并生成一个String

假设我有一个包含文本数据的InputStream,我想将它转换为String,这样我就可以将它写入日志文件。

InputStream转换成String最简单的方法是什么?

1
2
3
public String convertStreamToString(InputStream is) {
    // ???
}


一个很好的方法是使用ApacheCommons IOUtilsInputStream复制到StringWriter中……类似的东西

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

甚至

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

或者,如果不想混合流和作者,可以使用ByteArrayOutputStream


这是一种只使用标准Java库的方法(注意,流没有关闭,您的里程可能会有所不同)。

1
2
3
4
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")。

帽子的尖端也属于雅各布,他曾经指给我看那篇文章。


Summarize other answers I found 11 main ways to do this(see below).我写了一些表演测试(见下面的结果):

Ways to convert an inputstream to a string:

  • 使用IOUtils.toString

    1
    String result = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
  • 使用EDOCX1&6

    1
    2
    String result = CharStreams.toString(new InputStreamReader(
          inputStream, Charsets.UTF_8));
  • 使用Scanner

    1
    2
    Scanner s = new Scanner(inputStream).useDelimiter("\\A");
    String result = s.hasNext() ? s.next() :"";
  • Using Stream API(Java 8).警告:这个解决方案将不同的线路断裂(如

    )转化为

    1
    2
    3
    String result = new BufferedReader(new InputStreamReader(inputStream))
      .lines().collect(Collectors.joining("
    "
    ));
  • 使用平行流API(Java 8).警告:这个解决方案将不同的线路断裂(如

    )转化为

    1
    2
    3
    String result = new BufferedReader(new InputStreamReader(inputStream)).lines()
       .parallel().collect(Collectors.joining("
    "
    ));
  • 使用InputStreamReaderStringBuilder

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    final int bufferSize = 1024;
    final char[] buffer = new char[bufferSize];
    final StringBuilder out = new StringBuilder();
    Reader in = new InputStreamReader(inputStream,"UTF-8");
    for (; ; ) {
        int rsz = in.read(buffer, 0, buffer.length);
        if (rsz < 0)
            break;
        out.append(buffer, 0, rsz);
    }
    return out.toString();
  • 使用StringWriterIOUtils.copy(Apache Commons)

    1
    2
    3
    StringWriter writer = new StringWriter();
    IOUtils.copy(inputStream, writer,"UTF-8");
    return writer.toString();
  • 使用ByteArrayOutputStreaminputStream.read(JDK)

    1
    2
    3
    4
    5
    6
    7
    8
    ByteArrayOutputStream result = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int length;
    while ((length = inputStream.read(buffer)) != -1) {
        result.write(buffer, 0, length);
    }
    // StandardCharsets.UTF_8.name() > JDK 7
    return result.toString("UTF-8");
  • 使用BufferedReader警告:这个解决方案将不同的线路断裂(如EDOCX1〕〔19〕转换为line.separator系统性能(例如,在窗口到「r」)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    String newLine = System.getProperty("line.separator");
    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
    StringBuilder result = new StringBuilder();
    boolean flag = false;
    for (String line; (line = reader.readLine()) != null; ) {
        result.append(flag? newLine:"").append(line);
        flag = true;
    }
    return result.toString();
  • 使用BufferedInputStreamByteArrayOutputStream(JDK)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    BufferedInputStream bis = new BufferedInputStream(inputStream);
    ByteArrayOutputStream buf = new ByteArrayOutputStream();
    int result = bis.read();
    while(result != -1) {
        buf.write((byte) result);
        result = bis.read();
    }
    // StandardCharsets.UTF_8.name() > JDK 7
    return buf.toString("UTF-8");
  • 使用inputStream.read()StringBuilder(JDK)。警告:这一解决方案与Unicode有问题,以俄罗斯文本为例(正确的工作只与非Unicode文本相关)

    1
    2
    3
    4
    5
    6
    int ch;
    StringBuilder sb = new StringBuilder();
    while((ch = inputStream.read()) != -1)
        sb.append((char)ch);
    reset();
    return sb.toString();
  • 警告:

  • 解决方案4、5和9将不同的线路切断为一条。

  • 解决方案11无法用统一文本正确地工作

  • 性能测试

    String(长度=175),URL in Github(Mode=平均时间,System=Linux,score 1343 is the best):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
                  Benchmark                         Mode  Cnt   Score   Error  Units
     8. ByteArrayOutputStream and read (JDK)        avgt   10   1,343 ± 0,028  us/op
     6. InputStreamReader and StringBuilder (JDK)   avgt   10   6,980 ± 0,404  us/op
    10. BufferedInputStream, ByteArrayOutputStream  avgt   10   7,437 ± 0,735  us/op
    11. InputStream.read() and StringBuilder (JDK)  avgt   10   8,977 ± 0,328  us/op
     7. StringWriter and IOUtils.copy (Apache)      avgt   10  10,613 ± 0,599  us/op
     1. IOUtils.toString (Apache Utils)             avgt   10  10,605 ± 0,527  us/op
     3. Scanner (JDK)                               avgt   10  12,083 ± 0,293  us/op
     2. CharStreams (guava)                         avgt   10  12,999 ± 0,514  us/op
     4. Stream Api (Java 8)                         avgt   10  15,811 ± 0,605  us/op
     9. BufferedReader (JDK)                        avgt   10  16,038 ± 0,711  us/op
     5. parallel Stream Api (Java 8)                avgt   10  21,544 ± 0,583  us/op

    Github(Mode=平均时间,System=Linux,score 2007 715 is the best):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
                   Benchmark                        Mode  Cnt   Score        Error  Units
     8. ByteArrayOutputStream and read (JDK)        avgt   10   200,715 ±   18,103  us/op
     1. IOUtils.toString (Apache Utils)             avgt   10   300,019 ±    8,751  us/op
     6. InputStreamReader and StringBuilder (JDK)   avgt   10   347,616 ±  130,348  us/op
     7. StringWriter and IOUtils.copy (Apache)      avgt   10   352,791 ±  105,337  us/op
     2. CharStreams (guava)                         avgt   10   420,137 ±   59,877  us/op
     9. BufferedReader (JDK)                        avgt   10   632,028 ±   17,002  us/op
     5. parallel Stream Api (Java 8)                avgt   10   662,999 ±   46,199  us/op
     4. Stream Api (Java 8)                         avgt   10   701,269 ±   82,296  us/op
    10. BufferedInputStream, ByteArrayOutputStream  avgt   10   740,837 ±    5,613  us/op
     3. Scanner (JDK)                               avgt   10   751,417 ±   62,026  us/op
    11. InputStream.read() and StringBuilder (JDK)  avgt   10  2919,350 ± 1101,942  us/op

    视窗7系统输入流长度的性能测试MGX1〔0〕

    性能测试(平均时间)取决于窗口7系统的输入流长度:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     length  182    546     1092    3276    9828    29484   58968

     test8  0.38    0.938   1.868   4.448   13.412  36.459  72.708
     test4  2.362   3.609   5.573   12.769  40.74   81.415  159.864
     test5  3.881   5.075   6.904   14.123  50.258  129.937 166.162
     test9  2.237   3.493   5.422   11.977  45.98   89.336  177.39
     test6  1.261   2.12    4.38    10.698  31.821  86.106  186.636
     test7  1.601   2.391   3.646   8.367   38.196  110.221 211.016
     test1  1.529   2.381   3.527   8.411   40.551  105.16  212.573
     test3  3.035   3.934   8.606   20.858  61.571  118.744 235.428
     test2  3.136   6.238   10.508  33.48   43.532  118.044 239.481
     test10 1.593   4.736   7.527   20.557  59.856  162.907 323.147
     test11 3.913   11.506  23.26   68.644  207.591 600.444 1211.545


    Apache Commons允许:

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

    当然,除了UTF-8,您还可以选择其他字符编码。

    另请参见:(文档)


    考虑到文件,首先应该得到一个java.io.Reader实例。然后可以读取并添加到StringBuilder(如果不在多个线程中访问它,我们不需要StringBufferStringBuilder更快)。这里的诀窍是我们在块中工作,因此不需要其他缓冲流。块大小是为运行时性能优化而参数化的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    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();
    }


    用途:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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();


    如果您使用google collections/guava,可以执行以下操作:

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

    注意,InputStreamReader的第二个参数(即charset.utf_8)是不必要的,但是如果您知道(应该是哪个)编码,通常最好指定它。


    这是我的纯Java和Android解决方案,它工作得很好…

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    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(无库)解决方案:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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();
    }


    用途:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    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();
    }


    For completeness here is Java 9 solution:

    1
    2
    3
    public static String toString(InputStream input) throws IOException {
        return new String(input.readAllBytes(), StandardCharsets.UTF_8);
    }

    目前在JDK 9主编码中,所以在释放时会出现。你现在可以用JDK 9突击步枪大楼试试看。


    我在这里做了14个不同答案的基准(抱歉没有提供学分,但有太多的重复)。

    结果非常令人惊讶。结果表明,ApacheIOutils是最慢的,ByteArrayOutputStream是最快的解决方案:

    因此,首先是最好的方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public String inputStreamToString(InputStream inputStream) throws IOException {
        try(ByteArrayOutputStream result = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[1024];
            int length;
            while ((length = inputStream.read(buffer)) != -1) {
                result.write(buffer, 0, length);
            }

            return result.toString(UTF_8);
        }
    }

    20个周期内20 MB随机字节的基准测试结果

    时间(毫秒)

    • BytearrayOutputStream测试:194
    • 尼罗河:198
    • JAVA9ISTRANSFERTO:201号
    • java9isreadallbytes:205个
    • BufferedInputStreamVsBytearrayOutputStream:314
    • ApacheStringWriter2:574
    • 瓜瓦卡河:589
    • 扫描仪读卡器非文本测试:614
    • 扫描仪读卡器:633
    • 阿帕切斯特林格:1544
    • streamapi:错误
    • ParallelStreamAPI:错误
    • BufferReaderTest:错误
    • InputStreamAndStringBuilder:错误

    基准源代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    import com.google.common.io.CharStreams;
    import org.apache.commons.io.IOUtils;

    import java.io.*;
    import java.nio.ByteBuffer;
    import java.nio.channels.Channels;
    import java.nio.channels.ReadableByteChannel;
    import java.nio.channels.WritableByteChannel;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Random;
    import java.util.stream.Collectors;

    /**
     * Created by Ilya Gazman on 2/13/18.
     */

    public class InputStreamToString {


        private static final String UTF_8 ="UTF-8";

        public static void main(String... args) {
            log("App started");
            byte[] bytes = new byte[1024 * 1024];
            new Random().nextBytes(bytes);
            log("Stream is ready
    "
    );

            try {
                test(bytes);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        private static void test(byte[] bytes) throws IOException {
            List<Stringify> tests = Arrays.asList(
                    new ApacheStringWriter(),
                    new ApacheStringWriter2(),
                    new NioStream(),
                    new ScannerReader(),
                    new ScannerReaderNoNextTest(),
                    new GuavaCharStreams(),
                    new StreamApi(),
                    new ParallelStreamApi(),
                    new ByteArrayOutputStreamTest(),
                    new BufferReaderTest(),
                    new BufferedInputStreamVsByteArrayOutputStream(),
                    new InputStreamAndStringBuilder(),
                    new Java9ISTransferTo(),
                    new Java9ISReadAllBytes()
            );

            String solution = new String(bytes,"UTF-8");

            for (Stringify test : tests) {
                try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes)) {
                    String s = test.inputStreamToString(inputStream);
                    if (!s.equals(solution)) {
                        log(test.name() +": Error");
                        continue;
                    }
                }
                long startTime = System.currentTimeMillis();
                for (int i = 0; i < 20; i++) {
                    try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes)) {
                        test.inputStreamToString(inputStream);
                    }
                }
                log(test.name() +":" + (System.currentTimeMillis() - startTime));
            }
        }

        private static void log(String message) {
            System.out.println(message);
        }

        interface Stringify {
            String inputStreamToString(InputStream inputStream) throws IOException;

            default String name() {
                return this.getClass().getSimpleName();
            }
        }

        static class ApacheStringWriter implements Stringify {

            @Override
            public String inputStreamToString(InputStream inputStream) throws IOException {
                StringWriter writer = new StringWriter();
                IOUtils.copy(inputStream, writer, UTF_8);
                return writer.toString();
            }
        }

        static class ApacheStringWriter2 implements Stringify {

            @Override
            public String inputStreamToString(InputStream inputStream) throws IOException {
                return IOUtils.toString(inputStream, UTF_8);
            }
        }

        static class NioStream implements Stringify {

            @Override
            public String inputStreamToString(InputStream in) throws IOException {
                ReadableByteChannel channel = Channels.newChannel(in);
                ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 16);
                ByteArrayOutputStream bout = new ByteArrayOutputStream();
                WritableByteChannel outChannel = Channels.newChannel(bout);
                while (channel.read(byteBuffer) > 0 || byteBuffer.position() > 0) {
                    byteBuffer.flip();  //make buffer ready for write
                    outChannel.write(byteBuffer);
                    byteBuffer.compact(); //make buffer ready for reading
                }
                channel.close();
                outChannel.close();
                return bout.toString(UTF_8);
            }
        }

        static class ScannerReader implements Stringify {

            @Override
            public String inputStreamToString(InputStream is) throws IOException {
                java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
                return s.hasNext() ? s.next() :"";
            }
        }

        static class ScannerReaderNoNextTest implements Stringify {

            @Override
            public String inputStreamToString(InputStream is) throws IOException {
                java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
                return s.next();
            }
        }

        static class GuavaCharStreams implements Stringify {

            @Override
            public String inputStreamToString(InputStream is) throws IOException {
                return CharStreams.toString(new InputStreamReader(
                        is, UTF_8));
            }
        }

        static class StreamApi implements Stringify {

            @Override
            public String inputStreamToString(InputStream inputStream) throws IOException {
                return new BufferedReader(new InputStreamReader(inputStream))
                        .lines().collect(Collectors.joining("
    "
    ));
            }
        }

        static class ParallelStreamApi implements Stringify {

            @Override
            public String inputStreamToString(InputStream inputStream) throws IOException {
                return new BufferedReader(new InputStreamReader(inputStream)).lines()
                        .parallel().collect(Collectors.joining("
    "
    ));
            }
        }

        static class ByteArrayOutputStreamTest implements Stringify {

            @Override
            public String inputStreamToString(InputStream inputStream) throws IOException {
                try(ByteArrayOutputStream result = new ByteArrayOutputStream()) {
                    byte[] buffer = new byte[1024];
                    int length;
                    while ((length = inputStream.read(buffer)) != -1) {
                        result.write(buffer, 0, length);
                    }

                    return result.toString(UTF_8);
                }
            }
        }

        static class BufferReaderTest implements Stringify {

            @Override
            public String inputStreamToString(InputStream inputStream) throws IOException {
                String newLine = System.getProperty("line.separator");
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                StringBuilder result = new StringBuilder(UTF_8);
                String line;
                boolean flag = false;
                while ((line = reader.readLine()) != null) {
                    result.append(flag ? newLine :"").append(line);
                    flag = true;
                }
                return result.toString();
            }
        }

        static class BufferedInputStreamVsByteArrayOutputStream implements Stringify {

            @Override
            public String inputStreamToString(InputStream inputStream) throws IOException {
                BufferedInputStream bis = new BufferedInputStream(inputStream);
                ByteArrayOutputStream buf = new ByteArrayOutputStream();
                int result = bis.read();
                while (result != -1) {
                    buf.write((byte) result);
                    result = bis.read();
                }

                return buf.toString(UTF_8);
            }
        }

        static class InputStreamAndStringBuilder implements Stringify {

            @Override
            public String inputStreamToString(InputStream inputStream) throws IOException {
                int ch;
                StringBuilder sb = new StringBuilder(UTF_8);
                while ((ch = inputStream.read()) != -1)
                    sb.append((char) ch);
                return sb.toString();
            }
        }

        static class Java9ISTransferTo implements Stringify {

            @Override
            public String inputStreamToString(InputStream inputStream) throws IOException {
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                inputStream.transferTo(bos);
                return bos.toString(UTF_8);
            }
        }

        static class Java9ISReadAllBytes implements Stringify {

            @Override
            public String inputStreamToString(InputStream inputStream) throws IOException {
                return new String(inputStream.readAllBytes(), UTF_8);
            }
        }

    }

    我会使用一些Java 8技巧。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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("
    "
    ));
        } catch (final IOException e) {
            throw new RuntimeException(e);
            // whatever.
        }
    }

    基本上和其他答案一样,只是更简洁。


    我做了一些计时测试,因为时间总是很重要的。

    我试图以3种不同的方式将响应变成字符串。(如下所示)
    为了可读性,我省略了try/catch块。

    为了给出上下文,这是所有3种方法的前面代码:

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

    1)

    1
     response = method.getResponseBodyAsString();

    2)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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)

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

    因此,在对具有相同请求/响应数据的每个方法运行500个测试之后,下面是数字。再一次,这些是我的发现,你的发现可能不完全相同,但我写这篇文章是为了给其他人一些关于这些方法效率差异的指示。

    排名:
    进近1
    接近3-2.6%慢于1
    接近2-比1慢4.3%

    这些方法中的任何一种都是获取响应并从中创建字符串的适当解决方案。


    纯爪哇溶液使用流体,自爪哇8号以来的作品。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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()));
        }
    }

    克里斯托弗·哈马斯特说谎?另一个答案是,具体地说,这辆车是安全的。I.E.The inputstreamreader constructor can be changes as follows:

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


    这里或多或少是sampath的答案,清理了一点并表示为一个函数:

    1
    2
    3
    4
    5
    6
    7
    8
    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();
    }

    如果你觉得冒险,你可以混合斯卡拉和Java,并最终与此:

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

    将Java和Scala代码和库混合有好处。

    请参阅此处的完整描述:将inputstream转换为scala中字符串的惯用方法


    如果不能使用commons io(fileutils/ioutils/copyutils),下面是一个使用bufferedreader逐行读取文件的示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    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('
    '
    );
                }
            }
            catch (IOException ignore) { }

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

    或者,如果您想要原始速度,我建议对paul de vrieze的建议进行更改(这样可以避免使用StringWriter(内部使用StringBuffer)):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    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);
        }
    }


    这是一个改编自org.apache.commons.io.IOUtils源代码的答案,适用于那些希望使用Apache实现但不希望使用整个库的用户。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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();
    }

    如果使用流读取器,请确保在结束时关闭流

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    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("
    "
    ); // 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();
    }

    编辑:在JDK7+上,可以使用Try with Resources构造。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    /**
     * 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("
    "
    ); // append new line to preserve lines
            }
            return builder.toString();
        }
    }


    这里是在不使用任何第三方库的情况下将InputStream转换为String的完整方法。单线程环境使用StringBuilder,否则使用StringBuffer

    1
    2
    3
    4
    5
    6
    7
    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();
    }


    下面介绍如何仅使用JDK使用字节数组缓冲区。这实际上就是通用IO IOUtils.copy()方法的工作原理。如果您是从Reader而不是从InputStream复制,则可以用char[]替换byte[]

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    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);


    Another one,for all the spring users:

    1
    2
    3
    4
    5
    6
    import java.nio.charset.StandardCharsets;
    import org.springframework.util.FileCopyUtils;

    public String convertStreamToString(InputStream is) throws IOException {
        return new String(FileCopyUtils.copyToByteArray(is), StandardCharsets.UTF_8);
    }

    org.springframework.util.StreamUtils中使用的方法与FileCopyUtils中使用的方法相似,但它们在使用时就离开了流水。


    Use the java.io.inputstream.transferto(outputstream)supported in Java 9 and the bytearrayoutputstream.tostring(string)which takes the charset name:

    1
    2
    3
    4
    5
    public static String gobble(InputStream in, String charsetName) throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        in.transferTo(bos);
        return bos.toString(charsetName);
    }


    Kotlin users simply do:

    1
    println(InputStreamReader(is).readText())

    whereas

    ZZU1

    Is Kotlin Standard Library's Buill-in Extension Method.


    这个很好,因为:

    • 用手保护字符集。
    • 您可以控制读取缓冲区的大小。
    • 您可以设置生成器的长度,但不能精确设置。
    • 没有库依赖项。
    • 是Java 7或更高版本。

    为了什么?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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中最简单的方法是使用以下代码截图。

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

    这是我的Java 8号解决方案,用新的流程API收集所有线条的InputStream

    1
    2
    3
    4
    5
    6
    public static String toString(InputStream inputStream) {
        BufferedReader reader = new BufferedReader(
            new InputStreamReader(inputStream));
        return reader.lines().collect(Collectors.joining(
            System.getProperty("line.separator")));
    }


    In terms of EDOCX1&3,and EDOCX1&4),it can be expressed in Java 8 as:

    1
    2
    String fromFile = new BufferedReader(new  
    InputStreamReader(inputStream)).lines().reduce(String::concat).get();


    在Groovy中

    1
    inputStream.getText()


    Raghu K Nair是唯一一个使用扫描仪的人。我使用的代码有点不同:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    String convertToString(InputStream in){
        Scanner scanner = new Scanner(in)
        scanner.useDelimiter("\\A");

        boolean hasInput = scanner.hasNext();
        if (hasInput) {
            return scanner.next();
        } else {
            return null;
        }

    }

    关于Delimiters:如何在Java扫描仪中使用定界符?


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    InputStream is = Context.openFileInput(someFileName); // whatever format you have

    ByteArrayOutputStream bos = new ByteArrayOutputStream();

    byte[] b = new byte[8192];
    for (int bytesRead; (bytesRead = is.read(b)) != -1;) {
        bos.write(b, 0, bytesRead);
    }

    String output = bos.toString(someEncoding);

    我写了一个这样的课程,所以我想我会和大家分享。有时,您不想仅仅为了一件事就添加ApacheCommons,并且想要比不检查内容的扫描器更愚蠢的东西。

    用法如下

    1
    2
    3
    4
    5
    6
    7
    8
    // 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的代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    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);
            }
        }
    }

    下面的代码适用于我。

    1
    2
    3
    4
    5
    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文档,EDCOX1×0的方法可能不适用于EDCOX1 OR 1,但总是使用EDCOX1 2。如果您不想使用available()方法,我们可以使用下面的代码

    1
    2
    3
    4
    5
    6
    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);

    我不确定是否会有编码问题。如果代码有任何问题,请评论。


    Guava提供了大量的短效率自动闭锁解决方案,当输入流从典型的路径资源来(这似乎是一个流行的任务):

    1
    byte[] bytes = Resources.toByteArray(classLoader.getResource(path));

    黄金

    1
    String text = Resources.toString(classLoader.getResource(path), StandardCharsets.UTF_8);

    还有一个一般的拜土思想和夏源思想,那就是人类既要开启又要关闭河流。

    So,for example,instead of explicitly opening a small file to read its contents:

    1
    2
    String content = Files.asCharSource(new File("robots.txt"), StandardCharsets.UTF_8).read();
    byte[] data = Files.asByteSource(new File("favicon.ico")).read();

    或只是

    1
    2
    String content = Files.toString(new File("robots.txt"), StandardCharsets.UTF_8);
    byte[] data = Files.toByteArray(new File("favicon.ico"));


    Based on the second part of the accepted Apache commons answer but with the small gap filled in for always closing the stream:

    1
    2
    3
    4
    5
    6
        String theString;
        try {
            theString = IOUtils.toString(inputStream, encoding);
        } finally {
            IOUtils.closeQuietly(inputStream);
        }


    JDK 7/8应答,关闭流并仍抛出IOException:

    1
    2
    3
    4
    5
    6
    7
    8
    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种说法。

    根据Fred回忆的观点,不建议在+=运算符后面加一个String,因为每次在现有String运算符后面加一个新的char,重新创建一个新的String对象,并将其地址分配给st,而旧的st对象变成垃圾。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public String convertStreamToString(InputStream is)
    {
        int k;
        StringBuffer sb=new StringBuffer();
        while((k=fin.read()) != -1)
        {
            sb.append((char)k);
        }
        return sb.toString();
    }

    不推荐,但这也是一种方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public String convertStreamToString(InputStream is) {
        int k;
        String st="";
        while((k=is.read()) != -1)
        {
            st+=(char)k;
        }
        return st;
    }


    您可以使用Apache Commons。

    在ioutils中,您可以找到具有三个有用实现的toString方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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));
    }


    与Okio:

    1
    String result = Okio.buffer(Okio.source(inputStream)).readUtf8();

    好吧,你可以自己编程…这并不复杂…

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    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();
        }


    1
    2
    3
    4
    5
    6
    public String read(InputStream in) throws IOException {
        try (BufferedReader buffer = new BufferedReader(new InputStreamReader(in))) {
            return buffer.lines().collect(Collectors.joining("
    "
    ));
        }
    }

    你可以用仙人掌:

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

    UTF-8编码是默认编码。如果您需要另一个:

    1
    String text = new TextOf(inputStream,"UTF-16").asString();

    ISO-859-1

    如果您知道输入流的编码是iso-8859-1或ascii,那么下面是一种非常有效的方法。它(1)避免了StringWriter的内部StringBuffer中不必要的同步;(2)避免了InputStreamReader的开销;(3)最小化了StringBuilder的内部char数组必须被复制的次数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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编码的流,也可以使用相同的一般策略:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    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()函数定义如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    /**
     * 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编码的,但您不确定是哪种,那么我们可以使用与上一种方法类似的方法,但使用附加的编码检测组件在返回字符串之前自动检测编码。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    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,那么我将遵从已经存在的其他答案。


    以下内容并没有解决最初的问题,而是一些回答。

    一些反应表明了形式的循环

    1
    2
    3
    4
    String line = null;
    while((line = reader.readLine()) != null) {
      // ...
    }

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

    第一个表单通过在封闭范围中声明一个变量"read"来污染封闭范围的命名空间,该变量将不会用于for循环之外的任何内容。第二个窗体与readline()调用重复。

    这里有一个更简洁的方法来编写Java中的这种循环。原来for循环中的第一个子句不需要实际的初始值设定项值。这将变量"line"的范围保持在for循环的主体中。更优雅!我没见过任何人在任何地方使用过这个表单(几年前的一天我随机发现了它),但我一直在使用它。

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

    1
    2
    3
    4
    InputStreamReader i = new InputStreamReader(s);
    BufferedReader str = new BufferedReader(i);
    String msg = str.readLine();
    System.out.println(msg);

    这是你的InputStream物体,它会变成String的。


    转换输入流到弦乐的方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    public static String getStringFromInputStream(InputStream inputStream) {

        BufferedReader bufferedReader = null;
        StringBuilder stringBuilder = new StringBuilder();
        String line;

        try {
            bufferedReader = new BufferedReader(new InputStreamReader(
                    inputStream));
            while ((line = bufferedReader.readLine()) != null) {
                stringBuilder.append(line);
            }
        } catch (IOException e) {
            logger.error(e.getMessage());
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    logger.error(e.getMessage());
                }
            }
        }
        return stringBuilder.toString();
    }

    用途:

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


    这个问题的解决方案并不是最简单的,但是由于没有提到NIO流和通道,这里介绍了一个使用NIO通道和ByteBuffer将流转换为字符串的版本。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public static String streamToStringChannel(InputStream in, String encoding, int bufSize) throws IOException {
        ReadableByteChannel channel = Channels.newChannel(in);
        ByteBuffer byteBuffer = ByteBuffer.allocate(bufSize);
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        WritableByteChannel outChannel = Channels.newChannel(bout);
        while (channel.read(byteBuffer) > 0 || byteBuffer.position() > 0) {
            byteBuffer.flip();  //make buffer ready for write
            outChannel.write(byteBuffer);
            byteBuffer.compact(); //make buffer ready for reading
        }
        channel.close();
        outChannel.close();
        return bout.toString(encoding);
    }

    下面是一个如何使用它的示例:

    1
    2
    3
    4
    try (InputStream in = new FileInputStream("/tmp/large_file.xml")) {
        String x = streamToStringChannel(in,"UTF-8", 1);
        System.out.println(x);
    }

    对于大型文件,此方法的性能应该很好。


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    InputStream  inputStream = null;
    BufferedReader bufferedReader = null;
    try {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String stringBuilder = new StringBuilder();
        String content;
        while((content = bufferedReader.readLine()) != null){
            stringBuilder.append(content);
        }
        System.out.println("content of file::" + stringBuilder.toString());
    }
    catch (IOException e) {
                e.printStackTrace();
            }finally{          
                if(bufferedReader != null){
                    try{
                        bufferedReader.close();
                    }catch(IoException ex){
                       ex.printStackTrace();
                }

    在SDKSAMPsANDROID-19 连接性 NETWorksNo.NETWorkCopyStaseSrcMadiajavacom示例 Android ETWorkSnutsMadiActuv.java中,Apache许可证、2版和谷歌编写了Java。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    /** 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);
    }

    对于这个问题,我建议使用StringWriter类。

    1
    2
    3
    StringWriter wt= new StringWriter();
    IOUtils.copy(inputStream, wt, encoding);
    String st= wt.toString();

    还可以从特定资源路径输入:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public static InputStream getResourceAsStream(String path)
    {
        InputStream myiInputStream = ClassName.class.getResourceAsStream(path);
        if (null == myiInputStream)
        {
            mylogger.info("Can't find path =", path);
        }

        return myiInputStream;
    }

    To get inputstream from a specific path:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public static URL getResource(String path)
    {
        URL myURL = ClassName.class.getResource(path);
        if (null == myURL)
        {
            mylogger.info("Can't find resource path =", path);
        }
        return myURL;
    }


    我已经创建了这个代码,并且它可以工作。不需要外部插件。

    有将字符串转换为流,将流转换为字符串…

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    import java.io.ByteArrayInputStream;
    import java.io.InputStream;

    public class STRINGTOSTREAM {

        public static void main(String[] args)
        {
            String text ="Hello Bhola..!
    My 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;
        }


    注:这可能不是一个好主意。这一方法使用的回归和Thus将击中一个EDOCX1&2。

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

    请不要低估这一点,因为这是一个糟糕的使用选择;这是最有创意的:)


    String resultString = IOUtils.toString(userInputStream,"UTF-8");


    我有log4j可用,所以我可以使用org.apache.log4j.lf5.util.streamutils.get bytes获取字节,我可以使用字符串ctor将其转换为字符串。

    1
    String result = new String(StreamUtils.getBytes(inputStream));


    1
    2
    3
    4
    5
    6
    7
      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);


    首先,您必须知道要转换的字符串的编码。由于java.io.InputStream操作一个基本的字节数组,但是字符串是由一个需要编码的字符数组组成的,例如utf-8,jdk将采用默认编码,该默认编码是从

    1
    2
    3
    4
    5
    System.getProperty("file.encoding","UTF-8");

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

    如果InputStream的字节数组非常大,可以在循环中进行。


    快速简便:

    1
    String result = (String)new ObjectInputStream( inputStream ).readObject();