In Java, is there any method to read a particular line from a file? For example, read line 32 or any other line number.
问题:
回答1:
Unless you have previous knowledge about the lines in the file, there\'s no way to directly access the 32nd line without reading the 31 previous lines.
That\'s true for all languages and all modern file systems.
So effectively you\'ll simply read lines until you\'ve found the 32nd one.
回答2:
Java 8 solution:
For small files:
String line32 = Files.readAllLines(Paths.get(\"file.txt\")).get(32)
For large files:
try (Stream<String> lines = Files.lines(Paths.get(\"file.txt\"))) {
line32 = lines.skip(31).findFirst().get();
}
回答3:
Not that I know of, but what you could do is loop through the first 31 lines doing nothing using the readline() function of 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();
回答4:
Joachim is right on, of course, and an alternate implementation to Chris\' (for small files only because it loads the entire file) might be to use commons-io from Apache (though arguably you might not want to introduce a new dependency just for this, if you find it useful for other stuff too though, it could make sense).
For example:
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)
回答5:
You may try indexed-file-reader (Apache License 2.0). The class IndexedFileReader has a method called readLines(int from, int to) which returns a SortedMap whose key is the line number and the value is the line that was read.
Example:
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]\"));
The above example reads a text file composed of 50 lines in the following format:
[1] The quick brown fox jumped over the lazy dog ODD
[2] The quick brown fox jumped over the lazy dog EVEN
Disclamer: I wrote this library
回答6:
Although as said in other answers, it is not possible to get to the exact line without knowing the offset ( pointer ) before. So, I\'ve achieved this by creating an temporary index file which would store the offset values of every line. If the file is small enough, you could just store the indexes ( offset ) in memory without needing a separate file for it.
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();
Also visit the java docs for more information: https://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html#mode
Complexity : This is O(n) as it reads the entire file once. Please be aware for the memory requirements. If it\'s too big to be in memory, then make a temporary file that stores the offsets instead of ArrayList as shown above.
Note : If all you want in \'32\' line, you just have to call the readLine() also available through other classes \'32\' times. The above approach is useful if you want to get the a specific line (based on line number of course) multiple times.
Thanks !
回答7:
No, unless in that file format the line lengths are pre-determined (e.g. all lines with a fixed length), you\'ll have to iterate line by line to count them.
回答8:
Another way.
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);
}
回答9:
If you are talking about a text file, then there is really no way to do this without reading all the lines that precede it - After all, lines are determined by the presence of a newline, so it has to be read.
Use a stream that supports readline, and just read the first X-1 lines and dump the results, then process the next one.
回答10:
In Java 8,
For small files:
String line = Files.readAllLines(Paths.get(\"file.txt\")).get(n);
For large files:
String line;
try (Stream<String> lines = Files.lines(Paths.get(\"file.txt\"))) {
line = lines.skip(n).findFirst().get();
}
In 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();
}
Source: Reading nth line from file
回答11:
It works for me: I have combined the answer of Reading a simple text file
But instead of return a String I am returning a LinkedList of Strings. Then I can select the line that I want.
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;
}
回答12:
Use this code:
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);
}
}
回答13:
You can use LineNumberReader instead of BufferedReader. Go through the api. You can find setLineNumber and getLineNumber methods.
回答14:
You can also take a look at LineNumberReader, subclass of BufferedReader. Along with the readline method, it also has setter/getter methods to access line number. Very useful to keep track of the number of lines read, while reading data from file.
回答15:
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;
}
回答16:
you can use the skip() function to skip the lines from begining.
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);
}
回答17:
They are all wrong I just wrote this in about 10 seconds. With this I managed to just call the object.getQuestion(\"linenumber\") in the main method to return whatever line I want.
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; }}