【问题标题】:Reading a certain line from a text file using Scanner使用扫描仪从文本文件中读取某一行
【发布时间】:2020-07-12 16:55:54
【问题描述】:

我正在一个一个地读取文本文件中的值,在 Java 中没有任何问题。该文件具有如下所示的整数值:

2 3
5 6 7 8 9
12 13 15 18 21 26 55
16 24 45 58 97

我只需要读取单行值而不是读取所有值,How to get line number using scanner 上有一个示例,但我正在寻找一个不使用 LineNumberReader 并通过循环所有行来使用计数器的解决方案。相反,最好通过我已经用来读取值的扫描仪方法获取行号。有可能吗?

这是我尝试创建的方法:

public static List<Integer> getInput(int lineIndex) throws FileNotFoundException{   
    List list = new ArrayList<Integer>();
    Scanner scan = new Scanner(new File(INPUT_FILE_NAME));
    int lineNum=0;
    //s = new Scanner(new BufferedReader(new FileReader("input.txt")));

    while(scan.hasNextLine()) {         
        if(lineNum == lineIndex) {
               list.add(scan.nextInt()); //but in this case I also loop all values in this line
        }
        lineNum++;      
    }
    scan.close();
    return list;
}

【问题讨论】:

  • 当我运行你发布的代码时,我得到一个无限循环。你呢?
  • @Abra 这是可能的,因为我为了简洁省略了一些部分。但是,如果您当然有任何想法,则不要依赖我的代码。有什么帮助吗?

标签: java file java.util.scanner java-io


【解决方案1】:

如果您有一个小文件,可以将整个内容加载到内存中:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

....

public static List<Integer> getInput(int lineIndex) {
    List<Integer> list = new ArrayList<>();
    try {
        String line = Files.readAllLines(Paths.get("path to your file")).get(lineIndex);
        list = Pattern.compile("\\s+")
                .splitAsStream(line)
                .map(Integer::parseInt)
                .collect(Collectors.toList());
    } catch (IOException ex) {
        ex.printStackTrace();
    }
    return list;
}

Files.readAllLines 方法将文件所有行的列表作为字符串返回,其中每个字符串对应一行。使用get(lineIndex),您可以返回所需的第 n 行,并且只需将字符串解析为整数。

第二种方法:

如果您有一个大文件,请使用流的惰性求值:

public static List<Integer> getInputLargeFile(int lineIndex) {
    List<Integer> list = new ArrayList<>();
    try (Stream<String> lines = Files.lines(Paths.get("path to your file"))) {
        String line = lines.skip(lineIndex).findFirst().get();
        list = Pattern.compile("\\s+")
                .splitAsStream(line)
                .map(Integer::parseInt)
                .collect(Collectors.toList());
    } catch (IOException ex) {
        ex.printStackTrace();
    }
    return list;
}

通过这种方法,您可以使用方法lines.skip 从文件开头跳转 n 行。使用findFirst().get(),您将在跳转后获得下一行。然后同上进行数字转换。

【讨论】:

  • 感谢您的回复,但我正在寻找一种通过跳过其他索引直接进入给定索引的解决方案。例如,如果我关注第 100 行,它必须跳过所有其他行。
  • @Jason 这正是我对...get(lineIndex);lines.skip(lineIndex)... 上面的两种方法所做的事情
  • 看来 OP 不理解您的解决方案。也许你应该添加更多关于你的代码是如何工作的解释?
  • @Abra 已编辑。谢谢你的建议。
  • @厄立特里亚完美!!!现在好了,非常感谢 Abra 的警告 :)
【解决方案2】:

在读取所需行中的数字时不要进行迭代,也许您可​​以使用scanner.nextLine()读取该行,然后您可以使用split("\\s")将整数的起始值放入数组中,然后您可以简单地转换并添加它们在您的列表中:

public static void main(String[] args) throws FileNotFoundException {
    Scanner scan = new Scanner(new File("input.txt"));
    List<Integer> list = new ArrayList<>();
    int lineNum = 0;
    int lineIndex = 2;

    while(scan.hasNextLine()) {
        if(lineNum == lineIndex) {
            String[] nums = scan.nextLine().split("\\s");
            for (String s : nums){
                list.add(Integer.parseInt(s));
            }
            break;
        }
        lineNum++;
        scan.nextLine();
    }

    System.out.println(list); // [12, 13, 15, 18, 21, 26, 55]
}

【讨论】:

  • 谢谢,但它给出了第一行的值而不是给定的索引。尽管如此,还是投了赞成票。
  • 是的,你是对的,因为即使我们增加了循环计数器,我们也没有将扫描仪移到下一行,所以当条件为真时它读取第一行。我们需要在迭代器之后添加scan.nextLine(),我将编辑我的答案
  • 在您上次发表评论之前我也尝试过scan.nextLine(),但它不能解决问题并导致scan.hasNextLine() 返回false。我不知道为什么,但我也认为相同的方法(跳到下一行)。
  • 奇怪,我刚刚用你的输入试了一下,我可以通过更改lineIndex 读取任何行。让我分享整个代码块,也许我错过了什么
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-04
  • 2016-03-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多