【问题标题】:How to read a specific line using the specific line number from a file in Java?java - 如何使用Java文件中的特定行号读取特定行?
【发布时间】:2010-02-22 17:30:44
【问题描述】:

在 Java 中,是否有任何方法可以从文件中读取特定行?例如,读取第 32 行或任何其他行号。

【问题讨论】:

  • 我知道我很晚了,但万一有人发现了这个问题:请注意,文件只是一个字节序列。换行符只是一个字符(在 Windows 上是两个),一个字符只是一个(或更多,取决于编码)字节。而且,如果没有文件中字节位置的索引,知道这些字节在哪里的唯一方法是读取并查找它。 (但这并不意味着您必须将整个文件加载到内存中)。

标签: java file-io


【解决方案1】:

对于小文件:

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

【讨论】:

  • 这会返回 java.nio.charset.MalformedInputException: Input length = 1 when using skip value is 1
  • 这不是我发布的代码的问题,而是文件编码的问题。见this post
  • "请注意,此方法适用于在单个操作中方便读取所有行的简单情况。它不适用于读取大文件。" - Files.readAllLines()的Javadoc
  • 以下代码在android中需要API级别26。如果我们的最小值小于这个级别,那么它就不起作用
【解决方案2】:

除非您对文件中的行有先前的了解,否则没有办法直接访问第 32 行而不读取前 31 行。

对于所有语言和所有现代文件系统都是如此。

因此,您只需阅读行,直到找到第 32 行。

【讨论】:

  • “以前的知识”可以简单到文件中精确的行大小模式,这样你就可以寻找到某个位置。
  • @Murali:当然。它也可以是行号到字节偏移或其任意组合的索引。
【解决方案3】:

据我所知,你可以做的是使用 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();

【讨论】:

  • 请注意,这里你读的是第 30 行,这是第 31 行,因为我们从 0 开始行号。所以我建议更改它以精确匹配问题。
【解决方案4】:

当然,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)

【讨论】:

  • 虽然这会在转到第 32 行之前将整个文件加载到内存中,但这对于大文件可能不实用,并且比读取 util 查找第 32 行要慢...
  • 公平点,是的。我在测试文件很小的测试用例中使用了它,但在大文件上,我同意,这不是一个好方法。
  • 更新了回答帖子,以反映如果您有一个大文件并且不需要超出 X 行的任何内容,则 FileUtils 在此用例中是一个坏主意。
【解决方案5】:

您可以尝试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]"));      

上面的例子读取了一个由50行组成的文本文件,格式如下:

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

声明:我写了这个库

【讨论】:

    【解决方案6】:

    尽管正如其他答案中所说,如果不知道之前的偏移量(指针),就不可能到达确切的行。因此,我通过创建一个临时索引文件来实现这一点,该文件将存储每一行​​的偏移值。如果文件足够小,您可以将索引(偏移量)存储在内存中,而不需要单独的文件。

    可以使用 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();
    

    另请访问RandomAccessFile 上的 Java 文档了解更多信息:

    复杂性:这是 O(n),因为它读取整个文件一次。请注意内存要求。如果它太大而无法在内存中,则创建一个存储偏移量的临时文件,而不是如上所示的 ArrayList。

    注意:如果您想要在“32”行中的所有内容,您只需拨打readLine() 也可以通过其他课程“32”次。如果您想多次获取特定行(当然基于行号),上述方法很有用。

    【讨论】:

    【解决方案7】:

    另一种方式。

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

    【讨论】:

    • 优雅,我喜欢。
    【解决方案8】:

    不,除非在该文件格式中行长是预先确定的(例如所有具有固定长度的行),否则您必须逐行迭代以计算它们。

    【讨论】:

      【解决方案9】:

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

      来源:Reading nth line from file

      【讨论】:

        【解决方案10】:

        如果您正在谈论一个文本文件,那么如果不读取它之前的所有行,就真的没有办法做到这一点 - 毕竟,行是由换行符的存在决定的,所以必须读取它。

        使用支持 readline 的流,只读取前 X-1 行并转储结果,然后处理下一行。

        【讨论】:

          【解决方案11】:
          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;
              }
          

          【讨论】:

            【解决方案12】:

            它对我有用: 我结合了答案 Reading a simple text file

            但我不是返回一个字符串,而是返回一个字符串的 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;
            }
            

            【讨论】:

            • 你可以这样做:linkedlist.get(31)
            【解决方案13】:

            使用此代码:

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

            【讨论】:

              【解决方案14】:

              您可以使用 LineNumberReader 代替 BufferedReader。通过api。您可以找到 setLineNumber 和 getLineNumber 方法。

              【讨论】:

              • 没有帮助 - 你仍然必须阅读之前的所有行......除了你作弊并将第一行设置为 32
              【解决方案15】:

              您还可以查看 LineNumberReader,它是 BufferedReader 的子类。除了 readline 方法,它还具有访问行号的 setter/getter 方法。在从文件读取数据时跟踪读取的行数非常有用。

              【讨论】:

                【解决方案16】:

                您可以使用 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);
                
                }
                

                【讨论】:

                  【解决方案17】:

                  EASY WAY - 使用行号读取一行。 假设行号从 1 到 null 。

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

                  【讨论】:

                    【解决方案18】:

                    他们都错了我只是在大约 10 秒内写了这个。 有了这个,我设法在 main 方法中调用 object.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; }}
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2012-12-22
                      • 2014-06-03
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2014-10-13
                      相关资源
                      最近更新 更多