【问题标题】:java Scanner reads only first 2048 bytesjava Scanner 只读取前 2048 个字节
【发布时间】:2013-06-23 03:34:39
【问题描述】:

我正在使用 java.util.Scanner 通过以下代码从类路径中读取文件内容:

String path1 = getClass().getResource("/myfile.html").getFile();

System.out.println(new File(path1).length()); // 22244 (correct)

String file1 = new Scanner(new File(path1)).useDelimiter("\\Z").next();
System.out.println(file1.length()); // 2048 (first 2k only)

代码从idea用命令运行(maven测试)

/Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Home/bin/java -Dmaven.home=/usr/share/java/maven-3.0.4 -Dclassworlds.conf=/usr/share/java/maven-3.0.4/bin/m2.conf -Didea.launcher.port=7533 "-Didea.launcher.bin.path=/Applications/IntelliJ IDEA 12 CE.app/bin" -Dfile.encoding=UTF-8 -classpath "/usr/share/java/maven-3.0.4/boot/plexus-classworlds-2.4.jar:/Applications/IntelliJ IDEA 12 CE.app/lib/idea_rt.jar" com.intellij.rt.execution.application.AppMain org.codehaus.classworlds.Launcher --fail-fast --strict-checksums test

它在我的 win7 机器上完美运行。但是在我搬到 mac 之后,同样的测试失败了。 我试图谷歌但没有找到太多=(

为什么带分隔符 \Z 的扫描仪在 win7 上将我的整个文件读入字符串,但在 mac 上却不行? 我知道有更多的方法可以读取文件,但我喜欢这种单线并想了解它为什么不起作用。 谢谢。

【问题讨论】:

  • 除此之外,您不会在测试中比较 like 和 like - File.length() 给出了 bytes 的长度,而 String.length() 给出了 的长度i>字符。它没有解释这里的区别,但它仍然是一个奇怪的比较。文件里有什么?
  • mac 不区分大小写吗?您是否尝试使用小写 \\z
  • @fmodos 有趣的 \\z 给出前 1024 个字节,其中 \\Z 2048
  • @fmodos:这些在正则表达式中意味着不同的东西。这不是文件名 - 除了文件名之外,我不知道您在谈论 Mac 和 Windows 之间的区分大小写差异。
  • @JonSkeet 它是 HTML 文件,22244 是它的正确大小(以字节为单位)

标签: java windows macos java.util.scanner


【解决方案1】:

这里有一些来自java的信息

http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html

\Z 输入的结尾,但对于最后的终止符,如果有的话

\z 输入结束

Line terminators

行终止符是一个或两个字符的序列,用于标记 输入字符序列的行尾。以下是 识别为行终止符:

换行符('\n'),回车符 紧跟一个换行符(“\r\n”),一个独立的 回车符 ('\r'), 下一行字符 ('\u0085'), A 行分隔符 ('\u2028'),或段落分隔符 字符('\u2029)。

所以使用\z 而不是\Z

【讨论】:

    【解决方案2】:

    有一篇很好的文章介绍了这种用Scanner完全读取文件的方法:

    http://closingbraces.net/2011/12/17/scanner-with-z-regex/

    简而言之:

    因为使用“/z”作为分隔符的单次读取应该读取 直到“输入结束”之前的所有内容,很容易只做一个 阅读并保留它,就像上面列出的示例一样。

    在大多数情况下没关系,但我发现至少有一种情况 读取到“输入结束”不会读取整个输入 - 当 input 是一个 SequenceInputStream,每个组成 InputStreams 似乎给出了一个单独的“输入结束”。结果,如果 您使用“/z”分隔符进行单次读取,它会返回内容 SequenceInputStream 的第一个组成流,但是 不会读入其余的组成流。

    小心使用它。最好逐行阅读,或者使用hasNext()检查直到它是真实的false

    UPD:换句话说,试试这个代码:

    StringBuilder file1 = new StringBuilder();
    Scanner scanner = new Scanner(new File(path1)).useDelimiter("\\Z");
    
    while (scanner.hasNext()) {
       file1.append(scanner.next());
    }
    

    【讨论】:

    • 感谢您的帮助,但这不是我的情况。在我做 Scanner scanner = new Scanner(new File(path1)).useDelimiter("\\Z");扫描仪.next(); scanner.hasNext() 返回 false,但文件尚未完全读取
    【解决方案3】:

    我在 Mac 上使用 nextLine() 时也遇到了这个问题,Java 7 update 45。更糟糕的是,在超过 2048 字节的行之后,文件的其余部分被忽略,扫描器认为它已经结束了文件。

    我将其更改为明确告诉 Scanner 使用更大的缓冲区,并且它可以工作。

    Scanner sc = new Scanner(new BufferedInputStream(new FileInputStream(nf), 20*1024*1024), "utf-8");
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-19
      • 1970-01-01
      • 2011-06-24
      • 2010-11-30
      • 2021-08-02
      相关资源
      最近更新 更多