在Java中从文本文件中读取特定行

21

是否有一种方法可以从文本文件中读取特定行?在API或Apache Commons中有类似以下的功能:

String readLine(File file, int lineNumber)

我同意它很容易实现,但是如果文件很大,它就不太有效率。

9个回答

17
String line = FileUtils.readLines(file).get(lineNumber);

虽然这样做可以,但它仍然存在效率问题。

或者,您可以使用:

 LineIterator it = IOUtils.lineIterator(
       new BufferedReader(new FileReader("file.txt")));
 for (int lineNumber = 0; it.hasNext(); lineNumber++) {
    String line = (String) it.next();
    if (lineNumber == expectedLineNumber) {
        return line;
    }
 }

由于缓冲区的存在,这将会稍微更加有效率。

查看Scanner.skip(..)并尝试使用正则表达式跳过整行。我无法确定它是否更加有效率 - 进行基准测试。

P.S. 在此,效率指的是内存效率


FileUtils是什么?它来自Java 7吗? - finnw
1
效率?我认为真正的问题是第一个解决方案将整个文件读入内存... - abyx
1
是的,这就是为什么它有一个“效率问题”,特别是内存效率问题。 - Bozho
输入文件可能有数千行(要加载到数据库中的文档),因此将整个文件读入内存被丢弃。 - Lluis Martinez
应该是 new FileReader(..),提醒一下。 - Tito

5

我不知道。

请注意,文件中没有特定的索引来确定每行的起始位置,因此任何实用方法都与以下方法一样有效:

BufferedReader r = new BufferedReader(new FileReader(file));
for (int i = 0; i < lineNumber - 1; i++)
{
   r.readLine();
}
return r.readLine();

(当然,需要适当的错误处理和资源关闭逻辑。)

1

guava有类似的东西:

List<String> Files.readLines(File file, Charset charset);

这样你就可以做到:

String line = Files.readLines(file, Charsets.UTF_8).get(lineNumber);

1
如果你读取的行都是相同长度,那么进行计算可能会有用。但在行长不同的情况下,我认为没有别的办法,只能逐行读取直到行数正确为止。

“Same length” 意味着字节长度相同,而不是字符长度(考虑到可变长度字符编码)。 - MBO
实际上,输入文件是固定长度和ANSI编码的,我在问题中忘记指定了这一点。问题可能出在行分隔符上,应用程序必须在Windows和Unix上都能运行。 - Lluis Martinez

1

很遗憾,除非您能保证文件中的每一行都是完全相同的长度,否则您将不得不阅读整个文件,或者至少阅读到您需要的那一行。

您唯一能够计算行数的方法是在文件中查找换行符,这意味着您必须逐字节读取。

优化代码以使其整洁易读是可能的,但在底层,您始终会读取整个文件。

如果您要反复读取同一个文件,可以解析该文件并创建索引来存储某些行号的偏移量,例如第100行、第200行等的字节计数。


1

由于文件是按字节而不是按行定位的,因此任何通用解决方案的复杂度最多为O(n),其中n是文件大小(以字节为单位)。您必须扫描整个文件并计算行分隔符的数量,直到您知道要读取文件的哪个部分。


1
使用文件工具:
File fileFeatures = new File(
                "Homework1AdditionalFiles/jEdit4.3/jEdit4.3ListOfFeatureIDs.txt");
String line = (String) FileUtils.readLines(fileFeatures).get(lineNumber);

0
如果您要以相同的方式(寻找特定行的文本)处理相同的文件,则可以对文件进行索引。行号 -> 偏移量。

0
根据这个答案,Java 8使我们能够从文件中提取特定的行。该答案中提供了示例。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接