0

我仍然是 Java 的业余爱好者,边走边学,所以请温柔一点!

论坛说我应该使用 FileInputStream 从文件中读取二进制数据。但是,我的后续解析器无法正确验证数据,因此我从外部程序生成了一个包含连续字符 0 到 255 的测试文件,并使用十六进制读取器验证了这些值......所以我确定它包含我想要的是。我让我的 Java 程序使用 FileInputStream 将文件读入字节数组,然后使用 println 一次打印一个值。某些值 - 特别是 -127、-115、-113、-112 和 -99 - 会转换为 63(相当于问号)。尽我所能尝试我无法获得我期望的值。为什么会发生这种情况,我该如何解决?我正在处理的文件通常是几十兆字节,所以我需要一次性读取文件——逐字节的方法太慢了。TIA。

我的代码:

private static String readFileInputStream(String filename) {
  String sContent = null;
  File file = new File(filename);
  byte[] fileData = new byte[(int)file.length()];

  try {
    DataInputStream dis = new DataInputStream(new FileInputStream(file));      
    dis.readFully(fileData);
    dis.close(); sContent = new String(fileData);
  } catch(IOException e) { }

  return sContent;
}
4

2 回答 2

0

啊,你终于发布了你的代码。您正在正确读取字节,然后将它们放入字符串中。您在字符编码约定方面遇到问题。负字节的最高有效位为 1。许多编码(如 UTF-8)使用此位来指示字符分布在多个字节上。因此,读取代码输出的应用程序可能会将其解释为 UTF-8。

因此,通过使用String(byte[] data)构造函数,您可以使用默认系统编码来解释字符串。这种编码会有问题,因为输入字节是随机生成的,因为它们是随机生成的。

于 2013-09-17T17:44:31.940 回答
0

从您上面的评论中:

byte[] fileData = new byte[(int)file.length()]
// some stuff
sContent = new String(fileData);

您正在使用字节的默认编码创建一个字符串。它根据编码将 8 位bytes 转换为 16 位chars,并且由于某些字节在您的编码中被认为是无效的,因此它们被转换为未知字符符号,即'?'.

看:

private void p(String s) {
    System.out.println(s);
    System.out.println((int)s.charAt(i));
}
byte[] b= new byte[]{(byte)219};
p(new String(b, "Windows-1250"));
p(new String(b, "Windows-1251"));
p(new String(b, "Windows-1252"));
p(new String(b, "Windows-1253"));
p(new String(b, "UTF-8"));

印刷:

Ű
368
Ы
1067
Û
219
Ϋ
939
�
65533

我假设您正在使用 Windows 1252 代码页在 Windows 上工作。此代码页在位置 129 (= -127) 等处没有任何字符。

不要将二进制非文本数据转换为字符串。

于 2013-09-17T18:02:11.317 回答