对于我的数据结构项目,目标是在提供的文件中阅读包含10000多首带有艺术家,标题和歌词的歌词的文件,每首歌曲都被带有单个双引号的行分开。我已经编写了此代码来解析文本文件,并且运行时间不到3秒
阅读422k文字行
创建歌曲对象
将歌曲添加到阵列列表中

我写的解析代码是:

if (songSource.canRead()) {  //checks to see if file is valid to read
    readIn= new Scanner(songSource);
    while (readIn.hasNextLine()) {
 do {
     readToken= readIn.nextLine();

             if (readToken.startsWith("ARTIST=\"")) {
  artist= readToken.split("\"")[1];
      } 
      if (readToken.startsWith("TITLE=\"")) {
  title= readToken.split("\"")[1];
      } 
      if (readToken.startsWith("LYRICS=\"")) {
  lyrics= readToken.split("\"")[1];
      } else {
  lyrics+= "\n"+readToken;
      }//end individual song if block
 } while (!readToken.startsWith("\"")); //end inner while loop

    songList.add(new Song(artist, title, lyrics));

    }//end while not EOF 
} //end if file can be read 

我正在与算法教授介绍有关该项目的代码的介绍,他说我应该尝试在代码中更具防御性,以使其他人提供的数据不一致。最初,我在艺术家,标题和歌词字段之间使用if/其他障碍,在他的建议下,我更改为顺序if语句。虽然我可以看到他的观点,但使用此代码示例,我如何才能防御输入不一致?

有帮助吗?

解决方案

您假设输入是完美的。如果您查看应用程序当前设置的方式,请根据您的算法的快速阅读,数据将看起来像这样

ARTIST="John"
TITLE="HELLO WORLD"
LYRICS="Sing Song All night long"
"

但请考虑案件

ARTIST="John"
TITLE="HELLO WORLD"
LYRICS="Sing Song All night long"
"
ARTIST="Peter"
LYRICS="Sing Song All night long"
"

根据您的算法,您现在有2首歌被描述为

songList = { Song("JOHN", "HELLO WORLD", "Sing Song All night long"),
             Song("Peter", "HELLO WORLD", "Sing Song All night long") }

有了当前的算法,艺术家和标题即使没有定义,也将出现在第二首歌中。您需要重置三个变量。

在您的其他方面,您只是将完整的线倾倒到歌词中。如果您已经拔出歌词,那么您现在正在覆盖它。测试用例

 ARTIST="John"
 LYRICS="Sing Song All night long"
 TILET="HELLO WORLD"
 "

考虑将此记录发送到错误状态。因此,当批处理读取完成后,可以生成和修复错误报告。

另外,您仅在阅读艺术家后才考虑EOF。如果在艺术家阅读过程中出现EOF,并且文件不会结束。 ()

其他提示

我会取代例如:

artist= readToken.split("\"")[1];

String[] parts = readToken.split("\"");
if(parts.length >= 2) artist = parts[1];
else continue;

其他修改将包括:

  1. 重置本地变量(因此,如果在第一首歌曲之后没有为某些歌曲提供歌曲,您就不会意外地获得错误的歌曲。
  2. 决定如果缺少某些数据该怎么办 - 您是否仍然想将歌曲添加到歌曲列表中?

在现实世界中,关于数据完整性有一些保证。在处理用户输入(无论是从stdin还是文件)处理的情况下,有一些项目定义的范例,可以将需要注意的问题通知用户。

例如,当编译器编译代码或执行脚本的外壳会遇到不一致时,它可能会停止并打印包含在其下方的第二行不一致的行,该行使用使用“^”符号来指示问题的位置。

因此,这里有一些基本问题要问自己:
1.是否保证每行都包含每个字段?
2.是否保证了字段的顺序?

如果这些是输入合同的条件并受到违反,则应忽略/报告该行。如果它们不是输入的条件,那么您需要处理。

我看到这里缺少的几件事。

我认为如果/其他很好,它不会改变逻辑。但是,您应该尽可能限制变量的范围。通过宣布艺术家,标题等。在当时循环的内部,它们将被初始化为null(或其他),因此,如果输入缺少艺术家,则不会获得最后一个条目的价值。

另外,如果标题,艺术家等有报价,会发生什么?如何处理?歌词似乎是多行正确的呢?

如果有一个未知的领域,会发生什么 - 也许是拼写错误?它将被添加到歌词的结尾,这似乎是不正确的。只有找到歌词字段,您就可以添加它。如果歌词为null,则它将以“ null”开头。

这是一些可以解决的问题:

  • 您的代码假定之前没有空格(例如)“艺术家”,没有“ =”标志等。

  • 您的代码假设关键字在全范围内。有人可以使用小写或混合箱。

  • 您的代码假设一条线不开头 keyword=\" 是歌曲歌词的延续。但是如果用户输入该怎么办 ARTOST="Sting"?或者如果用户尝试使用两行作为艺术家名称怎么办?

最后,在这种情况下,我不相信将“ else if”代替“ if” 拥有 对代码的鲁棒性有任何影响。

处理异常(我猜扫描仪可能会为无效的字符投掷InputMismatchException)。

看起来像 do { } while (...) 如果文件不正确,可以无休止地循环,并达到文件的末尾。

没有任何阻止 artist 或者 title 从空的

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top