Saya telah menggunakan idiom di bawah ini untuk beberapa waktu sekarang. Dan itu tampaknya menjadi yang paling luas, setidaknya di situs yang saya kunjungi.
Apakah ada cara yang lebih baik / berbeda untuk membaca file menjadi string di Java?
private String readFile(String file) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader (file));
String line = null;
StringBuilder stringBuilder = new StringBuilder();
String ls = System.getProperty("line.separator");
try {
while((line = reader.readLine()) != null) {
stringBuilder.append(line);
stringBuilder.append(ls);
}
return stringBuilder.toString();
} finally {
reader.close();
}
}
byte[] Files.readAllBytes(file);
Kepada mereka, yang menyarankan solusi Pemindai 'satu baris': Tidakkah Anda perlu menutupnya?Jawaban:
Baca semua teks dari file
Java 11 menambahkan metode readString () untuk membaca file kecil sebagai
String
, mempertahankan terminator garis:Untuk versi antara Java 7 dan 11, berikut adalah idiom yang ringkas dan kuat, terbungkus dalam metode utilitas:
Baca baris teks dari file
Java 7 menambahkan metode kenyamanan untuk membaca file sebagai baris teks, direpresentasikan sebagai
List<String>
. Pendekatan ini "lossy" karena pemisah garis dilucuti dari akhir setiap baris.Java 8 menambahkan
Files.lines()
metode untuk menghasilkan aStream<String>
. Sekali lagi, metode ini lossy karena pemisah garis dilucuti. JikaIOException
ditemui saat membaca file, itu dibungkus dalamUncheckedIOException
, karenaStream
tidak menerima lambdas yang melempar pengecualian yang diperiksa.Ini
Stream
memang membutuhkanclose()
panggilan; ini tidak terdokumentasi dengan baik di API, dan saya curiga banyak orang yang bahkan tidak menyadariStream
adanyaclose()
metode. Pastikan untuk menggunakan blok ARM seperti yang ditunjukkan.Jika Anda bekerja dengan sumber selain file, Anda dapat menggunakan
lines()
metode ini diBufferedReader
sebagai gantinya.Pemanfaatan memori
Metode pertama, yang mempertahankan jeda baris, untuk sementara waktu membutuhkan memori beberapa kali ukuran file, karena untuk waktu yang singkat isi file mentah (array byte), dan karakter yang diterjemahkan (masing-masing adalah 16 bit bahkan jika dikodekan) sebagai 8 bit dalam file) berada di memori sekaligus. Itu paling aman untuk diterapkan ke file yang Anda tahu kecil relatif terhadap memori yang tersedia.
Metode kedua, membaca baris, biasanya lebih efisien memori, karena buffer byte input untuk decoding tidak perlu mengandung seluruh file. Namun, itu masih tidak cocok untuk file yang sangat besar relatif terhadap memori yang tersedia.
Untuk membaca file besar, Anda memerlukan desain yang berbeda untuk program Anda, yang membaca sepotong teks dari stream, memprosesnya, dan kemudian pindah ke yang berikutnya, menggunakan kembali blok memori berukuran tetap yang sama. Di sini, "besar" tergantung pada spesifikasi komputer. Saat ini, ambang ini mungkin banyak RAM gigabytes. Metode ketiga, menggunakan a
Stream<String>
adalah salah satu cara untuk melakukan ini, jika input Anda "catatan" kebetulan menjadi baris individual. (MenggunakanreadLine()
metodeBufferedReader
adalah prosedur yang setara dengan pendekatan ini.)Pengkodean karakter
Satu hal yang hilang dari sampel dalam posting asli adalah pengkodean karakter. Ada beberapa kasus khusus di mana platform default adalah apa yang Anda inginkan, tetapi jarang, dan Anda harus dapat membenarkan pilihan Anda.
The
StandardCharsets
kelas mendefinisikan beberapa konstanta untuk pengkodean diperlukan dari semua runtimes Jawa:Platform standar tersedia dari yang
Charset
kelas itu sendiri:Catatan: Jawaban ini sebagian besar menggantikan versi Java 6 saya. Utilitas Java 7 dengan aman menyederhanakan kode, dan jawaban lama, yang menggunakan buffer byte yang dipetakan, mencegah file yang dibaca tidak dihapus sampai buffer yang dipetakan dikumpulkan dari sampah. Anda dapat melihat versi lama melalui tautan "diedit" pada jawaban ini.
sumber
FileChannel#map
secara umum tidak dapat digunakan.Jika Anda ingin menggunakan perpustakaan eksternal, periksa Apache Commons IO (200KB JAR). Ini berisi
org.apache.commons.io.FileUtils.readFileToString()
metode yang memungkinkan Anda untuk membaca keseluruhanFile
menjadiString
dengan satu baris kode.Contoh:
sumber
Solusi yang sangat ramping berdasarkan
Scanner
:Atau, jika Anda ingin mengatur rangkaian karakter:
Atau, dengan blok coba-dengan-sumber daya , yang akan memanggil
scanner.close()
Anda:Ingat bahwa
Scanner
konstruktor dapat melemparIOException
. Dan jangan lupa untuk mengimporjava.io
danjava.util
.Sumber: blog Pat Niemeyer
sumber
java.util.NoSuchElementException
.sejak java 7 Anda bisa melakukannya dengan cara ini.
sumber
Jika Anda mencari alternatif yang tidak melibatkan perpustakaan pihak ketiga (mis. Commons I / O ), Anda bisa menggunakan kelas Scanner :
sumber
Scanner scanner = new Scanner((Readable) new BufferedReader(new FileReader(file)));
. Kalau tidak, Anda hanya dapat menangkap sebagian file.Jambu biji memiliki metode yang mirip dengan yang ada di Commons IOUtils yang disebutkan oleh Willi aus Rohr:
EDIT oleh PiggyPiglet
Files#toString
sudah usang, dan akan dihapus Octobor 2019. Sebagai gantinya gunakanFiles.asCharSource(new File(path), StandardCharsets.UTF_8).read();
EDIT oleh Oscar Reyes
Ini adalah kode dasar (disederhanakan) pada pustaka yang dikutip:
Sunting (oleh Jonik): Di atas tidak cocok dengan kode sumber versi Jambu terbaru. Untuk sumber saat ini, lihat kelas Files , CharStreams , ByteSource dan CharSource dalam paket com.google.common.io .
sumber
Closer
di CharSource . Kode dalam jawaban bukanlah sumber aktual Guava saat ini........
sumber
new String(Files.readAllBytes(FileSystems.getDefault().getPath( filename)));
new String(Files.readAllBytes(Paths.get(filename)));
:-)Paths
tampaknya 1,7+ apa adanyaFileSystems
. (Jika Anda memerlukan pemrosesan string (pemrosesan paralel) Java 8 memiliki API Stream yang hebat.
Lebih banyak contoh tersedia dalam sampel JDK
sample/lambda/BulkDataOperations
yang dapat diunduh dari halaman unduhan Oracle Java SE 8Contoh satu liner lainnya
sumber
Kode itu akan menormalkan jeda baris, yang mungkin atau tidak mungkin benar-benar ingin Anda lakukan.
Berikut adalah alternatif yang tidak melakukan itu, dan yang (IMO) lebih mudah dipahami daripada kode NIO (meskipun masih menggunakan
java.nio.charset.Charset
):sumber
Kumpulkan semua cara yang mungkin untuk membaca File sebagai String dari Disk atau Jaringan.
Jambu: Google menggunakan kelas
Resources
,Files
APACHE - COMMONS IO menggunakan kelas IOUtils, FileUtils
Java 8 BufferReader menggunakan Stream API
Kelas Scanner dengan regex
\A
. yang cocok dengan awal input.Java 7 (
java.nio.file.Files.readAllBytes
)BufferedReader
menggunakanInputStreamReader
.Contoh dengan metode utama untuk mengakses metode di atas.
@Lihat
sumber
Jika itu file teks, mengapa tidak menggunakan apache commons-io ?
Ini memiliki metode berikut
Jika Anda ingin garis sebagai daftar gunakan
sumber
Sejak JDK 11:
sumber
Untuk membaca File sebagai biner dan mengonversi di akhir
sumber
Dengan Java 7, ini adalah pilihan saya untuk membaca file UTF-8:
Sejak Java 7, JDK memiliki
java.nio.file
API baru , yang menyediakan banyak pintasan, sehingga perpustakaan pihak ketiga tidak selalu diperlukan untuk operasi file yang sederhana.sumber
Java berupaya menjadi sangat umum dan fleksibel dalam semua hal yang dilakukannya. Akibatnya, sesuatu yang relatif sederhana dalam bahasa scripting (kode Anda akan diganti dengan "
open(file).read()
" dengan python) jauh lebih rumit. Tampaknya tidak ada cara yang lebih pendek untuk melakukannya, kecuali menggunakan perpustakaan eksternal (seperti yang disebutkan oleh Willi aus Rohr ). Pilihan Anda:Taruhan terbaik Anda mungkin yang ke-2, karena memiliki dependensi paling sedikit.
sumber
byte[] bytes = Files.readAllBytes(someFile.toPath());
Menggunakan JDK 8 atau lebih tinggi:
tidak ada perpustakaan eksternal yang digunakan
Anda dapat membuat objek String baru dari konten file (Menggunakan kelas dari
java.nio.file
paket):sumber
Ada variasi pada tema yang sama yang menggunakan loop untuk, alih-alih loop sementara, untuk membatasi ruang lingkup variabel baris. Apakah itu "lebih baik" adalah masalah selera pribadi.
sumber
line
variabel. Hasil edit menyatakannya dua kali, yang merupakan kesalahan kompilasi.Jika Anda tidak memiliki akses ke
Files
kelas, Anda dapat menggunakan solusi asli.sumber
Solusi fleksibel menggunakan IOUtils dari Apache commons-io dalam kombinasi dengan StringWriter :
Ini berfungsi dengan pembaca apa pun atau aliran input (tidak hanya dengan file), misalnya saat membaca dari URL.
sumber
Berhati-hatilah saat menggunakan
fileInputStream.available()
integer yang dikembalikan tidak harus mewakili ukuran file yang sebenarnya, tetapi jumlah byte yang ditebak oleh sistem harus dapat dibaca dari stream tanpa memblokir IO. Cara yang aman dan sederhana bisa terlihat seperti iniHarus dipertimbangkan bahwa pendekatan ini tidak cocok untuk pengkodean karakter multi-byte seperti UTF-8.
sumber
available()
metode, tidak ada jaminan bahwa akhir file tercapai dalam hal metode mengembalikan 0. Dalam hal ini Anda mungkin berakhir dengan file yang tidak lengkap. Yang lebih buruk, jumlah byte yang benar-benar dibaca bisa lebih kecil dari nilai yang dikembalikan olehavailable()
, dalam hal ini Anda mendapatkan output yang rusak.Yang ini menggunakan metode
RandomAccessFile.readFully
, tampaknya tersedia dari JDK 1.0!sumber
Anda dapat mencoba kelas Pemindai dan File, beberapa solusi garis
sumber
Pengguna
java.nio.Files
membaca semua baris file.sumber
sumber
cannot find symbol
.Saya belum dapat mengomentari entri lain, jadi saya akan meninggalkannya di sini.
Salah satu jawaban terbaik di sini ( https://stackoverflow.com/a/326448/1521167 ):
masih memiliki satu kelemahan. Itu selalu menempatkan baris baru char di akhir string, yang dapat menyebabkan beberapa bug aneh. Saran saya adalah mengubahnya menjadi:
sumber
Setelah Ctrl + F'ing setelah Scanner, saya pikir solusi Scanner juga harus terdaftar. Dalam mode yang paling mudah dibaca, bunyinya seperti ini:
Jika Anda menggunakan Java 7 atau yang lebih baru (dan memang harus demikian) pertimbangkan untuk menggunakan sumber daya coba-pakai untuk membuat kode lebih mudah dibaca. Tidak ada lagi hal-hal dot-close yang mengotori segalanya. Tapi itu kebanyakan metode pilihan gaya.
Saya memposting ini sebagian besar untuk penyelesaian, karena jika Anda perlu melakukan ini banyak, harus ada hal-hal di java.nio.file.Files yang seharusnya melakukan pekerjaan dengan lebih baik.
Saran saya adalah menggunakan Files # readAllBytes (Path) untuk mengambil semua byte, dan memasukkannya ke String baru (byte [] Charset) untuk mendapatkan sebuah String dari itu yang dapat Anda percayai. Charsets akan berarti bagi Anda selama hidup Anda, jadi waspadalah terhadap hal ini sekarang.
Yang lain telah memberikan kode dan barang, dan saya tidak ingin mencuri kemuliaan mereka. ;)
sumber
Menggunakan perpustakaan ini , ini adalah satu baris:
sumber
Juga jika file Anda berada di dalam toples, Anda juga dapat menggunakan ini:
Path harus dimulai dengan
/
misalnya jika toples AndaMaka Anda ingin memanggilnya seperti ini:
sumber
Dalam satu baris (Java 8), dengan asumsi Anda memiliki Reader:
sumber
Berdasarkan jawaban @ erickson, Anda dapat menggunakan:
sumber