Bagaimana cara membaca / mengubah suatu InputStream ke String dalam Java?
Jika anda memiliki jawa.io.InputStream
objek, bagaimana seharusnya proses itu objek dan menghasilkan String
?
Misalkan saya memiliki sebuah InputStream
yang berisi data teks, dan saya ingin mengubahnya menjadi String
, jadi misalnya saya dapat menulis ke file log.
Apa adalah cara termudah untuk mengambil InputStream
dan mengubahnya menjadi String
?
public String convertStreamToString(InputStream is) {
// ???
}
3842
57
Cara yang baik untuk melakukan ini adalah dengan menggunakan Apache commons
IOUtils
untuk menyalinInputStream
menjadiStringWriter
... sesuatu sepertiatau bahkan
Sebagai alternatif, anda bisa menggunakan
ByteArrayOutputStream
jika anda don't ingin mencampur Stream anda dan PenulisBerikut ini's cara yang hanya menggunakan standard library Java (perhatikan bahwa aliran ini tidak tertutup, anda mungkin berbeda).
Saya belajar trik ini dari "Bodoh Scanner trik" artikel. Alasan bekerja adalah karena Scanner iterates atas token di sungai, dan dalam hal ini kita terpisah token menggunakan "mulai dari input batas" (\A), sehingga memberikan kita hanya satu token untuk seluruh isi sungai.
Catatan, jika anda perlu untuk lebih spesifik tentang input stream's encoding, anda dapat memberikan argumen kedua untuk
Scanner
konstruktor yang menunjukkan apa set karakter yang digunakan (misalnya "UTF-8").Hat tip pergi juga ke Yakub, yang pernah menunjuk saya untuk pasal tersebut.
Meringkas jawaban lain saya menemukan 11 cara utama untuk melakukan hal ini (lihat di bawah). Dan saya menulis beberapa tes kinerja (lihat hasil di bawah ini):
Cara untuk mengkonversi InputStream untuk String:
IOUtils.toString
(Apache Utils)String hasil = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
CharStreams
(Jambu Biji)String hasil = CharStreams.toString(new InputStreamReader( inputStream, Charset.UTF_8));
Scanner
(JDK)Scanner s = new Scanner(inputStream).useDelimiter("\"); String hasil = s.hasNext() ? s.next() : ",";
\r\n
) untuk\n
.String hasil = new BufferedReader(new InputStreamReader(inputStream)) .garis().mengumpulkan(Kolektor.bergabung("\n"));
\r\n
) untuk\n
.String hasil = new BufferedReader(new InputStreamReader(inputStream)).garis() .paralel().mengumpulkan(Kolektor.bergabung("\n"));
InputStreamReader
danStringBuilder
(JDK)final int bufferSize = 1024; akhir char[] buffer = new char[bufferSize]; akhir StringBuilder out = new StringBuilder(); Reader = new InputStreamReader(inputStream, "UTF-8"); for (; ; ) { int lain bagi anda untuk memilih = di.read(buffer, 0, buffer.panjang); jika (lain bagi anda untuk memilih < 0) break; keluar.append(buffer, 0, lain bagi anda untuk memilih); } kembali keluar.toString();
StringWriter
danIOUtils.salin
(Apache Commons)StringWriter writer = new StringWriter(); IOUtils.copy(inputStream, penulis, "UTF-8"); kembali penulis.toString();
ByteArrayOutputStream
daninputStream.baca
(JDK)ByteArrayOutputStream hasil = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int panjang; sementara ((panjang = inputStream.read(buffer)) != -1) { hasilnya.write(buffer, 0, panjang); } // StandardCharsets.UTF_8.nama() > JDK 7 kembali hasilnya.toString("UTF-8");
(JDK). **Peringatan:** solusi Ini mengkonversi garis yang berbeda istirahat (seperti
\n\r) ke
garis.pemisah` sistem properti (misalnya, di Windows untuk "\r\n").String newLine = Sistem.getProperty("garis.separator"); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); StringBuilder hasil = new StringBuilder(); boolean flag = false; untuk (String line; (baris = reader.readLine()) != null; ) { hasilnya.append(bendera? newLine: ",").append(garis); bendera = true; } kembali hasilnya.toString();
BufferedInputStream
danByteArrayOutputStream
(JDK)BufferedInputStream bis = new BufferedInputStream(inputStream); ByteArrayOutputStream buf = new ByteArrayOutputStream(); int hasil = bis.read(); sementara(hasil != -1) { buf.menulis((byte) hasil); hasil = bis.read(); } // StandardCharsets.UTF_8.nama() > JDK 7 kembali buf.toString("UTF-8");
inputStream.read()
danStringBuilder
(JDK). Peringatan: solusi Ini memiliki masalah dengan Unicode, misalnya dengan teks rusia (bekerja dengan benar hanya dengan teks non-Unicode)int ch; StringBuilder sb = new StringBuilder(); sementara((ch = inputStream.read()) != -1) sb.append((char)ch); reset(); kembali sb.toString();
Peringatan:
Solusi 4, 5 dan 9 mengkonversi garis yang berbeda istirahat untuk satu.
Solusi 11't bekerja dengan benar dengan teks Unicode
Kinerjates**
Tes kinerja untuk kecil
String
(panjang = 175), url di github (modus = rata-Rata Waktu, sistem = Linux, skor 1,343 adalah yang terbaik):Tes kinerja untuk besar
String
(panjang = 50100), url di github (modus = rata-Rata Waktu, sistem = Linux, skor 200,715 adalah yang terbaik):Grafik (tes kinerja tergantung pada Input Stream panjang di sistem Windows 7)
Tes kinerja (Waktu rata-Rata) tergantung pada Input Stream panjang di sistem Windows 7:
Apache Commons memungkinkan:
Tentu saja, anda bisa memilih pengkodean karakter selain UTF-8.
Juga lihat: (dokumentasi)
Dengan mempertimbangkan file yang pertama harus mendapatkan
jawa.io.Pembaca
misalnya. Hal ini kemudian dapat membaca dan ditambahkan keStringBuilder
(kita don't perluStringBuffer
jika kita tidak mengakses di beberapa thread, danStringBuilder
lebih cepat). Kuncinya di sini adalah bahwa kita bekerja di blok, dan seperti don't perlu lainnya buffering streaming. Ukuran blok adalah parameter untuk run-time optimasi kinerja.Gunakan:
Jika anda menggunakan Google-Koleksi/Jambu anda bisa melakukan hal berikut:
Perhatikan bahwa parameter kedua (yaitu Charset.UTF_8) untuk
InputStreamReader
isn't perlu, tapi hal ini umumnya ide yang baik untuk menentukan encoding jika anda tahu itu (yang anda harus!)Ini adalah yang terbaik Java murni solusi yang cocok untuk Android dan lainnya JVM.
Solusi ini bekerja luar biasa baik... hal ini sederhana, cepat, dan bekerja pada kecil dan besar di sungai sama saja!! (lihat acuan di atas.. No. 8)
Untuk kelengkapan di sini adalah Jawa 9 solusi:
Yang
readAllBytes
saat ini sedang dalam JDK 9 utama basis kode, sehingga mungkin muncul di rilis. Anda bisa mencobanya sekarang dengan menggunakan JDK 9 snapshot membangun.Berikut ini's paling elegan, murni-Jawa (tidak ada perpustakaan) solusi saya datang dengan setelah beberapa eksperimen:
Gunakan:
Saya melakukan benchmark pada 14 berbeda dengan jawaban berikut ini (maaf untuk tidak memberikan kredit tapi ada terlalu banyak duplikat).
Hasilnya sangat mengejutkan. Ternyata Apache IOUtils adalah yang paling lambat dan
ByteArrayOutputStream
adalah yang tercepat solusi:Jadi pertama di sini adalah metode terbaik:
Hasil Benchmark, dari 20 MB random byte dalam siklus 20
Waktu dalam milidetik
Acuan kode sumber
I'd gunakan beberapa Java 8 trik.
Pada dasarnya sama seperti beberapa jawaban lain kecuali lebih ringkas.
Aku berlari beberapa waktu tes karena waktu penting, selalu.
Saya berusaha untuk mendapatkan respon menjadi String dengan 3 cara yang berbeda. (ditampilkan di bawah)
Saya mencoba menangkap blok untuk kepentingan dibaca.
Untuk memberikan konteks, ini adalah kode sebelumnya untuk semua 3 pendekatan:
1)
2)
3)
Jadi, setelah menjalankan 500 tes pada masing-masing pendekatan dengan permintaan yang sama/data tanggapan, berikut ini adalah angka-angka. Sekali lagi, ini adalah temuan saya dan temuan anda mungkin tidak persis sama, tapi aku menulis ini untuk memberikan beberapa indikasi lain dari efisiensi perbedaan dari pendekatan ini.
Peringkat:
Pendekatan #1
Pendekatan #3 - 2.6% lebih lambat dari #1
Pendekatan #2 - 4.3% lebih lambat dari #1
Setiap pendekatan ini merupakan solusi yang tepat untuk meraih respon dan menciptakan sebuah String dari itu.
Jawa murni solusi menggunakan Streams, bekerja sejak Java 8.
Seperti yang disebutkan oleh Christoffer Hammarström di bawah jawaban hal ini lebih aman untuk secara eksplisit menentukan Charset. I. e. Yang InputStreamReader konstruktor bisa menjadi perubahan sebagai berikut:
Berikut ini's lebih-atau-kurang sampath's jawaban, dibersihkan sedikit dan direpresentasikan sebagai fungsi:
Jika anda merasa petualang, anda bisa mencampur Scala dan Jawa dan end up dengan ini:
Pencampuran Java dan Scala kode dan perpustakaan itu's manfaat.
Lihat keterangan lengkap di sini: https://stackoverflow.com/q/5221524/828757
Jika anda dapat't menggunakan Commons IO (FileUtils/IOUtils/CopyUtils), di sini's contoh menggunakan BufferedReader untuk membaca file baris demi baris:
Atau jika anda ingin baku, kecepatan angin dan I'd mengusulkan variasi pada apa yang Paul de Vrieze yang disarankan (yang menghindari menggunakan StringWriter (yang menggunakan StringBuffer internal):
Ini adalah jawaban yang diadaptasi dari
org.apache.commons.io.IOUtils
sumber code, bagi mereka yang ingin memiliki apache pelaksanaan tetapi tidak ingin seluruh perpustakaan.Pastikan untuk menutup aliran pada ujung jika anda menggunakan Stream Pembaca
EDIT: Pada JDK 7+, anda dapat menggunakan try-dengan-sumber daya yang membangun.