[java] Java의 파일에서 특정 줄 번호를 사용하여 특정 줄을 읽는 방법은 무엇입니까?

Java에서 파일에서 특정 행을 읽는 방법이 있습니까? 예를 들어, 32 행 또는 다른 행 번호를 읽으십시오.



답변

파일의 줄에 대한 사전 지식이없는 한 이전 31 줄을 읽지 않고 32 번째 줄에 직접 액세스 할 수있는 방법은 없습니다.

이는 모든 언어와 모든 최신 파일 시스템에 해당됩니다.

그래서 효과적으로 당신은 32 번째 줄을 찾을 때까지 단순히 줄을 읽을 것입니다.


답변

작은 파일의 경우 :

String line32 = Files.readAllLines(Paths.get("file.txt")).get(32)

대용량 파일의 경우 :

try (Stream<String> lines = Files.lines(Paths.get("file.txt"))) {
    line32 = lines.skip(31).findFirst().get();
}


답변

내가 아는 것은 아니지만 BufferedReader의 readline () 함수를 사용하여 아무것도하지 않고 처음 31 줄을 반복하는 것입니다.

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


답변

물론 Joachim이 적합하며 Chris의 대체 구현 (전체 파일을로드하기 때문에 작은 파일에만 해당)은 Apache의 commons-io를 사용하는 것일 수 있습니다. 이것은 다른 것들에도 유용하다고 생각되면 이해가 될 수 있습니다).

예를 들면 :

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)


답변

인덱싱 된 파일 판독기 (Apache License 2.0)를 사용해 볼 수 있습니다 . IndexedFileReader 클래스에는 키가 줄 번호이고 값이 읽은 줄인 SortedMap을 반환하는 readLines (int from, int to) 라는 메서드 가 있습니다.

예:

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]"));      

위의 예는 다음 형식으로 50 줄로 구성된 텍스트 파일을 읽습니다.

[1] The quick brown fox jumped over the lazy dog ODD
[2] The quick brown fox jumped over the lazy dog EVEN

Disclamer :이 라이브러리를 작성했습니다.


답변

다른 답변에서 말했듯이 이전에 오프셋 (pointer)을 알지 못하면 정확한 줄을 얻을 수 없습니다. 그래서 저는 모든 라인의 오프셋 값을 저장하는 임시 인덱스 파일을 생성하여이를 달성했습니다. 파일이 충분히 작 으면 별도의 파일 없이도 인덱스 (offset)를 메모리에 저장할 수 있습니다.

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

자세한 내용은 Java 문서를 참조하십시오.
https://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html#mode

복잡성 : 전체 파일을 한 번 읽으므로 O (n)입니다. 메모리 요구 사항에 유의하십시오. 메모리에 저장하기에 너무 크면 위와 같이 ArrayList 대신 오프셋을 저장하는 임시 파일을 만드십시오.

노트 : ’32’줄에서 원하는 모든 것을 원한다면 다른 클래스를 통해 ’32’번 사용할 수있는 readLine ()을 호출하면됩니다. 위의 접근 방식은 특정 라인 (물론 라인 번호 기준)을 여러 번 가져 오려는 경우 유용합니다.

감사 !


답변

또 다른 방법.

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