Scanner的nextLine()方法,仅获取部分输入

3
因此,使用类似以下内容的代码:

这样做:

for (int i = 0; i < files.length; i++) {
            if (!files[i].isDirectory() && files[i].canRead()) {
                try {
                    Scanner scan = new Scanner(files[i]);
                System.out.println("Generating Categories for " + files[i].toPath());
                while (scan.hasNextLine()) {
                    count++;
                    String line = scan.nextLine();
                    System.out.println("  ->" + line);
                    line = line.split("\t", 2)[1];
                    System.out.println("!- " + line);
                    JsonParser parser = new JsonParser();
                    JsonObject object = parser.parse(line).getAsJsonObject();
                    Set<Entry<String, JsonElement>> entrySet = object.entrySet();
                    exploreSet(entrySet);
                }
                scan.close();
                // System.out.println(keyset);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }

        }
    }

当浏览Hadoop输出文件时,中间的一个JSON对象出现了问题...因为scan.nextLine()在将其带到分割之前并没有获取整行。即,输出结果是:

  ->0   {"Flags":"0","transactions":{"totalTransactionAmount":"0","totalQuantitySold":"0"},"listingStatus":"NULL","conditionRollupId":"0","photoDisplayType":"0","title":"NULL","quantityAvailable":"0","viewItemCount":"0","visitCount":"0","itemCountryId":"0","itemAspects":{   ...  "sellerSiteId":"0","siteId":"0","pictureUrl":"http://somewhere.com/45/x/AlphaNumeric/$(KGrHqR,!rgF!6n5wJSTBQO-G4k(Ww~~
!- {"Flags":"0","transactions":{"totalTransactionAmount":"0","totalQuantitySold":"0"},"listingStatus":"NULL","conditionRollupId":"0","photoDisplayType":"0","title":"NULL","quantityAvailable":"0","viewItemCount":"0","visitCount":"0","itemCountryId":"0","itemAspects":{   ...  "sellerSiteId":"0","siteId":"0","pictureUrl":"http://somewhere.com/45/x/AlphaNumeric/$(KGrHqR,!rgF!6n5wJSTBQO-G4k(Ww~~

大部分数据已经过了清理(但 URL 大部分情况下并没有...) 而且 URL 继续如下: $(KGrHqZHJCgFBsO4dC3MBQdC2)Y4Tg~~60_1.JPG?set_id=8800005007 在文件中.... 所以有点烦人。 这也是第112个条目,我还有其他文件解析没有错误...但这个文件让我很困惑,主要是因为我不知道为什么 scan.nextLine() 不起作用... 通过调试输出,JSON 错误是由字符串没有正确拆分造成的。 还差点忘了,如果我尝试将问题行放入自己的文件中并解析,它也运行得非常好。 编辑: 如果我删除大约相同位置的有问题的行,它也会崩溃。 使用 JVM 1.6 和 1.7 尝试过。 解决方法: BufferedReader scan = new BufferedReader(new FileReader(files[i])); 而不是 scanner....

你可能正在读取一个尚未完全写入的文件吗? - clstrfsck
那么是文件中的第112行出了问题,之前的都没有问题吗? - leigero
在第111行出现了错误,并且文件已经完全写入,所以只有一行不同。 - Kurios
1个回答

2
根据您的代码,我能想到的最好解释是,根据Scanner.nextLine()使用的标准,该行确实在"~~"之后结束。
行结束的标准如下:
- 与此正则表达式匹配的内容:"\r\n | [\n\r\u2028\u2029\u0085]"或 - 输入流的结尾
您说文件在"~~"之后继续,所以让我们把EOF放在一边,看看正则表达式。它将匹配以下任何内容:
通常的行分隔符:
- <CR> - <NL> - <CR><NL> ...和Scanner还识别的三种不寻常的行分隔符。
- 0x0085是“ISO C1控制”组中的<NEL>或“下一行”控制码。 - 0x2028是Unicode的“行分隔符”字符。 - 0x2029是Unicode的“段落分隔符”字符。
我的理论是,您的输入文件中有一种“不寻常”的形式,并且这并没有显示在您用于检查文件的工具中。
我建议您使用一个可以显示文件实际字节的工具(例如Linux / Unix系统上的od实用程序)来检查输入文件。此外,请检查这是否是由于某种字符编码不匹配或尝试将二进制数据读取或写入文本引起的。
如果这些都没有帮助,那么下一步应该是使用IDE的Java调试器运行您的应用程序,并逐步执行Scanner.hasNextLine()nextLine()调用,以了解代码实际正在执行什么操作。

几乎忘记了,如果我尝试将有问题的行放在自己的文件中并解析该文件,它也可以正常工作。

那很有趣。但是,如果您用于提取行的工具与未显示(假设的)不寻常行分隔符的工具相同,则此证据不可靠。提取过程可能会更改导致问题的“内容”。

解决方法是: BufferedReader scan = new BufferedReader(new FileReader(files[i])); 因为我在输入文件的十六进制中发现了#2029。 - Kurios

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接