Java:11 種方法 InputStream => String

轉(zhuǎn)自StackOverflow:
原貼地址:https://stackoverflow.com/questions/309424/how-do-i-read-convert-an-inputstream-into-a-string-in-java

從InputStream 獲得 String 應(yīng)該算是比較常見的問題毕籽,方法也很多吱涉,我在網(wǎng)上看到了一個(gè)問答货裹,回答者總結(jié)了11種常用的方法并比較了它們的運(yùn)行效率:

1. 使用IOUtils.toString (Apache Utils)

String result = IOUtils.toString(inputStream, StandardCharsets.UTF_8);

2. 使用CharStreams (Guava)

String result = CharStreams.toString(new InputStreamReader(
      inputStream, Charsets.UTF_8));

3. 使用 Scanner (JDK)

Scanner s = new Scanner(inputStream).useDelimiter("\\A");
String result = s.hasNext() ? s.next() : "";

4. 使用 Stream API (Java 8)

注意:這種方式會(huì)把換行(比如:"\r\n")一律轉(zhuǎn)化為"\n"

String result = new BufferedReader(new InputStreamReader(inputStream))
  .lines().collect(Collectors.joining("\n"));

5. 使用 Parallel Stream API (Java 8)

注意: 這種方式會(huì)把換行(比如:"\r\n")一律轉(zhuǎn)化為"\n"

String result = new BufferedReader(new InputStreamReader(inputStream)).lines()
   .parallel().collect(Collectors.joining("\n"));

6. 使用 InputStreamReader 和 StreamBuilder (JDK)

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

7. 使用StringWriter 和 IOUtils.copy (Apache Commons)

StringWriter writer = new StringWriter();
IOUtils.copy(inputStream, writer, "UTF-8");
return writer.toString();

8. 使用 ByteArrayOutputStream 和 inputStream.read (JDK)

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

9. 使用 BufferedReader

注意:這種方法會(huì)把換行(比如:"\n\r")轉(zhuǎn)換成 line.separator 然后在不同的操作系統(tǒng)中轉(zhuǎn)換成不同的形式

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

10. 使用 BufferedInputStream 和 ByteArrayOutputStram (JDK)

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

11. 使用 InputStream.read() 和 StringBuilder (JDK)

注意: 這種方法不能處理unicode (處理不了中文)

int ch;
StringBuilder sb = new StringBuilder();
while((ch = inputStream.read()) != -1)
    sb.append((char)ch);
reset();
return sb.toString();

對(duì)小的String (長度為175)進(jìn)行處理器净,表現(xiàn):

             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

對(duì)大的String (長度為50100) 進(jìn)行處理萤捆,表現(xiàn):

               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

對(duì)不同長度的String 進(jìn)行處理兼贸,表現(xiàn):

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

可見晰绎,第8 種方法(使用 ByteArrayOutputStream 和 inputStream.read)效率遠(yuǎn)優(yōu)于其他10種

而,第3種方法(使用 Scanner)在3種實(shí)驗(yàn)中表現(xiàn)都不是很好

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市在跳,隨后出現(xiàn)的幾起案子枪萄,更是在濱河造成了極大的恐慌,老刑警劉巖猫妙,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瓷翻,死亡現(xiàn)場離奇詭異,居然都是意外死亡割坠,警方通過查閱死者的電腦和手機(jī)逻悠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來韭脊,“玉大人,你說我怎么就攤上這事单旁』Ω幔” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵象浑,是天一觀的道長蔫饰。 經(jīng)常有香客問我,道長愉豺,這世上最難降的妖魔是什么篓吁? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮蚪拦,結(jié)果婚禮上杖剪,老公的妹妹穿的比我還像新娘。我一直安慰自己驰贷,他們只是感情好盛嘿,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著括袒,像睡著了一般次兆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上锹锰,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天芥炭,我揣著相機(jī)與錄音,去河邊找鬼恃慧。 笑死园蝠,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的糕伐。 我是一名探鬼主播砰琢,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了陪汽?” 一聲冷哼從身側(cè)響起训唱,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎挚冤,沒想到半個(gè)月后况增,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡训挡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年澳骤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片澜薄。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡为肮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出肤京,到底是詐尸還是另有隱情颊艳,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布忘分,位于F島的核電站棋枕,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏妒峦。R本人自食惡果不足惜重斑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望肯骇。 院中可真熱鬧窥浪,春花似錦、人聲如沸笛丙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽若债。三九已至符相,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蠢琳,已是汗流浹背啊终。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留傲须,地道東北人蓝牲。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像泰讽,于是被迫代替她去往敵國和親例衍。 傳聞我的和親對(duì)象是個(gè)殘疾皇子昔期,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354