a

Câu hỏi Đọc / chuyển đổi một InputStream thành một chuỗi


Nếu bạn có một java.io.InputStream đối tượng, bạn nên xử lý đối tượng đó như thế nào và tạo ra String?


Giả sử tôi có một InputStream có chứa dữ liệu văn bản và tôi muốn chuyển đổi nó thành String, vì vậy, ví dụ tôi có thể viết nó vào một tệp nhật ký.

Cách dễ nhất để lấy InputStream và chuyển đổi nó thành String?

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

3267
2017-11-21 16:47


gốc


Cậu bé, tôi hoàn toàn yêu Java, nhưng câu hỏi này xuất hiện thường xuyên như bạn nghĩ rằng họ sẽ chỉ ra rằng chuỗi suối có phần khó khăn và giúp người tạo ra các kết hợp khác nhau hoặc suy nghĩ lại toàn bộ sự việc. - Bill K
Câu trả lời cho câu hỏi này chỉ hoạt động nếu bạn muốn đọc nội dung của luồng đầy đủ (cho đến khi nó được đóng lại). Vì đó không phải lúc nào cũng được dự định (các yêu cầu http có kết nối tiếp tục tồn tại sẽ không bị đóng), các phương thức này sẽ chặn khối (không cung cấp cho bạn nội dung). - f1sh
Bạn nhu cầu để biết và chỉ định mã hóa ký tự cho luồng hoặc bạn sẽ có lỗi mã hóa ký tự, vì bạn sẽ sử dụng mã hóa được chọn ngẫu nhiên tùy thuộc vào máy / hệ điều hành / nền tảng hoặc phiên bản mã của bạn được chạy trên đó. Đó là, làm không phải sử dụng các phương pháp phụ thuộc vào mã hóa mặc định nền tảng. - Christoffer Hammarström
Chỉ để vui chơi với bình luận của riêng tôi từ 9 năm trước, những ngày này tôi sử dụng "String s = new File (" SomeFile.txt ") của Groovy" văn bản "để đọc toàn bộ tập tin cùng một lúc và nó hoạt động tốt. Tôi hài lòng với việc sử dụng groovy cho mã không phải sản xuất (scripting) và - cũng thành thật buộc bạn phải xử lý mã hóa và các tệp cực dài theo cách java thực sự là một ý tưởng tốt cho mã sản xuất, vì vậy nó hoạt động cho mục đích của nó, Groovy làm việc cho các kịch bản nhanh mà java không phải là tuyệt vời tại - Chỉ cần sử dụng đúng công cụ cho công việc và tất cả các công trình ra. - Bill K
Đơn giản hóa: ByteArrayOutputStream outputBytes = new ByteArrayOutputStream();  for(byte[] b = new byte[512]; 0 < inputStream.read(b); outputBytes.write(b));  return new String(outputBytes.toByteArray(), StandardCharsets.UTF_8); - Felypp Oliveira


Các câu trả lời:


Một cách hay để làm điều này là sử dụng Apache commons  IOUtils để sao chép InputStream thành một StringWriter... cái gì đó như

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

hoặc thậm chí

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

Ngoài ra, bạn có thể sử dụng ByteArrayOutputStream nếu bạn không muốn kết hợp các luồng và nhà văn của mình


2048
2017-11-21 16:54



tôi tìm thấy ngoại lệ filenotfound trong khi tôi cố gắng đọc tên tập tin với tên tập tin "До_свидания" (tiếng Nga) tôi thử với FileInputstream nhưng nó không cáp để đọc tên tập tin này từ sdcard. - Bhanu Sharma
Đối với các nhà phát triển Android, có vẻ như android không đi kèm với IOUtils từ Apache. Vì vậy, bạn có thể xem xét đề cập đến câu trả lời khác. - Chris.Zou
Tôi làm việc trong một môi trường hạn chế, vì vậy giải pháp của @PavelRepin dưới đây sử dụng java io / util libs có ý nghĩa hơn. - James
Đây là một câu hỏi cực kỳ cũ tại thời điểm này (nó đã được yêu cầu trong năm 2008). Bạn nên dành thời gian đọc qua các câu trả lời hiện đại hơn. Một số sử dụng các cuộc gọi tự nhiên từ thư viện Java 8. - Shadoninja
Câu trả lời này là rất lỗi thời và một trong những sẽ có thể đánh dấu nó như vậy (thật đáng tiếc này là không thể atm). - codepleb


