2012-03-07 342 views
21

我正在将文件读取到块中的字节数组中,并通过POST请求将其发送到网络服务器。这并不复杂,我在使用完全相同的代码之前完成了它。这一次,我注意到当我的图像到达服务器时看起来很奇怪,所以我决定查看正在发送的字节数组和正在接收的字节数组,以确保它们是相同的。不是。在java发送端,字节数组包含负数。在C#接收方,没有负数。Java字节数组包含负数

在接收侧的前15个字节(C#)

137 
80 
78 
71 
13 
10 
26 
10 
0 
0 
0 
13 
73 
72 
68 

那些相同字节,但在发送侧(JAVA)

-119 
80 
78 
71 
13 
10 
26 
10 
0 
0 
0 
13 
73 
72 
68 

所有非负数的是相同的,-119不是唯一的负数,他们都结束了。我确实注意到-119和137相距256,并想知道这是否与它有关。

我使用读取图像的代码(JAVA)

public static byte[] readPart(String fileName, long offset, int length) throws FileNotFoundException, Exception 
{ 
    byte[] data = new byte[length]; 
    File file = new File(fileName); 
    InputStream is = new FileInputStream(file); 
    is.skip(offset); 
    is.read(data,0,data.length); 
    is.close(); 
    return data; 
} 

我用写数据的代码(C#)

private void writeFile(string fileName, Stream contents) 
    { 
     using (FileStream fs = new FileStream(fileName, FileMode.Append, FileAccess.Write, FileShare.ReadWrite)) 
     { 
      int bufferLen = 65000; 
      byte[] buffer = new byte[bufferLen]; 
      int count = 0; 
      while ((count = contents.Read(buffer, 0, bufferLen)) > 0) 
      { 
       fs.Write(buffer, 0, count); 
      } 
      fs.Close(); 
     } 
     contents.Close(); 
    } 

我不知道这是总是发生的事情,我从来没有注意到它,或者如果它决定发生可怕的错误。我所知道的是,此代码之前的工作非常类似,并且现在不工作。

如果有人有任何建议或解释我会很感激。

编辑: 我的图像看起来很奇怪的原因是我如何调用readPart方法。

byte[] data = FileUtilities.readPart(fileName,counter,maxFileSize);//counter is the current chunk number 

如何,我会一直称这是

byte[] data = FileUtilities.readPart(fileName,counter*maxFileSize,maxFileSize);//the current chunk * cuhnksize for the offset... 

谢谢大家,我现在显著少困惑:)

+0

刚刚尝试使用数据[i] =(byte)Math.abs((int)data [i])发送所有字节之前,这不起作用,它告诉我图像在那时已经腐败了。 – nick 2012-03-07 21:35:28

+0

它只是整个文件的第一个字节,还是每个块的第一个字节? – 2012-03-07 21:37:37

+2

Java的'byte'是有符号的,所以不可能有137个字节存储在'byte'中。也许你的问题来自这个? – Laf 2012-03-07 21:37:45

回答

25

Java没有无符号字节;所有字节都被视为有符号。就这样。

所有真正重要的是你如何认为的字节,因为你很少真正需要做字节比较。正如你发现的,唯一重要的不同之处在于它们打印出的是已签名的。

如果你喜欢,你可以使用例如番石榴的UnsignedBytes实用程序将Java字节视为未签名,但实际上并没有太大的实际区别。

+3

而在C#中,'byte'是无符号的,'sbyte'是有符号的。 – 2012-03-07 21:36:30

26

在Java中,byte是一个有符号的值(使用two's complement来对负值进行编码),所以如果大多数人意外发现它是正确的。

要将byte转换为无符号int值,使用b & 0xff

+2

我可以证实它的工作原理,并且了解它。同时加上+256到-25(在我的情况下是0xE7)实际上也可以。尽管如此,我还是不完全了解这里的实际问题。你能解释一下更多的位移吗? – 2014-10-15 12:42:10

+1

'(byte)0xE7 + 256'将有符号的字节转换为'int'(仍然给你-25),然后加上'(int)256'。要充分理解正在发生的事情,您必须首先明白,一切都只是一种模式,而您*通过以某种方式定义数学运算来编码实际事物,从而赋予这些位。有了这些知识,您可以阅读链接的文章以了解位模式的含义。下一步是了解Java的类型扩展规则:http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html – 2014-10-16 09:47:13

3

也许它是与Java的字节进行签名(范围-128到127)的事实,而C#的是无符号数(0〜255) :)。这些信息在二进制文件中是相同的,只是解释不同而已。

9

作为进一步说明,假设您有137作为无符号字节。这表现为:

1000 1001 

这个二进制值,当为有符号的补数表示,原来是-119。 (-128 + 9

128上的任何无符号字节值都会受到差异的影响,因为最左边的位以这种方式被双补码方案使用。

+0

最后,我能够验证字节是否正确调试。我有-16,而这又是240作为ubyte(240 - 256)= - 16 – 2015-11-26 10:59:44