java 无法从文件中读取一行
java can not read a line from file
我正在读取包含以下代码的文件:
Scanner in = new Scanner(new File(fileName));
while (in.hasNextLine()) {
String[] line = in.nextLine().trim().split("[ \t]");
.
.
.
}
当我用 vim 打开文件时,有些行以以下特殊字符开头:
但是 java 代码无法读取这些行。当它到达这些行时,它认为它是文件的末尾并且 hasNextLine() 函数 returns false!!
编辑:这是上述(有问题的)行的十六进制转储:
0000000: e280 9c20 302e 3230 3133 3220 302e 3231 ... 0.20132 0.21
0000010: 3431 392d 302e 3034 0a 419-0.04.
@VGR 做对了。
tl;dr:使用 Scanner in = new Scanner(new File(fileName), "ISO-8859-1");
似乎正在发生的事情是:
- 由于那个单独的 0x9C 字符,您的文件不是有效的 UTF-8。
- 扫描程序正在以 UTF-8 格式读取文件,因为这是系统默认设置
- 底层库抛出
MalformedInputException
- 扫描仪捕获并隐藏它(一个善意但错误的设计决定)
- 它开始报告它没有更多行
- 除非您实际询问扫描仪,否则您不会知道出现了什么问题
这是一个 MCVE:
import java.io.*;
import java.util.*;
class Test {
public static void main(String[] args) throws Exception {
Scanner in = new Scanner(new File(args[0]), args[1]);
while (in.hasNextLine()) {
String line = in.nextLine();
System.out.println("Line: " + line);
}
System.out.println("Exception if any: " + in.ioException());
}
}
这是一个正常调用的例子:
$ printf 'Hello\nWorld\n' > myfile && java Test myfile UTF-8
Line: Hello
Line: World
Exception if any: null
这就是您所看到的(只是您没有检索和显示隐藏的异常)。特别注意没有显示任何行:
$ printf 'Hello\nWorld 4\n' > myfile && java Test myfile UTF-8
Exception if any: java.nio.charset.MalformedInputException: Input length = 1
这里是解码为 ISO-8859-1 时,所有字节序列都有效的解码(即使 0x9C 没有分配的字符,因此不会出现在终端中):
$ printf 'Hello\nWorld 4\n' > myfile && java Test myfile ISO-8859-1
Line: Hello
Line: World
Exception if any: null
如果您只对 ASCII 数据感兴趣并且没有任何 UTF-8 字符串,您可以简单地要求扫描器使用 ISO-8859-1
,方法是将它作为第二个参数传递给 [=18] =]构造函数:
Scanner in = new Scanner(new File(fileName), "ISO-8859-1");
我正在读取包含以下代码的文件:
Scanner in = new Scanner(new File(fileName));
while (in.hasNextLine()) {
String[] line = in.nextLine().trim().split("[ \t]");
.
.
.
}
当我用 vim 打开文件时,有些行以以下特殊字符开头:
但是 java 代码无法读取这些行。当它到达这些行时,它认为它是文件的末尾并且 hasNextLine() 函数 returns false!!
编辑:这是上述(有问题的)行的十六进制转储:
0000000: e280 9c20 302e 3230 3133 3220 302e 3231 ... 0.20132 0.21 0000010: 3431 392d 302e 3034 0a 419-0.04.
@VGR 做对了。
tl;dr:使用 Scanner in = new Scanner(new File(fileName), "ISO-8859-1");
似乎正在发生的事情是:
- 由于那个单独的 0x9C 字符,您的文件不是有效的 UTF-8。
- 扫描程序正在以 UTF-8 格式读取文件,因为这是系统默认设置
- 底层库抛出
MalformedInputException
- 扫描仪捕获并隐藏它(一个善意但错误的设计决定)
- 它开始报告它没有更多行
- 除非您实际询问扫描仪,否则您不会知道出现了什么问题
这是一个 MCVE:
import java.io.*;
import java.util.*;
class Test {
public static void main(String[] args) throws Exception {
Scanner in = new Scanner(new File(args[0]), args[1]);
while (in.hasNextLine()) {
String line = in.nextLine();
System.out.println("Line: " + line);
}
System.out.println("Exception if any: " + in.ioException());
}
}
这是一个正常调用的例子:
$ printf 'Hello\nWorld\n' > myfile && java Test myfile UTF-8
Line: Hello
Line: World
Exception if any: null
这就是您所看到的(只是您没有检索和显示隐藏的异常)。特别注意没有显示任何行:
$ printf 'Hello\nWorld 4\n' > myfile && java Test myfile UTF-8
Exception if any: java.nio.charset.MalformedInputException: Input length = 1
这里是解码为 ISO-8859-1 时,所有字节序列都有效的解码(即使 0x9C 没有分配的字符,因此不会出现在终端中):
$ printf 'Hello\nWorld 4\n' > myfile && java Test myfile ISO-8859-1
Line: Hello
Line: World
Exception if any: null
如果您只对 ASCII 数据感兴趣并且没有任何 UTF-8 字符串,您可以简单地要求扫描器使用 ISO-8859-1
,方法是将它作为第二个参数传递给 [=18] =]构造函数:
Scanner in = new Scanner(new File(fileName), "ISO-8859-1");