kas*_*iko 14 java java.util.scanner java-io
我对Scanner有一种奇怪的行为.它将使用我在使用Scanner(FileInputStream)
构造函数时使用的一组特定文件,但它不会与Scanner(File)
构造函数一起使用.
Scanner(File)
Scanner s = new Scanner(new File("file"));
while(s.hasNextLine()) {
System.out.println(s.nextLine());
}
Run Code Online (Sandbox Code Playgroud)
结果:没有输出
Scanner(FileInputStream)
Scanner s = new Scanner(new FileInputStream(new File("file")));
while(s.hasNextLine()) {
System.out.println(s.nextLine());
}
Run Code Online (Sandbox Code Playgroud)
结果:文件内容输出到控制台.
输入文件是包含单个类的java文件.
我以编程方式(在Java中)仔细检查:
Scanner(File)
在这种情况下通常适合我,我不知道为什么现在没有.
hasNextLine()调用findWithinHorizon(),它依次调用findPatternInBuffer(),搜索匹配的行终止符字符模式定义为.*(\r\n|[\n\r\u2028\u2029\u0085])|.+$
奇怪的是,使用两种方式构建Scanner(使用FileInputStream或通过File),如果文件包含(独立于文件大小),例如0x0A行终止符,则findPatternInBuffer返回正匹配; 但是如果文件包含ascii之外的字符(即> = 7f),则使用File返回false时,使用FileInputStream返回true.
非常简单的测试用例:
创建一个只包含char"a"的文件
# hexedit file
00000000 61 0A a.
# java Test.java
using File: true
using FileInputStream: true
Run Code Online (Sandbox Code Playgroud)
现在使用hexedit编辑文件:
# hexedit file
00000000 61 0A 80 a..
# java Test.java
using File: false
using FileInputStream: true
Run Code Online (Sandbox Code Playgroud)
在测试java代码中,除了问题中已有的内容之外别无其他:
import java.io.*;
import java.lang.*;
import java.util.*;
public class Test {
public static void main(String[] args) {
try {
File file1 = new File("file");
Scanner s1 = new Scanner(file1);
System.out.println("using File: "+s1.hasNextLine());
File file2 = new File("file");
Scanner s2 = new Scanner(new FileInputStream(file2));
System.out.println("using FileInputStream: "+s2.hasNextLine());
} catch (IOException e) {
e.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)
所以,事实证明这是一个charset问题.事实上,将测试更改为:
Scanner s1 = new Scanner(file1, "latin1");
Run Code Online (Sandbox Code Playgroud)
我们得到:
# java Test
using File: true
using FileInputStream: true
Run Code Online (Sandbox Code Playgroud)
通过查看Oracle/Sun JDK的1.6.0_23 Scanner实现,Scanner(File)
构造函数调用a FileInputStream
,用于原始二进制数据.
这指出了在调用一个或另一个构造函数时使用的缓冲和解析技术的差异,这将直接影响调用时的代码hasNextLine()
.
Scanner(InputStream)
使用一段InputStreamReader
时间Scanner(File)
使用InputStream
传递给a ByteChannel
(并且可能在一次跳转中读取整个文件,从而在你的情况下推进光标).