Đây là một cách chỉ sử dụng thư viện Java chuẩn (lưu ý rằng luồng không được đóng, YMMV).

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

Tôi đã học được mẹo này từ "Thủ thuật quét ngu ngốc" bài báo. Lý do nó hoạt động là vì Máy quét lặp lại trên mã thông báo trong luồng và trong trường hợp này, chúng tôi tách các mã thông báo bằng cách sử dụng "đầu ranh giới đầu vào" (\ A), do đó chỉ cung cấp cho chúng tôi một mã thông báo cho toàn bộ nội dung của luồng.

Lưu ý, nếu bạn cần phải cụ thể về mã hóa của luồng đầu vào, bạn có thể cung cấp đối số thứ hai cho Scanner hàm tạo cho biết bộ ký tự nào cần sử dụng (ví dụ: "UTF-8").

Hat tip cũng đi đến Jacob, người đã từng chỉ cho tôi bài viết đã nói.

CHỈNH SỬA: Nhờ có đề xuất từ Patrick, làm cho hàm mạnh mẽ hơn khi xử lý luồng đầu vào trống. Một chỉnh sửa khác: nixed cố gắng / bắt, cách của Patrick là laconic hơn.


2093
2018-03-26 20:40



Cảm ơn, cho phiên bản của tôi này tôi đã thêm một khối cuối cùng mà đóng dòng đầu vào, do đó, người dùng không phải kể từ khi bạn đã đọc xong đầu vào. Đơn giản hóa mã người gọi một cách đáng kể.
@PavelRepin @Patrick trong trường hợp của tôi, một inputStream trống gây ra một NPE trong quá trình xây dựng Scanner. Tôi phải thêm if (is == null) return ""; ngay ở đầu phương pháp; Tôi tin rằng câu trả lời này cần phải được cập nhật để xử lý tốt hơn null inputStreams. - CFL_Jeff
Đối với Java 7, bạn có thể đóng một bản thử: try(java.util.Scanner s = new java.util.Scanner(is)) { return s.useDelimiter("\\A").hasNext() ? s.next() : ""; } - earcam
Thật không may, giải pháp này dường như đi và mất các ngoại lệ được ném trong triển khai luồng cơ bản của tôi. - Taig
FYI, hasNext chặn trên luồng đầu vào của bảng điều khiển (xem đây). (Chỉ cần chạy vào vấn đề này ngay bây giờ.) Giải pháp này hoạt động tốt nếu không ... chỉ cần một người đứng lên. - Ryan


Tóm tắt các câu trả lời khác tôi đã tìm thấy 11 cách chính để thực hiện việc này (xem bên dưới). Và tôi đã viết một số bài kiểm tra hiệu suất (xem kết quả dưới đây):

