Trong Java, có phương pháp nào để đọc một dòng cụ thể từ một tệp không? Ví dụ: đọc dòng 32 hoặc bất kỳ số dòng nào khác.
Trong Java, có phương pháp nào để đọc một dòng cụ thể từ một tệp không? Ví dụ: đọc dòng 32 hoặc bất kỳ số dòng nào khác.
Câu trả lời:
Trừ khi bạn đã có kiến thức trước đó về các dòng trong tệp, không có cách nào để truy cập trực tiếp vào dòng thứ 32 mà không đọc 31 dòng trước đó.
Điều đó đúng cho tất cả các ngôn ngữ và tất cả các hệ thống tệp hiện đại.
Vì vậy, hiệu quả là bạn sẽ chỉ cần đọc các dòng cho đến khi bạn tìm thấy dòng thứ 32.
Đối với các tệp nhỏ:
String line32 = Files.readAllLines(Paths.get("file.txt")).get(32)
Đối với các tệp lớn:
try (Stream<String> lines = Files.lines(Paths.get("file.txt"))) {
line32 = lines.skip(31).findFirst().get();
}
Tôi không biết, nhưng những gì bạn có thể làm là lặp lại 31 dòng đầu tiên mà không làm gì bằng cách sử dụng hàm readline () của 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();
Tất nhiên, Joachim đã đúng và một cách triển khai thay thế cho Chris '(chỉ dành cho các tệp nhỏ vì nó tải toàn bộ tệp) có thể là sử dụng commons-io từ Apache (mặc dù có thể bạn không muốn giới thiệu một phần phụ thuộc mới chỉ dành cho điều này, nếu bạn thấy nó cũng hữu ích cho những thứ khác, nó có thể có ý nghĩa).
Ví dụ:
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)
Bạn có thể thử lập chỉ mục-tệp-đọc (Giấy phép Apache 2.0). Lớp IndexedFileReader có một phương thức gọi là readLines (int from, int to) trả về một Bản đồ sắp xếp có khóa là số dòng và giá trị là dòng đã được đọc.
Thí dụ:
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]"));
Ví dụ trên đọc một tệp văn bản gồm 50 dòng ở định dạng sau:
[1] The quick brown fox jumped over the lazy dog ODD
[2] The quick brown fox jumped over the lazy dog EVEN
Disclamer: Tôi đã viết thư viện này
Mặc dù như đã nói trong các câu trả lời khác, không thể đến dòng chính xác mà không biết phần bù (con trỏ) trước đó. Vì vậy, tôi đã đạt được điều này bằng cách tạo một tệp chỉ mục tạm thời sẽ lưu trữ các giá trị bù đắp của mọi dòng. Nếu tệp đủ nhỏ, bạn có thể chỉ lưu các chỉ mục (offset) trong bộ nhớ mà không cần tệp riêng cho nó.
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();
Ngoài ra, hãy truy cập tài liệu java để biết thêm thông tin: https://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html#mode
Độ phức tạp : Đây là O (n) vì nó đọc toàn bộ tệp một lần. Vui lòng lưu ý các yêu cầu về bộ nhớ. Nếu nó quá lớn để có trong bộ nhớ, hãy tạo một tệp tạm thời để lưu trữ các phần bù thay vì ArrayList như được hiển thị ở trên.
Lưu ý : Nếu tất cả những gì bạn muốn trong dòng '32', bạn chỉ cần gọi readLine () cũng có sẵn thông qua các lớp khác '32' lần. Cách tiếp cận trên rất hữu ích nếu bạn muốn lấy một dòng cụ thể (tất nhiên là dựa trên số dòng) nhiều lần.
Cảm ơn !
Cách khác.
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);
}
Nếu bạn đang nói về một tệp văn bản, thì thực sự không có cách nào để làm điều này mà không đọc tất cả các dòng đứng trước nó - Sau cùng, các dòng được xác định bởi sự hiện diện của một dòng mới, vì vậy nó phải được đọc.
Sử dụng một luồng hỗ trợ dòng đọc và chỉ đọc những dòng X-1 đầu tiên và kết xuất kết quả, sau đó xử lý dòng tiếp theo.
Trong Java 8,
Đối với các tệp nhỏ:
String line = Files.readAllLines(Paths.get("file.txt")).get(n);
Đối với các tệp lớn:
String line;
try (Stream<String> lines = Files.lines(Paths.get("file.txt"))) {
line = lines.skip(n).findFirst().get();
}
Trong Java 7
String line;
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
for (int i = 0; i < n; i++)
br.readLine();
line = br.readLine();
}
Nguồn: Đang đọc dòng thứ n từ tệp
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;
}
Nó hoạt động cho tôi: Tôi đã kết hợp câu trả lời của Đọc một tệp văn bản đơn giản
Nhưng thay vì trả về một Chuỗi, tôi đang trả về một Danh sách chuỗi liên kết. Sau đó, tôi có thể chọn dòng mà tôi muốn.
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;
}
Sử dụng mã này:
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);
}
}
Bạn có thể sử dụng LineNumberReader thay vì BufferedReader. Đi qua api. Bạn có thể tìm thấy các phương thức setLineNumber và getLineNumber.
Bạn cũng có thể xem qua LineNumberReader, lớp con của BufferedReader. Cùng với phương thức readline, nó cũng có các phương thức setter / getter để truy cập số dòng. Rất hữu ích để theo dõi số dòng đã đọc, trong khi đọc dữ liệu từ tệp.
bạn có thể sử dụng chức năng bỏ qua () để bỏ qua các dòng bắt đầu.
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);
}
Tất cả đều sai Tôi chỉ viết điều này trong khoảng 10 giây. Với điều này, tôi quản lý để chỉ gọi object.getQuestion ("linenumber") trong phương thức chính để trả về bất kỳ dòng nào tôi muốn.
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; }}