这是完整的转换方法 InputStream 成 String 不使用任何第三方库。使用 StringBuilder 对于单线程环境,否则使用 StringBuffer 。
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(); }
总结其他答案我找到了11种主要方法(见下文)。我写了一些性能测试(见下面的结果):
的 将InputStream转换为String的方法: 强>
运用 IOUtils.toString (Apache Utils)
IOUtils.toString
String result = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
运用 CharStreams (番石榴)
CharStreams
String result = CharStreams.toString(new InputStreamReader( inputStream, Charsets.UTF_8));
运用 Scanner (JDK)
Scanner
Scanner s = new Scanner(inputStream).useDelimiter("\\A"); String result = s.hasNext() ? s.next() : "";
运用 的 流API 强> (Java 8)。 的 警告 强> :此解决方案可转换不同的换行符(如 \r\n ) 至 \n 。
\r\n
\n
String result = new BufferedReader(new InputStreamReader(inputStream)) .lines().collect(Collectors.joining("\n"));
运用 的 并行Stream API 强> (Java 8)。 的 警告 强> :此解决方案可转换不同的换行符(如 \r\n ) 至 \n 。
String result = new BufferedReader(new InputStreamReader(inputStream)).lines() .parallel().collect(Collectors.joining("\n"));
运用 InputStreamReader 和 StringBuilder (JDK)
InputStreamReader
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();
运用 StringWriter 和 IOUtils.copy (Apache Commons)
StringWriter
IOUtils.copy
StringWriter writer = new StringWriter(); IOUtils.copy(inputStream, writer, "UTF-8"); return writer.toString();
运用 ByteArrayOutputStream 和 inputStream.read (JDK)
ByteArrayOutputStream
inputStream.read
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 (JDK)。 的 警告: 强> 此解决方案可转换不同的换行符(如 \n\r ) 至 line.separator 系统属性(例如,在Windows中为“\ r \ n”)。
BufferedReader
\n\r
line.separator
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();
运用 BufferedInputStream 和 ByteArrayOutputStream (JDK)
BufferedInputStream
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文本)
inputStream.read()
int ch; StringBuilder sb = new StringBuilder(); while((ch = inputStream.read()) != -1) sb.append((char)ch); reset(); return sb.toString();
的 警告 强> :
解决方案4,5和9将不同的换行符转换为1。
解决方案11无法与Unicode文本一起正常工作
的 性能测试 强>
性能测试小 String (长度= 175),网址为 github上 (模式=平均时间,系统= Linux,得分1,343是最好的):
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
性能测试大 String (长度= 50100),网址 github上 (模式=平均时间,系统= Linux,得分200,715是最好的):
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
图表(性能测试取决于Windows 7系统中的输入流长度)
性能测试(平均时间)取决于Windows 7系统中的输入流长度:
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
我会使用一些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. } }
基本上与其他一些答案相同,除了更简洁。
就......而言 reduce ,和 concat 它可以用Java 8表示为:
reduce
concat
String fromFile = new BufferedReader(new InputStreamReader(inputStream)).lines().reduce(String::concat).get();
一个很好的方法是使用 Apache公地 IOUtils 复制 InputStream 进入 StringWriter ... 就像是
IOUtils
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 如果你不想混合你的Streams和Writers
以下是使用字节数组缓冲区仅使用JDK的方法。这实际上是如何公共的 IOUtils.copy() 方法都有效。你可以替换 byte[] 同 char[] 如果你是从一个复制 Reader 而不是 InputStream 。
IOUtils.copy()
byte[]
char[]
Reader
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);
如果您喜欢冒险,可以将Scala和Java混合使用,最后得到:
scala.io.Source.fromInputStream(is).mkString("")
混合Java和Scala代码和库有它的好处。
看这里的完整描述: 在Scala中将InputStream转换为String的惯用法
这里的完整性是 的 Java 9 强> 解:
public static String toString(InputStream input) throws IOException { return new String(input.readAllBytes(), StandardCharsets.UTF_8); }
该 readAllBytes 目前在JDK 9主代码库中,因此很可能会在发布中出现。你现在可以尝试使用 JDK 9快照构建 。
readAllBytes
这个很好,因为:
这是为了什么?
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(); }
如果您不能使用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); } }
Kotlin用户只需:
println(InputStreamReader(is).readText())
而
readText()
是Kotlin标准库的内置扩展方法。
这是我的 的 Java 8 强> 基于解决方案,使用 新的Stream API 从一个收集所有行 InputStream :
public static String toString(InputStream inputStream) { BufferedReader reader = new BufferedReader( new InputStreamReader(inputStream)); return reader.lines().collect(Collectors.joining( System.getProperty("line.separator"))); }
如果您使用的是Google-Collections / Guava,则可以执行以下操作:
InputStream stream = ... String content = CharStreams.toString(new InputStreamReader(stream, Charsets.UTF_8)); Closeables.closeQuietly(stream);
注意第二个参数(即Charsets.UTF_8) InputStreamReader 没有必要,但如果您知道它(通常应该!),通常最好指定编码。
JDK中最简单的方法是使用以下代码snipplet。
String convertToString(InputStream in){ String resource = new Scanner(in).useDelimiter("\\Z").next(); return resource; }
我经常进行一些时间测试,因为时间很重要。
我试图以不同的方式将响应变为String 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 - 比#1慢2.6% 方法#2 - 比#1慢4.3%
这些方法中的任何一种都是用于获取响应并从中创建String的适当解决方案。