Saya tahu saya sangat terlambat, tetapi jika seseorang menemukan pertanyaan ini: Perhatikan bahwa file hanyalah urutan byte. Dan baris baru hanyalah satu karakter (dua di Windows), dan karakter hanya satu (atau lebih, tergantung pada pengkodean) byte. Dan, tanpa memiliki indeks posisi byte dalam file, satu-satunya cara untuk mengetahui di mana byte tersebut berada adalah dengan membacanya dan mencarinya. (ini tidak berarti bahwa Anda harus memuat seluruh file ke dalam memori).
szgal
Jawaban:
72
Kecuali Anda memiliki pengetahuan sebelumnya tentang baris di file, tidak ada cara untuk langsung mengakses baris ke-32 tanpa membaca 31 baris sebelumnya.
Itu benar untuk semua bahasa dan semua sistem file modern.
Jadi secara efektif Anda hanya akan membaca baris sampai Anda menemukan baris ke-32.
Ini mengembalikan java.nio.charset.MalformedInputException: Panjang input = 1 saat digunakan dengan nilai lewati 1
canadiancreed
Itu bukan masalah dengan kode yang saya posting, ini masalah dengan pengkodean file Anda. Lihat posting ini .
aioobe
4
"Perhatikan bahwa metode ini ditujukan untuk kasus sederhana yang nyaman untuk membaca semua baris dalam satu operasi. Metode ini tidak dimaksudkan untuk membaca dalam file besar." - Javadoc of Files.readAllLines ()
PragmaticProgrammer
Kode berikut membutuhkan API level 26 di android. Jika min kami kurang dari level ini maka itu tidak berfungsi
Ali Azaz Alam
38
Bukan yang saya tahu, tetapi yang dapat Anda lakukan adalah melakukan loop melalui 31 baris pertama tanpa melakukan apa pun menggunakan fungsi readline () dari BufferedReader
FileInputStream fs= new FileInputStream("someFile.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fs));
for(int i = 0; i < 31; ++i)
br.readLine();
String lineIWant = br.readLine();
Harap dicatat bahwa di sini Anda membaca nomor baris 30, yang merupakan baris ke-31 karena kita memulai nomor baris dari 0. Jadi saya sarankan untuk mengubahnya agar cocok dengan pertanyaannya.
kiedysktos
15
Joachim benar, tentu saja, dan implementasi alternatif untuk Chris '(untuk file kecil hanya karena memuat seluruh file) mungkin menggunakan commons-io dari Apache (meskipun Anda mungkin tidak ingin memperkenalkan dependensi baru hanya untuk ini, jika Anda merasa berguna untuk hal lain juga, itu bisa masuk akal).
Meskipun itu akan memuat seluruh file ke dalam memori sebelum pergi ke baris ke-32, yang mungkin tidak praktis dengan file besar dan akan lebih lambat daripada membaca dengan menemukan baris ke-32 ...
beny23
Poin yang adil, ya. Saya telah menggunakan itu dalam kasus uji, di mana file pengujian kecil, pada file besar, setuju, bukan pendekatan yang baik.
Charlie Collins
Posting jawaban yang diperbarui untuk mencerminkan bahwa FileUtils adalah ide buruk dalam kasus penggunaan ini jika Anda memiliki file besar dan tidak memerlukan apa pun di luar baris X.
Charlie Collins
11
Anda dapat mencoba indexed-file-reader (Apache License 2.0). Kelas IndexedFileReader memiliki metode yang disebut readLines (int from, int to) yang mengembalikan SortedMap yang kuncinya adalah nomor baris dan nilainya adalah baris yang telah dibaca.
Meskipun seperti yang dikatakan dalam jawaban lain, tidak mungkin untuk sampai ke baris yang tepat tanpa mengetahui offset (penunjuk) sebelumnya. Jadi, saya telah mencapai ini dengan membuat file indeks sementara yang akan menyimpan nilai offset setiap baris. Jika file cukup kecil, Anda bisa menyimpan indeks (offset) di memori tanpa memerlukan file terpisah untuk itu.
The offsets can be calculated by using the RandomAccessFile
RandomAccessFile raf = new RandomAccessFile("myFile.txt","r");
//above 'r' means open in read only mode
ArrayList<Integer> arrayList = new ArrayList<Integer>();
String cur_line = "";
while((cur_line=raf.readLine())!=null)
{
arrayList.add(raf.getFilePointer());
}
//Print the 32 line//Seeks the file to the particular location from where our '32' line starts
raf.seek(raf.seek(arrayList.get(31));
System.out.println(raf.readLine());
raf.close();
Kompleksitas : Ini adalah O (n) karena membaca seluruh file sekali. Harap perhatikan persyaratan memori. Jika terlalu besar untuk disimpan di memori, buat file sementara yang menyimpan offset, bukan ArrayList seperti yang ditunjukkan di atas.
Catatan : Jika semua yang Anda inginkan di baris '32', Anda hanya perlu memanggil readLine () yang juga tersedia melalui kelas lain '32' kali. Pendekatan di atas berguna jika Anda ingin mendapatkan baris tertentu (tentu saja berdasarkan nomor baris) beberapa kali.
Ada sesuatu yang perlu diedit untuk membuat kode di atas berfungsi. Dan jika seseorang membutuhkan charset yang bersangkutan, Anda benar-benar harus membaca ini: stackoverflow.com/a/37275357/3198960
Tidak, kecuali dalam format file itu panjang baris sudah ditentukan sebelumnya (misalnya semua baris dengan panjang tetap), Anda harus mengulang baris demi baris untuk menghitungnya.
Jika Anda berbicara tentang file teks, maka tidak ada cara untuk melakukan ini tanpa membaca semua baris yang mendahuluinya - Bagaimanapun, baris ditentukan oleh keberadaan baris baru, jadi itu harus dibaca.
Gunakan aliran yang mendukung garis baca, dan cukup baca baris X-1 pertama dan buang hasilnya, lalu proses baris berikutnya.
String line;
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
for (int i = 0; i < n; i++)
br.readLine();
line = br.readLine();
}
Tapi bukannya mengembalikan String saya mengembalikan LinkedList of Strings. Kemudian saya dapat memilih jalur yang saya inginkan.
publicstatic LinkedList<String> readFromAssets(Context context, String filename)throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(context.getAssets().open(filename)));
LinkedList<String>linkedList = new LinkedList<>();
// do reading, usually loop until end of file reading
StringBuilder sb = new StringBuilder();
String mLine = reader.readLine();
while (mLine != null) {
linkedList.add(mLine);
sb.append(mLine); // process line
mLine = reader.readLine();
}
reader.close();
return linkedList;
}
tidak membantu - Anda masih harus membaca semua baris sebelumnya ... kecuali Anda menipu dan menyetel baris pertama ke 32 <g>
kleopatra
0
Anda juga dapat melihat LineNumberReader, subkelas BufferedReader. Seiring dengan metode readline, ia juga memiliki metode penyetel / pengambil untuk mengakses nomor baris. Sangat berguna untuk melacak jumlah baris yang dibaca, saat membaca data dari file.
CARA MUDAH - Membaca baris menggunakan nomor baris. Misalkan nomor baris dimulai dari 1 sampai null.
publicclassTextFileAssignmentOct{
privatevoidreadData(int rowNum, BufferedReader br)throws IOException {
int n=1; //Line number starts from 1
String row;
while((row=br.readLine()) != null) { // Reads every lineif (n == rowNum) { // When Line number matches with which you want to read
System.out.println(row);
}
n++; //This increments Line number
}
}
publicstaticvoidmain(String[] args)throws IOException {
File f = new File("../JavaPractice/FileRead.txt");
FileReader fr = new FileReader(f);
BufferedReader br = new BufferedReader(fr);
TextFileAssignmentOct txf = new TextFileAssignmentOct();
txf.readData(4, br); //Read a Specific Line using Line number and Passing buffered reader
}
}
Semuanya salah. Saya baru saja menulis ini dalam waktu sekitar 10 detik. Dengan ini saya berhasil memanggil object.getQuestion ("linenumber") dalam metode utama untuk mengembalikan baris apa pun yang saya inginkan.
publicclassQuestions{
File file = new File("Question2Files/triviagame1.txt");
publicQuestions(){
}
public String getQuestion(int numLine)throws IOException {
BufferedReader br = new BufferedReader(new FileReader(file));
String line = "";
for(int i = 0; i < numLine; i++) {
line = br.readLine();
}
return line; }}
Jawaban:
Kecuali Anda memiliki pengetahuan sebelumnya tentang baris di file, tidak ada cara untuk langsung mengakses baris ke-32 tanpa membaca 31 baris sebelumnya.
Itu benar untuk semua bahasa dan semua sistem file modern.
Jadi secara efektif Anda hanya akan membaca baris sampai Anda menemukan baris ke-32.
sumber
Untuk file kecil:
String line32 = Files.readAllLines(Paths.get("file.txt")).get(32)
Untuk file besar:
try (Stream<String> lines = Files.lines(Paths.get("file.txt"))) { line32 = lines.skip(31).findFirst().get(); }
sumber
Bukan yang saya tahu, tetapi yang dapat Anda lakukan adalah melakukan loop melalui 31 baris pertama tanpa melakukan apa pun menggunakan fungsi readline () dari BufferedReader
FileInputStream fs= new FileInputStream("someFile.txt"); BufferedReader br = new BufferedReader(new InputStreamReader(fs)); for(int i = 0; i < 31; ++i) br.readLine(); String lineIWant = br.readLine();
sumber
Joachim benar, tentu saja, dan implementasi alternatif untuk Chris '(untuk file kecil hanya karena memuat seluruh file) mungkin menggunakan commons-io dari Apache (meskipun Anda mungkin tidak ingin memperkenalkan dependensi baru hanya untuk ini, jika Anda merasa berguna untuk hal lain juga, itu bisa masuk akal).
Sebagai contoh:
String line32 = (String) FileUtils.readLines(file).get(31);
http://commons.apache.org/io/api-release/org/apache/commons/io/FileUtils.html#readLines(java.io.File , java.lang.String)
sumber
Anda dapat mencoba indexed-file-reader (Apache License 2.0). Kelas IndexedFileReader memiliki metode yang disebut readLines (int from, int to) yang mengembalikan SortedMap yang kuncinya adalah nomor baris dan nilainya adalah baris yang telah dibaca.
Contoh:
File file = new File("src/test/resources/file.txt"); reader = new IndexedFileReader(file); lines = reader.readLines(6, 10); assertNotNull("Null result.", lines); assertEquals("Incorrect length.", 5, lines.size()); assertTrue("Incorrect value.", lines.get(6).startsWith("[6]")); assertTrue("Incorrect value.", lines.get(7).startsWith("[7]")); assertTrue("Incorrect value.", lines.get(8).startsWith("[8]")); assertTrue("Incorrect value.", lines.get(9).startsWith("[9]")); assertTrue("Incorrect value.", lines.get(10).startsWith("[10]"));
Contoh di atas membaca file teks yang terdiri dari 50 baris dalam format berikut:
[1] The quick brown fox jumped over the lazy dog ODD [2] The quick brown fox jumped over the lazy dog EVEN
Penolakan: Saya menulis perpustakaan ini
sumber
Meskipun seperti yang dikatakan dalam jawaban lain, tidak mungkin untuk sampai ke baris yang tepat tanpa mengetahui offset (penunjuk) sebelumnya. Jadi, saya telah mencapai ini dengan membuat file indeks sementara yang akan menyimpan nilai offset setiap baris. Jika file cukup kecil, Anda bisa menyimpan indeks (offset) di memori tanpa memerlukan file terpisah untuk itu.
The offsets can be calculated by using the RandomAccessFile RandomAccessFile raf = new RandomAccessFile("myFile.txt","r"); //above 'r' means open in read only mode ArrayList<Integer> arrayList = new ArrayList<Integer>(); String cur_line = ""; while((cur_line=raf.readLine())!=null) { arrayList.add(raf.getFilePointer()); } //Print the 32 line //Seeks the file to the particular location from where our '32' line starts raf.seek(raf.seek(arrayList.get(31)); System.out.println(raf.readLine()); raf.close();
Kunjungi juga dokumen java untuk informasi lebih lanjut: https://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html#mode
Kompleksitas : Ini adalah O (n) karena membaca seluruh file sekali. Harap perhatikan persyaratan memori. Jika terlalu besar untuk disimpan di memori, buat file sementara yang menyimpan offset, bukan ArrayList seperti yang ditunjukkan di atas.
Catatan : Jika semua yang Anda inginkan di baris '32', Anda hanya perlu memanggil readLine () yang juga tersedia melalui kelas lain '32' kali. Pendekatan di atas berguna jika Anda ingin mendapatkan baris tertentu (tentu saja berdasarkan nomor baris) beberapa kali.
Terima kasih!
sumber
Cara lain.
try (BufferedReader reader = Files.newBufferedReader( Paths.get("file.txt"), StandardCharsets.UTF_8)) { List<String> line = reader.lines() .skip(31) .limit(1) .collect(Collectors.toList()); line.stream().forEach(System.out::println); }
sumber
Tidak, kecuali dalam format file itu panjang baris sudah ditentukan sebelumnya (misalnya semua baris dengan panjang tetap), Anda harus mengulang baris demi baris untuk menghitungnya.
sumber
Jika Anda berbicara tentang file teks, maka tidak ada cara untuk melakukan ini tanpa membaca semua baris yang mendahuluinya - Bagaimanapun, baris ditentukan oleh keberadaan baris baru, jadi itu harus dibaca.
Gunakan aliran yang mendukung garis baca, dan cukup baca baris X-1 pertama dan buang hasilnya, lalu proses baris berikutnya.
sumber
Di Jawa 8,
Untuk file kecil:
String line = Files.readAllLines(Paths.get("file.txt")).get(n);
Untuk file besar:
String line; try (Stream<String> lines = Files.lines(Paths.get("file.txt"))) { line = lines.skip(n).findFirst().get(); }
Di Jawa 7
String line; try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) { for (int i = 0; i < n; i++) br.readLine(); line = br.readLine(); }
Sumber: Membaca baris ke-n dari file
sumber
public String readLine(int line){ FileReader tempFileReader = null; BufferedReader tempBufferedReader = null; try { tempFileReader = new FileReader(textFile); tempBufferedReader = new BufferedReader(tempFileReader); } catch (Exception e) { } String returnStr = "ERROR"; for(int i = 0; i < line - 1; i++){ try { tempBufferedReader.readLine(); } catch (Exception e) { } } try { returnStr = tempBufferedReader.readLine(); } catch (Exception e) { } return returnStr; }
sumber
Ini bekerja untuk saya: Saya telah menggabungkan jawaban Membaca file teks sederhana
Tapi bukannya mengembalikan String saya mengembalikan LinkedList of Strings. Kemudian saya dapat memilih jalur yang saya inginkan.
public static LinkedList<String> readFromAssets(Context context, String filename) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(context.getAssets().open(filename))); LinkedList<String>linkedList = new LinkedList<>(); // do reading, usually loop until end of file reading StringBuilder sb = new StringBuilder(); String mLine = reader.readLine(); while (mLine != null) { linkedList.add(mLine); sb.append(mLine); // process line mLine = reader.readLine(); } reader.close(); return linkedList; }
sumber
Gunakan kode ini:
import java.nio.file.Files; import java.nio.file.Paths; public class FileWork { public static void main(String[] args) throws IOException { String line = Files.readAllLines(Paths.get("D:/abc.txt")).get(1); System.out.println(line); } }
sumber
Anda dapat menggunakan LineNumberReader sebagai ganti BufferedReader. Pergi melalui api. Anda dapat menemukan metode setLineNumber dan getLineNumber.
sumber
Anda juga dapat melihat LineNumberReader, subkelas BufferedReader. Seiring dengan metode readline, ia juga memiliki metode penyetel / pengambil untuk mengakses nomor baris. Sangat berguna untuk melacak jumlah baris yang dibaca, saat membaca data dari file.
sumber
Anda dapat menggunakan fungsi skip () untuk melewati baris dari awal.
public static void readFile(String filePath, long lineNum) { List<String> list = new ArrayList<>(); long totalLines, startLine = 0; try (Stream<String> lines = Files.lines(Paths.get(filePath))) { totalLines = Files.lines(Paths.get(filePath)).count(); startLine = totalLines - lineNum; // Stream<String> line32 = lines.skip(((startLine)+1)); list = lines.skip(startLine).collect(Collectors.toList()); // lines.forEach(list::add); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } list.forEach(System.out::println); }
sumber
CARA MUDAH - Membaca baris menggunakan nomor baris. Misalkan nomor baris dimulai dari 1 sampai null.
public class TextFileAssignmentOct { private void readData(int rowNum, BufferedReader br) throws IOException { int n=1; //Line number starts from 1 String row; while((row=br.readLine()) != null) { // Reads every line if (n == rowNum) { // When Line number matches with which you want to read System.out.println(row); } n++; //This increments Line number } } public static void main(String[] args) throws IOException { File f = new File("../JavaPractice/FileRead.txt"); FileReader fr = new FileReader(f); BufferedReader br = new BufferedReader(fr); TextFileAssignmentOct txf = new TextFileAssignmentOct(); txf.readData(4, br); //Read a Specific Line using Line number and Passing buffered reader } }
sumber
Semuanya salah. Saya baru saja menulis ini dalam waktu sekitar 10 detik. Dengan ini saya berhasil memanggil object.getQuestion ("linenumber") dalam metode utama untuk mengembalikan baris apa pun yang saya inginkan.
public class Questions { File file = new File("Question2Files/triviagame1.txt"); public Questions() { } public String getQuestion(int numLine) throws IOException { BufferedReader br = new BufferedReader(new FileReader(file)); String line = ""; for(int i = 0; i < numLine; i++) { line = br.readLine(); } return line; }}
sumber