Các cách để chuyển đổi một InputStream thành một chuỗi:

  1. Sử dụng IOUtils.toString (Apache Utils)

    String result = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
    
  2. Sử dụng CharStreams (Trái ổi)

    String result = CharStreams.toString(new InputStreamReader(
          inputStream, Charsets.UTF_8));
    
  3. Sử dụng Scanner (JDK)

    Scanner s = new Scanner(inputStream).useDelimiter("\\A");
    String result = s.hasNext() ? s.next() : "";
    
  4. Sử dụng API luồng (Java 8). Cảnh báo: Giải pháp này chuyển đổi các ngắt dòng khác nhau (như \r\n) đến \n.

    String result = new BufferedReader(new InputStreamReader(inputStream))
      .lines().collect(Collectors.joining("\n"));
    
  5. Sử dụng API luồng song song (Java 8). Cảnh báo: Giải pháp này chuyển đổi các ngắt dòng khác nhau (như \r\n) đến \n.

    String result = new BufferedReader(new InputStreamReader(inputStream)).lines()
       .parallel().collect(Collectors.joining("\n"));
    
  6. Sử dụng InputStreamReader và StringBuilder (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. Sử dụng StringWriter và IOUtils.copy (Apache Commons)

    StringWriter writer = new StringWriter();
    IOUtils.copy(inputStream, writer, "UTF-8");
    return writer.toString();
    
  8. Sử dụng ByteArrayOutputStream và 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. Sử dụng BufferedReader (JDK). Cảnh báo: Giải pháp này chuyển đổi các ngắt dòng khác nhau (như \n\r) đến line.separator thuộc tính hệ thống (ví dụ, trong Windows thành "\ r \ n").

    String newLine = System.getProperty("line.separator");
    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
    StringBuilder result = new StringBuilder();
    String line; boolean flag = false;
    while ((line = reader.readLine()) != null) {
        result.append(flag? newLine: "").append(line);
        flag = true;
    }
    return result.toString();
    
  10. Sử dụng BufferedInputStream và ByteArrayOutputStream (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. Sử dụng inputStream.read() và StringBuilder (JDK). Cảnh báo: Giải pháp này có vấn đề với Unicode, ví dụ với văn bản tiếng Nga (chỉ hoạt động chính xác với văn bản không phải Unicode)

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

Cảnh báo:

  1. Giải pháp 4, 5 và 9 chuyển đổi các ngắt dòng khác nhau thành một.

  2. Giải pháp 11 không thể hoạt động chính xác với văn bản Unicode

Kiểm tra hiệu năng

Kiểm tra hiệu suất cho nhỏ String (length = 175), url trong github (chế độ = Thời gian trung bình, hệ thống = Linux, điểm số 1,343 là tốt nhất):

              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

Kiểm tra hiệu suất cho lớn String (length = 50100), url trong github (chế độ = Thời gian trung bình, hệ thống = Linux, điểm số là 200,715 là tốt nhất):

               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

Biểu đồ (kiểm tra hiệu suất tùy thuộc vào độ dài luồng đầu vào trong hệ thống Windows 7)
enter image description here

Kiểm tra hiệu suất (Thời gian trung bình) tùy thuộc vào độ dài luồng đầu vào trong hệ thống 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

1656
2018-02-17 00:58



Khi bạn đang viết "câu trả lời tóm tắt", bạn nên lưu ý rằng một số giải pháp tự động chuyển đổi các dấu ngắt dòng khác nhau (như \r\n) đến \n có thể không mong muốn trong một số trường hợp. Ngoài ra nó sẽ được tốt đẹp để xem bộ nhớ bổ sung cần thiết hoặc ít nhất là áp lực phân bổ (ít nhất bạn có thể chạy JMH với -prof gc). Đối với bài đăng thực sự thú vị, nó sẽ là tuyệt vời để xem các đồ thị (tùy thuộc vào độ dài chuỗi trong cùng một kích thước đầu vào và tùy thuộc vào kích thước đầu vào trong cùng một chuỗi dài). - Tagir Valeev
Upvoted; điều hài hước nhất là kết quả nhiều hơn mong đợi: người ta nên sử dụng đường cú pháp JDK và / hoặc Apache Commons chuẩn. - mudasobwa
Bài đăng tuyệt vời. Một điều nữa thôi. Java 8 cảnh báo chống lại việc sử dụng các luồng song song trên các tài nguyên sẽ buộc bạn khóa và chờ (chẳng hạn như luồng đầu vào này) vì vậy tùy chọn luồng song song khá cồng kềnh và không đáng giá? - mangusbrother
Liệu luồng song song thực sự duy trì thứ tự dòng? - Natix
Những gì là reset() ví dụ 11? - Rob Stewart


Apache Commons cho phép:

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

Tất nhiên, bạn có thể chọn mã hóa ký tự khác ngoài UTF-8.

Cũng thấy: (Tài liệu)


794
2017-12-08 20:13



Ngoài ra, có một phương thức chỉ lấy đối số inputStream, nếu bạn đang tìm bằng mã hóa mặc định. - Guillaume Coté
@Guillaume Coté Tôi đoán thông điệp ở đây là bạn không bao giờ nên "tốt với mã hóa mặc định", vì bạn không thể chắc chắn về nó là gì, tùy thuộc vào nền tảng mã java được chạy trên. - Per Wiklander
@Per Wiklander Tôi không đồng ý với bạn. Mã đó sẽ làm việc trên một đơn có thể khá chắc chắn rằng mã hóa mặc định sẽ được sử dụng tốt. Đối với mã chỉ mở tệp cục bộ, đó là một tùy chọn hợp lý để yêu cầu chúng được mã hóa trong mã hóa mặc định nền tảng. - Guillaume Coté
Để tiết kiệm cho bất kỳ ai rắc rối của Googling - <dependency> <groupId> org.apache.commons </ groupId> <artifactId> commons-io </ artifactId> <phiên bản> 1.3.2 </ version> </ dependency> - Chris
Cũng ít cải thiện sẽ được sử dụng apache io (hoặc khác) liên tục cho mã hóa ký tự thay vì sử dụng chuỗi chữ đồng bằng - ví dụ: IOUtils.toString (myInputStream, Charsets.UTF_8);


Đi vào tài khoản tập tin đầu tiên nên có được một java.io.Reader ví dụ. Điều này sau đó có thể được đọc và thêm vào StringBuilder (chúng ta không cần StringBuffer nếu chúng ta không truy cập nó trong nhiều chủ đề, và StringBuilder nhanh hơn). Bí quyết ở đây là chúng tôi làm việc trong các khối và do đó không cần các luồng đệm khác. Kích thước khối được tham số hóa cho tối ưu hóa hiệu suất thời gian chạy.

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

263
2017-08-04 08:29



Giải pháp này sử dụng các ký tự nhiều byte. Ví dụ này sử dụng mã hóa UTF-8 cho phép biểu thức phạm vi unicode đầy đủ (bao gồm cả tiếng Trung Quốc). Thay thế "UTF-8" bằng cách mã hóa khác sẽ cho phép sử dụng mã hóa đó. - Paul de Vrieze
@ User1 - Tôi thích sử dụng thư viện trong mã của mình để tôi có thể hoàn thành công việc của mình nhanh hơn. Thật tuyệt vời khi các nhà quản lý của bạn nói "Wow James! Làm thế nào bạn có thể thực hiện điều đó nhanh như vậy?". Nhưng khi chúng ta phải dành thời gian để phát minh lại bánh xe chỉ vì chúng ta đã đặt sai ý tưởng về việc bao gồm một tiện ích chung, có thể tái sử dụng, đã thử và thử nghiệm, chúng ta đang từ bỏ thời gian chúng ta có thể chi tiêu hơn nữa các mục tiêu của dự án. Khi chúng tôi phát minh lại bánh xe, chúng tôi làm việc gấp đôi, nhưng sau đó vẫn chưa đến đích. Khi chúng ta đang ở vạch đích, không có ai ở đó để chúc mừng chúng tôi. Khi xây nhà, đừng xây búa - jmort253
Xin lỗi, sau khi đọc lại bình luận của tôi, nó đi ra một chút kiêu ngạo. Tôi chỉ nghĩ rằng điều quan trọng là phải có lý do chính đáng để tránh các thư viện và lý do đó là một lý do hợp lệ, điều này rất có thể là :) - jmort253
@ jmort253 Chúng tôi nhận thấy hồi quy hiệu suất sau khi cập nhật một số thư viện trong sản phẩm của chúng tôi trong nhiều lần. May mắn là chúng tôi đang xây dựng và bán sản phẩm của riêng mình nên chúng tôi không thực sự có thời hạn được gọi là như vậy. Thật không may, chúng tôi đang xây dựng một sản phẩm có sẵn trên nhiều JVM, cơ sở dữ liệu và máy chủ ứng dụng trên nhiều hệ điều hành vì vậy chúng tôi phải suy nghĩ cho người dùng sử dụng máy kém ... Và tối ưu hóa hoạt động chuỗi có thể cải thiện mức độ hoàn thiện 30 ~ 40%. Và một sửa chữa: In our product, I even replaced nên được 'chúng ta thậm chí thay thế'. - coolcfan
@ jmort253 Nếu bạn đã sử dụng apache commons tôi sẽ nói, hãy tìm nó. Đồng thời, có một chi phí thực sự để sử dụng thư viện (như sự gia tăng sự phụ thuộc trong nhiều thư viện java apache cho thấy). Nếu điều này sẽ là sử dụng duy nhất của thư viện, nó sẽ là quá mức cần thiết để sử dụng thư viện. Mặt khác, xác định kích thước bộ đệm của riêng bạn (s), bạn có thể điều chỉnh cân bằng sử dụng bộ nhớ / bộ xử lý của bạn. - Paul de Vrieze


Còn cái này thì sao?

InputStream in = / * InputStream của bạn * /;
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();

226
2017-07-13 15:56



Vấn đề là, đầu tiên bạn chia thành các dòng, và sau đó hoàn tác nó. Việc đọc các bộ đệm tùy ý trở nên dễ dàng và nhanh hơn. - Paul de Vrieze
Ngoài ra, readLine không phân biệt giữa \ n và \ r, do đó bạn không thể tạo lại luồng chính xác một lần nữa. - María Arias de Reyna Domínguez
@PauldeVrieze có bao nhiêu dòng và bạn cần xử lý chúng nhanh như thế nào !? Tôi sẽ nguy hiểm một đoán rằng bất kỳ tổn thất hiệu suất sẽ là nhỏ, hoặc có thể được xử lý bởi mỗi một lần trong một thời gian đăng nhập chúng vào một tập tin và phá hủy cũ của obj String. - Thufir
rất kém hiệu quả, readLine đọc nhân vật theo ký tự để tìm EOL. Ngoài ra, nếu không có ngắt dòng trong luồng, điều này không thực sự có ý nghĩa. - njzk2
Đây không phải là câu trả lời tốt nhất bởi vì nó không phải là byte đúng byte. Người đọc chomps dòng mới, vì vậy bạn phải cẩn thận để duy trì chúng. - Jeffrey Blattman


Nếu bạn đang sử dụng Google-Collections / Guava, bạn có thể làm như sau:

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

Lưu ý rằng tham số thứ hai (ví dụ: Charsets.UTF_8) cho InputStreamReader là không cần thiết, nhưng thường là một ý tưởng tốt để chỉ định mã hóa nếu bạn biết nó (bạn nên làm gì!)


153
2018-05-08 20:24



@harschware: Với câu hỏi là: "Nếu bạn có đối tượng java.io.InputStream thì bạn nên xử lý đối tượng đó và tạo ra một String như thế nào?" Tôi cho rằng một luồng đã xuất hiện trong tình huống. - Sakuraba
Bạn đã không giải thích câu trả lời của bạn rất tốt, và có các biến ngoại lai; user359996 cho biết điều tương tự như bạn, nhưng rõ ràng hơn nhiều. - Uronym
+1 cho ổi, -1 vì không chỉ định mã hóa luồng đầu vào. ví dụ. new InputStreamReader (luồng, "UTF-8") - andras
@ Chris Noldus Mặt khác, một số người đã có ổi trong dự án của họ, giống như tôi, và nghĩ rằng giải pháp này là thanh lịch hơn so với phiên bản chỉ sdk. - CorayThan
@Vadzim rằng câu trả lời là giống như thế này - cả hai đều sử dụng CharStreams.toString - Tom


Đây là giải pháp Java và Android thuần túy của tôi, hoạt động tốt ...

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

107
2018-06-10 21:07



Hoạt động tốt trên Android so với các câu trả lời khác chỉ hoạt động trong java doanh nghiệp. - vorrtex
Đã bị lỗi trong Android với lỗi OutOfMemory trên dòng ".write", mỗi lần, đối với các chuỗi ngắn. - Adam
Tôi đã thêm mã hóa. cũng giống như một lưu ý phụ, phương thức readFully gốc mà tôi có trong mã của tôi không trả về String, nó trả về byte [] cho một chức năng mục đích chung hơn. Việc triển khai String mới (...) bằng mã hóa là trách nhiệm của việc sử dụng API! - TacB0sS
Ghi chú nhanh: Dấu chân bộ nhớ này được tối đa bởi 2*n, trong đó n là kích thước của luồng, theo ByteArrayInputStream hệ thống phát triển tự động. - njzk2
Không nhất thiết tăng gấp đôi mức sử dụng bộ nhớ, điều đó rất quý giá trên thiết bị di động. Bạn nên sử dụng InputStreamReader và nối thêm vào StringReader, việc chuyển đổi byte sang char sẽ được thực hiện ngay lập tức, không phải hàng loạt ở cuối. - Oliv