【问题标题】:FileInputStream converting some values to question markFileInputStream 将一些值转换为问号
【发布时间】:2013-09-17 17:37:44
【问题描述】:

我仍然是 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;
}

【问题讨论】:

  • 您能否为此发布您的代码部分?
  • @Graham 在问题中发布代码并格式化。这样不可读。
  • 明白了,谢谢:-)

标签: java fileinputstream


【解决方案1】:

根据您上面的评论:

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) 等处没有任何字符。

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

【讨论】:

  • 是的......我想那将是错误。所以我需要返回一个字节类型的数组,并直接将它们操作成整数?
  • 是的。您可以考虑使用来自 Guava 库的类 com.google.common.io 包,以便于数据操作。
  • 谢谢 - 我明天试试。我刚刚想到(站在淋浴间),在程序中将字节加入字符串,然后我将其转换回程序主体中的字节。好尴尬……
  • 谢谢你们俩。这对我来说是一次学习经历:-)
【解决方案2】:

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

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

【讨论】:

  • 欣赏 Martijn,但我的文件是二进制文件(实际上是 WAV)。
  • 是的,我错过了。更新了我的答案。
  • 好的。我曾经尝试通过 readLine 读取,但只得到了部分数据。您是否建议这样做的最佳方法是读取行终止符之间的不确定长度块,然后将它们连接在一起?
  • 检查更新。现在,您发布了代码,我们可以提供帮助。
猜你喜欢
  • 2011-08-11
  • 1970-01-01
  • 1970-01-01
  • 2013-07-09
  • 2015-02-11
  • 2015-07-20
  • 1970-01-01
  • 1970-01-01
  • 2011-03-27
相关资源
最近更新 更多