FileInputStream将一些值转换为问号

时间:2013-09-17 17:37:44

标签: java fileinputstream

我仍然是Java的业余爱好者,在我学习的同时学习,所以请保持温柔!

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

2 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

根据您的评论:

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

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

请参阅:

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上使用Windows 1252代码页。此代码页在129(= -127)位置没有任何字符,依此类推。

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