首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在以特殊字符串结尾的while循环中读取文件?

如何在以特殊字符串结尾的while循环中读取文件?
EN

Stack Overflow用户
提问于 2017-08-04 12:49:26
回答 3查看 251关注 0票数 0

这里的代码示例是用Java编写的,但是我在C++中遇到了这个问题,基本上在任何需要解析这样一个文件的地方都遇到了这个问题。我正在分析来自电子设计自动化软件套件的文件中的字符串。该文件被称为"netlist",它包含有关电子设备以及特殊字符串的信息。以下是一个示例:

代码语言:javascript
复制
R3 1 4 137 425 1
R4 1 2 60 479 0
R5 2 3 55 596 0
V2 3 4 171 680 1
.end

我有一个名为Device的Java类,它接收文件的一行并将数据输入到每个设备的成员变量中(例如,顶层是一个名为R3的电阻,连接到节点1和4等)。当我进入来自EDA软件的.end字符串时,显然无法将它解析为设备。

我觉得我一遍又一遍地重写相同的代码,这对我来说就像是一种严重的反模式。我使用一个while循环来读取每一行,检查它是否不是".end“字符串,然后再次检查它作为离开循环的条件:

代码语言:javascript
复制
String line = "";
         BufferedReader in;

         in = new BufferedReader(new FileReader(fileName));
         while(line != null && !line.startsWith(".end"))
         {
                line = in.readLine();
                //this feels like an anti-pattern...
                if(!line.startsWith("end"))
                {
                    Device d = new Device();
                    d.parseDeviceData(line);
                    devices.add(d); //devices  is an ArrayList
                }
         }

是那张双重支票让我心烦。我能想到的唯一方法就是在while循环之外读取第一行,然后在循环结束时读取每一行,但这并不能真正解决我的问题。为什么我应该有两个readLine语句?

所以,我认为这是反模式是对的吗?如果是的话,我该如何避免呢?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-08-04 13:34:42

基本上,您希望按行读取文件,如果到达末尾或出现以.end开头的行,则停止。您的当前方法确实可以简化,因为第二次检查的结果已经知道。

我会这样做:

代码语言:javascript
复制
BufferedReader in;
in = new BufferedReader(new FileReader(fileName));

while (true) {
    String line = in.readLine();
    if (line == null || line.startsWith(".end")) {
        // Abort parsing the file
        break;
    }

    // Valid line, parse it
    Device d = new Device();
    d.parseDeviceData(line);
    devices.add(d);
}

如果您不喜欢while (true),那么还可以在变量中保存比较结果。

请注意,我们现在应该使用名为NIO的Javas新I/O库。它更健壮,更容易使用,而且提供更多。它的主要类是FilesPaths。特别令人感兴趣的是Files#readAllLinesFiles#lines,第一个返回一个保存文件完整内容的List<String>,第二个返回一个Stream<String>,在那里您可以展示Lambda表达式的全部功能。

注意,目前,这两种方法都不是实现“读到”的最佳选项,因为第一种方法将读取整个内容,Stream的操作也不容易中止。因此,Java 9将引入方法Stream#takeWhileStream#dropWhile

但是,可以很容易地将Stream转换为Iterator,并且可以再次使用常规逻辑,因此我们可以使用以下代码:

代码语言:javascript
复制
Iterator<String> lineIterator = Files.lines(Paths.get(fileName)).iterator();

while (lineIterator.hasNext()) {
    String line = lineIterator.next();
    if (line.startsWith(".end")) {
        // Abort parsing the file
        break;
    }

    // Valid line, parse it
    Device d = new Device();
    d.parseDeviceData(line);
    devices.add(d);
}
票数 3
EN

Stack Overflow用户

发布于 2017-08-04 13:08:02

您可以将行扫描位放入while条件:

代码语言:javascript
复制
while(!(line = in.readLine()).startsWith(".end"))
{
    System.out.println(line);
}

它不好看,但它将防止你不得不测试你的情况两次。它会变得更脏(真的很脏!)如果你有很多条件要检查的话。

票数 1
EN

Stack Overflow用户

发布于 2017-08-04 13:37:47

也许我错了,但答案似乎非常简单

代码语言:javascript
复制
     String line = null;
     BufferedReader in;

     in = new BufferedReader(new FileReader(fileName));
     for(;;)
     // instead use while(true) on personal taste / teacher / tradition / :)
     {
            line = in.readLine();
            if(line == null)
            {
                 // break because of eof, wrong end, do something !!!!
                 // throw new XxxxxxxxException("bad end of file")  
                 break;

            }  
            if( line.startsWith(".end") )
            {  
               // correnct end
                break;
            }
            Device d = new Device();
            d.parseDeviceData(line);
            devices.add(d); //devices  is an ArrayList

     }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45507297

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档