对于我的数据结构项目,目标是读取一个包含超过10000首歌曲的提供文件,其中清晰标记了艺术家,标题和歌词,每首歌曲用一条双引号分隔。我已经编写了这段代码来解析文本文件,它运行起来,运行时间不到3秒
阅读422K行文字
创建一个Song对象
将所述歌曲添加到ArrayList中
我写的解析代码是:
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
我正在与我的Intro to Algorithms教授谈论这个项目的代码,他说我应该在我的代码中试图更加防御,以避免其他人提供的数据不一致。最初我在Artist,Title和Lyrics字段之间使用if / else块,并且根据他的建议我改为顺序if语句。虽然我可以看到他的观点,但是使用这个代码示例,我怎样才能更加谨慎地避免输入不一致?
答案 0 :(得分:4)
我会替换例如:
artist= readToken.split("\"")[1];
与
String[] parts = readToken.split("\"");
if(parts.length >= 2) artist = parts[1];
else continue;
其他修改包括:
答案 1 :(得分:2)
在现实世界中,对数据完整性有一些保证。在处理用户输入(无论是来自stdin还是文件)的情况下,有一些项目定义的范例用于通知用户需要注意的问题。
例如,当编译器编译代码或执行脚本的shell遇到不一致时,它可能会暂停并打印包含不一致的行,而下面的第二行使用“^”符号来指示问题的位置
所以这里有一些基本问题要问自己:
1.每条线路都保证包含每个区域吗?
2.字段的排序是否有保证?
如果这些是输入合同的条件并且被违反,您应该忽略/报告该行。如果它们不是输入的条件,那么你需要处理它......你目前没有。
答案 2 :(得分:2)
您假设输入是完美的。如果您查看当前设置应用程序的方式,基于对算法的快速读取,数据将如下所示
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,并且该文件未以“。”结束,那将会有一个例外。在你的do / while中添加另一个检查hasNextLine()
答案 3 :(得分:1)
我看到Jason缺少一些东西。
我认为if / else很好,它不会改变逻辑。但是,您应该尽可能地限制变量的范围。通过在while循环中声明艺术家,标题等,它们将被初始化为null(或其他),因此如果一个条目缺少艺术家,那么它将不会获得最后一个条目的值。
此外,如果标题,艺术家等有引号会怎样?怎么处理?看起来多行的歌词怎么样?
如果存在未知字段会发生什么 - 可能是拼写错误?它将被添加到歌词的末尾,这似乎不对。只有在找到LYRICS字段后才能附加它。如果歌词为null,则它将以“null”开头。
答案 4 :(得分:0)
以下是一些可以解决的问题:
您的代码假定之前没有空格(例如)“ARTIST”,“=”符号周围没有空格,依此类推。
您的代码假设关键字为全部大写字母。有人可以使用小写或混合大小写。
您的代码假定不以keyword=\"
开头的行是歌曲歌词的延续。但是如果用户输入ARTOST="Sting"
怎么办?或者,如果用户尝试使用两行作为艺术家姓名,该怎么办?
最后,我不相信在这种情况下用“if”替换“else if” 会对代码的健壮性产生任何影响。
答案 5 :(得分:0)
处理异常(我猜Scanner可能会因无效字符而抛出InputMismatchException。)
如果文件格式错误,并且文件末尾已到达,do { } while (...)
似乎可以无休止地循环。
无法阻止artist
或title
为空。