【问题标题】:File Reading in java to obtain a single line by providing line numberjava中的文件读取通过提供行号来获取单行
【发布时间】:2021-06-04 19:04:06
【问题描述】:

我有一个 java 文件阅读器方法。该文件由多行(最多 100 行)组成。我有兴趣阅读和存储第 2 行以及第 5-15 行,同时将它们存储到 arrayList 中。 遇到的问题是,我不知道如何获取特定行的内容 例如:这是文件内容。

Time after time
Heart to heart
Boys will be boys
Hand in hand
Get ready; get set; go
Hour to hour
Sorry, not sorry
Over and over
Home sweet home
Smile, smile, smile at your mind as often as possible.
Alone, alone at last
Now you see me; now you don’t
Rain, rain go away
All for one and one for all
It is what it is

正在使用的 Java API 是

 File f = new File ("t.txt");

BufferedReader br = new BufferedReader(new FileReader(f))

【问题讨论】:

  • 最简单的 方法是使用Files.readAllLines() 将整个文件作为列表读入内存。效率不是很高,但只有 100 行代码,可能不值得写任何更有效的东西。
  • 所以,这意味着我必须阅读内容两次并执行我需要采取@JonSkeet 的必要操作
  • 为什么需要阅读内容两次?你读过一次,你就有了所有行的列表。然后,您可以使用这些行做您喜欢的事情,而无需再次触摸文件。
  • 是的,我想出了一种使用 List ls = Files.readAllLines(f.toPath()) 读取它的方法。

标签: java arrays file


【解决方案1】:

使用 lambda 通过各自的行号获取行

Set<Integer> linesToGet = Set.of(2, 5, 15);
try(Stream<String> stream = Files.lines(Paths.get("test.txt"))) {
  int[] line = {1};
  List<String> list = stream.filter(s -> linesToGet.contains(line[0]++))
      .collect(toList());
}
catch (IOException ex) {…}

获取:[Heart to heart, Get ready; get set; go, It is what it is]

【讨论】:

    【解决方案2】:

    Java 7 引入了 NIO.21,其中包含声明方法 readAllLines2 的类 java.nio.Files。由于您声明您的文件最多可以包含 100 行,因此方法 readAllLines 似乎是合适的。然后你需要做的就是指出你想要的行[s]的索引[es]。下面的代码演示。

    import java.io.IOException;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.util.List;
    
    public class FileLine {
        public static void showLines(List<String> lines, int first, int last) {
            if (lines != null  &&  first >= 0  &&  last < lines.size()  &&  first <= last) {
                for (int i = first; i <= last; i++) {
                    System.out.println(lines.get(i));
                }
            }
        }
    
        public static void main(String[] args) {
            Path path = Paths.get("t.txt");
            try {
                List<String> lines = Files.readAllLines(path); // throws java.io.IOException
                showLines(lines, 2, 2);
                System.out.println("================================================================");
                showLines(lines, 5, 14);
            }
            catch (IOException xIo) {
                xIo.printStackTrace();
            }
        }
    }
    

    请注意,List 中第一行的索引为 0(零)。

    我运行上述代码时的输出是:

    Boys will be boys
    ================================================================
    Hour to hour
    Sorry, not sorry
    Over and over
    Home sweet home
    Smile, smile, smile at your mind as often as possible.
    Alone, alone at last
    Now you see me; now you don’t
    Rain, rain go away
    All for one and one for all
    It is what it is
    

    或者,如果您想将某些文件行收集到一个单独的列表中,请考虑以下代码(与上述代码略有不同)。

    public class FileLine {
    
        public static List<String> getLines(List<String> lines, int first, int last) {
            List<String> list = new ArrayList<>();
            if (lines != null  &&  first >= 0  &&  last < lines.size()  &&  first <= last) {
                for (int i = first; i <= last; i++) {
                    list.add(lines.get(i));
                }
            }
            return list;
        }
    
        public static void main(String[] args) {
            Path path = Paths.get("t.txt");
            try {
                List<String> lines = Files.readAllLines(path);
                List<String> selectedLines = getLines(lines, 2, 2);
                selectedLines.addAll(getLines(lines, 5, 14));
                System.out.println(selectedLines);
            }
            catch (IOException xIo) {
                xIo.printStackTrace();
            }
        }
    }
    

    运行替代代码会给出以下输出:

    [Boys will be boys, Hour to hour, Sorry, not sorry, Over and over, Home sweet home, Smile, smile, smile at your mind as often as possible., Alone, alone at last, Now you see me; now you don’t, Rain, rain go away, All for one and one for all, It is what it is]
    

    1 NIO 是在 Java 1.4 中引入的
    2 确切地说,该方法是在 Java 8 中添加的。在 Java 7 中,您还必须指出
    2 em>charset 文件。

    【讨论】:

      【解决方案3】:

      将您需要的逻辑提取到一个查看一般情况的方法中。

      给定一个文件f,只读取行的子集。查看此问题的一种方法是使用类似

      的方法
      List<String> readLines(File f, Function<Integer, Boolean> check);
      

      你可以这样定义这样的方法:

      List<String> readLines(File f, Function<Integer, Boolean> check) throws IOException {
          List<String> list = new ArrayList<>();
          int count = 0;
          String line;
          try (BufferedReader br = new BufferedReader(new FileReader(f))) {
              while((line = br.readLine()) != null) {
                  count++;
                  if (check.apply(count)) {
                      list.add(line);
                  }
              }
          }
          return list;
      }
      

      根据需要定义检查函数,给定一个整数,如果要添加该行,它将返回真/假,您可以针对不同的用例进行概括。

      例如(在您的情况下),检查功能将是

      Function<Integer, Boolean> check = lineNumber -> lineNumber == 2 || (lineNumber >= 5 && lineNumber <= 15);
      

      【讨论】:

        【解决方案4】:

        文件是通过streams读取的,每一行都是按顺序访问的,而不是随机访问的。处理此问题的一种方法是在循环内设置一个计数器,例如:

        int count = 1;     // line counter
        String line;       // current line being read
        
        while((line = br.readLine()) != null) {
            if(count == 2 ||
              (count >= 5 && count <= 15))
              arrayList.add(line);
            count++;
        }
        

        【讨论】:

        • 有一个柜台是我的想法,但我正在寻找是否有其他选择。谢谢@david mordigal
        猜你喜欢
        • 2016-01-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-15
        • 1970-01-01
        • 1970-01-01
        • 2020-08-10
        • 1970-01-01
        相关资源
        最近更新 更多