Как прочитать конкретную строку, используя конкретный номер строки из файла в Java?


в Java, есть ли способ, чтобы прочитать определенную строку из файла? Например, прочитайте строку 32 или любой другой номер строки.

17 74

17 ответов:

Если у вас нет предыдущих знаний о строках в файле, нет никакого способа напрямую получить доступ к 32-й строке, не читая 31 предыдущих строк.

Это справедливо для всех языков и всех современных файловых систем.

так эффективно вы будете просто читать строки, пока не найдете 32-й.

Java 8 решение:

файлы:

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

Не то, что я знаю, но то, что вы могли бы сделать, это цикл через первые 31 строки, ничего не делая с помощью функции readline() 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();

Joachim, конечно, прав, и альтернативная реализация Chris' (для небольших файлов только потому, что он загружает весь файл) может заключаться в использовании commons-io из Apache (хотя, возможно, вы не захотите вводить новую зависимость только для этого, если вы найдете ее полезной и для других вещей, хотя это может иметь смысл).

для пример:

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- Ява.ленг.Строка)

можно попробовать indexed-file-reader (Лицензия Apache 2.0). Класс IndexedFileReader имеет метод с именем readLines (int from, int to) который возвращает SortedMap, ключ которого является номером строки, а значение-это строка, которая была прочитана.

пример:

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]"));      
[1] The quick brown fox jumped over the lazy dog ODD
[2] The quick brown fox jumped over the lazy dog EVEN

Disclamer: я написал эту библиотеку

хотя, как сказано в других ответах, невозможно добраться до точной строки, не зная смещения ( указателя ) раньше. Итак, я достиг этого, создав временный индексный файл, который будет хранить значения смещения каждой строки. Если файл достаточно мал, вы можете просто хранить индексы ( смещение ) в памяти без необходимости отдельного файла для него.

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 docs для получения дополнительной информации информация: https://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html#mode

сложности: Это O (n), как он читает весь файл один раз. Обратите внимание на требования к памяти. Если он слишком большой, чтобы быть в памяти, а затем сделать временный файл, который хранит смещения вместо ArrayList, как показано выше.

Примечание : если все, что вы хотите в' 32 ' линии, вы просто должны вызвать readLine () также доступны через другие классы '32' раз. Приведенный выше подход полезен, если вы хотите получить определенную строку (на основе номера строки, конечно) несколько раз.

спасибо !

нет, если в этом формате файла длины строк не определены заранее (например, все строки с фиксированной длиной), вам придется перебирать строку за строкой, чтобы подсчитать их.

другой путь.

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

Если вы говорите о текстовом файле, то на самом деле нет способа сделать это без чтения всех строк, которые ему предшествуют - в конце концов, строки определяются наличием новой строки, поэтому ее нужно читать.

используйте поток, который поддерживает readline, и просто прочитайте первые строки X-1 и сбросьте результаты, а затем обработайте следующий.

это работает для меня: Я объединил ответ чтение простого текстового файла

но вместо того, чтобы возвращать строку, я возвращаюсь в LinkedList не строк. Затем я могу выбрать строку, которую я хочу.

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

В Java 8,

для небольших файлов:

String line = Files.readAllLines(Paths.get("file.txt")).get(n);

для больших файлов:

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

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

источник: чтение N-й строки из файла

используйте этот код:

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

}

вы можете использовать LineNumberReader вместо BufferedReader. Пройдите через api. Вы можете найти методы setLineNumber и getLineNumber.

вы также можете взглянуть на LineNumberReader, подкласс BufferedReader. Наряду с методом readline, он также имеет методы setter / getter для доступа к номеру строки. Очень полезно следить за количеством прочитанных строк, одновременно считывая данные из файла.

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

вы можете использовать функцию skip (), чтобы пропустить строки из начала.

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

}

они все неправы я просто написал это примерно за 10 секунд. С этим мне удалось просто вызвать объект.getQuestion ("linenumber") в основном методе возвращает любую строку, которую я хочу.

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