Я знаю, что очень опаздываю, но если кто-то нашел этот вопрос: обратите внимание, что файл - это просто последовательность байтов. А новая строка - это просто символ (два в Windows), а символ - это всего один (или несколько, в зависимости от кодировки) байт. И, не имея индекса позиций байта в файле, единственный способ узнать, где находятся эти байты, - это прочитать его и найти. (это не значит, что вам нужно загружать в память весь файл).
szgal
Ответы:
72
Если у вас нет предварительных знаний о строках в файле, невозможно получить прямой доступ к 32-й строке, не прочитав 31 предыдущую строку.
Это верно для всех языков и всех современных файловых систем.
Так эффективно вы просто читаете строки, пока не найдете 32-ю строку.
Это возвращает java.nio.charset.MalformedInputException: Длина входного = 1 при использовании с пропуском значение равно 1
canadiancreed
Это не проблема с кодом, который я опубликовал, это проблема с кодировкой вашего файла. См. Этот пост .
aioobe 01
4
«Обратите внимание, что этот метод предназначен для простых случаев, когда удобно читать все строки за одну операцию. Он не предназначен для чтения в больших файлах». - Документация по файлам Files.readAllLines ()
PragmaticProgrammer
Для следующего кода требуется уровень API 26 в android. Если наш минимум меньше этого уровня, то он не работает
Али Азаз Алам
38
Не то, чтобы я знал об этом, но вы могли бы пройти по первой 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();
Обратите внимание, что здесь вы читаете строку номер 30, которая является 31-й строкой, потому что мы начинаем номера строк с 0. Поэтому я бы предложил изменить ее, чтобы она точно соответствовала вопросу.
kiedysktos
15
Иоахим, конечно, прав, и альтернативная реализация Криса (для небольших файлов только потому, что он загружает весь файл) может заключаться в использовании commons-io из Apache (хотя, возможно, вы можете не захотеть вводить новую зависимость только для это, если вы сочтете это полезным и для других вещей, это может иметь смысл).
Хотя это загрузит весь файл в память перед переходом к 32-й строке, что может оказаться непрактичным с большим файлом и будет медленнее, чем чтение утилиты, обнаружив 32-ю строку ...
beny23
Справедливо, да. Я использовал это в тестовых примерах, где файлы тестирования были небольшими, но для больших файлов, согласился, не лучший подход.
Чарли Коллинз,
Обновлен ответ, чтобы отразить, что FileUtils - плохая идея в этом случае использования, если у вас большой файл и вам не нужно ничего, кроме строки X.
Чарли Коллинз,
11
Вы можете попробовать программу чтения индексированных файлов (Apache License 2.0). Класс IndexedFileReader имеет метод с именем readLines (int from, int to), который возвращает SortedMap, ключ которого является номером строки, а значение - строкой, которая была прочитана.
Хотя, как сказано в других ответах, невозможно добраться до точной строки, не зная смещения (указателя) раньше. Итак, я добился этого, создав временный индексный файл, в котором будут храниться значения смещения каждой строки. Если файл достаточно мал, вы можете просто сохранить индексы (смещение) в памяти, не требуя для него отдельного файла.
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();
Сложность : это O (n), поскольку он читает весь файл один раз. Обратите внимание на требования к памяти. Если он слишком велик для хранения в памяти, создайте временный файл, в котором будут храниться смещения вместо ArrayList, как показано выше.
Примечание : если все, что вам нужно, в строке «32», вам просто нужно вызвать readLine (), также доступный через другие классы, «32» раз. Вышеупомянутый подход полезен, если вы хотите получить определенную строку (на основе, конечно, номера строки) несколько раз.
Чтобы заставить приведенный выше код работать, нужно что-то отредактировать. И если кому-то нужна кодировка, вам действительно стоит прочитать это: stackoverflow.com/a/37275357/3198960
Нет, если в этом формате файла длина строк не определена заранее (например, все строки с фиксированной длиной), вам придется перебирать строку за строкой для их подсчета.
Если вы говорите о текстовом файле, то на самом деле нет способа сделать это, не прочитав все строки, предшествующие ему - в конце концов, строки определяются наличием новой строки, поэтому ее нужно прочитать.
Используйте поток, поддерживающий строку чтения, и просто прочтите первые строки X-1 и выгрузите результаты, а затем обработайте следующую.
String line;
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
for (int i = 0; i < n; i++)
br.readLine();
line = br.readLine();
}
Но вместо возврата String я возвращаю LinkedList of Strings. Затем я могу выбрать нужную строку.
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;
}
не помогает - вам все равно нужно прочитать все строки раньше ... кроме того, что вы обманываете и устанавливаете первую строку на 32 <g>
kleopatra
0
Вы также можете взглянуть на LineNumberReader, подкласс BufferedReader. Наряду с методом readline у него также есть методы setter / getter для доступа к номеру строки. Очень полезно отслеживать количество прочитанных строк при чтении данных из файла.
ЛЕГКИЙ СПОСОБ - чтение строки по номеру строки. Скажем, номер строки начинается с 1 до нуля.
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
}
}
Все они ошибаются. Я написал это примерно за 10 секунд. При этом мне удалось просто вызвать object.getQuestion ("lnenumber") в основном методе, чтобы вернуть любую строку, которую я хочу.
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; }}
Ответы:
Если у вас нет предварительных знаний о строках в файле, невозможно получить прямой доступ к 32-й строке, не прочитав 31 предыдущую строку.
Это верно для всех языков и всех современных файловых систем.
Так эффективно вы просто читаете строки, пока не найдете 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(); }
источник
Не то, чтобы я знал об этом, но вы могли бы пройти по первой 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();
источник
Иоахим, конечно, прав, и альтернативная реализация Криса (для небольших файлов только потому, что он загружает весь файл) может заключаться в использовании 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 , java.lang.String)
источник
Вы можете попробовать программу чтения индексированных файлов (Apache License 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]"));
В приведенном выше примере читается текстовый файл, состоящий из 50 строк, в следующем формате:
[1] The quick brown fox jumped over the lazy dog ODD [2] The quick brown fox jumped over the lazy dog EVEN
Отказ от ответственности: я написал эту библиотеку
источник
Хотя, как сказано в других ответах, невозможно добраться до точной строки, не зная смещения (указателя) раньше. Итак, я добился этого, создав временный индексный файл, в котором будут храниться значения смещения каждой строки. Если файл достаточно мал, вы можете просто сохранить индексы (смещение) в памяти, не требуя для него отдельного файла.
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); }
источник
Нет, если в этом формате файла длина строк не определена заранее (например, все строки с фиксированной длиной), вам придется перебирать строку за строкой для их подсчета.
источник
Если вы говорите о текстовом файле, то на самом деле нет способа сделать это, не прочитав все строки, предшествующие ему - в конце концов, строки определяются наличием новой строки, поэтому ее нужно прочитать.
Используйте поток, поддерживающий строку чтения, и просто прочтите первые строки X-1 и выгрузите результаты, а затем обработайте следующую.
источник
В 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-й строки из файла
источник
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; }
источник
У меня это работает: я объединил ответ чтения простого текстового файла
Но вместо возврата String я возвращаю LinkedList of Strings. Затем я могу выбрать нужную строку.
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; }
источник
Используйте этот код:
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 для доступа к номеру строки. Очень полезно отслеживать количество прочитанных строк при чтении данных из файла.
источник
вы можете использовать функцию 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); }
источник
ЛЕГКИЙ СПОСОБ - чтение строки по номеру строки. Скажем, номер строки начинается с 1 до нуля.
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 } }
источник
Все они ошибаются. Я написал это примерно за 10 секунд. При этом мне удалось просто вызвать object.getQuestion ("lnenumber") в основном методе, чтобы вернуть любую строку, которую я хочу.
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; }}
источник