2012-03-07 341 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