2012-01-18 106 views
5

我正在使用TCP套接字將文件從C#客戶端傳輸到Java服務器。在C#客戶端上,我將文件轉換爲字節數組進行傳輸並使用NetworkStream發送。讀取Java中的C#字節數組

在Java服務器上,我使用以下代碼將接收到的字節數組轉換回文件;

public void run() { 

     try { 

      byte[] byteArrayJAR = new byte[filesize]; 
      InputStream input = socket.getInputStream(); 

      FileOutputStream fos = new FileOutputStream(
        "Controller " + controllerNumber + ".jar"); 

      BufferedOutputStream output = new BufferedOutputStream(fos); 

      int bytesRead = input.read(byteArrayJAR, 0, byteArrayJAR.length); 
      int currentByte = bytesRead; 

      System.out.println("BytesRead = " + bytesRead); 

      do { 

       bytesRead = input.read(
         byteArrayJAR, 
         currentByte, 
         (byteArrayJAR.length - currentByte)); 

       if (bytesRead >= 0) { 

        currentByte += bytesRead; 

       } 
      } 

      while (bytesRead > -1); 

      output.write(byteArrayJAR, 0, currentByte); 
      output.flush(); 
      output.close(); 
      socket.close(); 

     } 

     catch (IOException e) { 

      e.printStackTrace(); 

     } 
} 

的代碼,如果接收到的字節數組來自與Java編程的客戶端,但對於C#客戶代碼在掛起上述工作do-while循環在bytesRead = input.read(...)方法。

有沒有人知道爲什麼代碼掛在C#客戶端而不是Java客戶端?根據println消息的輸出數據肯定是由InputStream接收的,並且在bytesRead變量初始化時讀取一次,但不在do-while循環中讀取。

任何解決方案或建議,以克服這個問題將受到歡迎。

Regards,

Midavi。基於

+2

向我們展示您的C#代碼。你可能錯過了一個'Flush()'? – dtb 2012-01-18 16:53:20

+3

如果文件大小不小於或等於有效發送的數據,則read()將被阻止。你不應該試圖猜測你要接收的數據的大小,你必須保持閱讀,直到流爲空。 – Viruzzo 2012-01-18 16:55:36

回答

0

上:http://docs.oracle.com/javase/1.4.2/docs/api/java/io/InputStream.html

int bytesRead = input.read(byteArrayJAR, 0, byteArrayJAR.length); 

讀取所有可用的字節,這意味着你的字節數據alread在byteArrayJAR或我在這裏完全地錯了嗎?

編輯:

剛纔檢查我的一些項目......我從安卓< => C#服務器應用程序發送數據。

我用String data = input.readLine();(JAVA)和_sw.WriteLine("Testdata");(C#)

+0

這也是我相信的。據我所知,如果正在發送的文件是相當大的bytesRead初始化後,更多的字節可能變得可用。 do-while循環用於確保在重建爲文件之前讀取整個字節數組。或者我有這個錯誤? – midavi 2012-01-18 17:04:01

1

你需要從C#,而不是byte發送您的字節sbyte

另外,您應該將do/while循環更改爲常規循環。如果您在第一次通話時已經閱讀了來自input.read的流中的所有內容,則您將在第二次通話時阻止,因爲read將等待輸入。

+0

這不應該導致它掛起,但可能在某個時候是一個問題。 – user7116 2012-01-18 17:31:46

+0

,直到你解決了這個問題,你將無法可靠地解決由於二進制數據錯誤而導致的任何其他問題。 – 2012-01-18 17:57:11

+0

帶符號的字節與無符號字節的寬度相同,因此,表示法的差異不會影響從套接字讀取。 OP的*當前*問題在別處。 – user7116 2012-01-18 19:03:37

0

由於在一般情況下您無法預先發送數據量,因此最好是以塊的形式接收數據並忽略大數組中的偏移量。如果數據比數組大,或者數組比數組小,那麼你的代碼就不能很好地處理這種情況。

一個更簡單的情況下,將刪除currentByte偏移:

InputStream input = socket.getInputStream(); 
BufferedOutputStream output = new BufferedOutputStream(
    new FileOutputStream("test.exe")); 

byte[] bytes = new byte[2048]; 
int bytesRead; 
do { 
    bytesRead = input.read(bytes, 0, bytes.length); 
    System.out.println("size: " + bytes.length + " read(): " + bytesRead); 

    if (bytesRead > 0) { 
     output.write(bytes, 0, bytesRead); 
    } 
} while (bytesRead > -1); 

output.close(); 
socket.close(); 
input.close(); 

而且我用在客戶端下面的C#代碼:

if (!args.Any()) 
{ 
    Console.Error.WriteLine("Usage: send.exe <executable>"); 
    Environment.Exit(-1); 
} 

using (var client = new TcpClient("localhost", 10101)) 
using (var file = File.Open(args.First(), FileMode.Open, FileAccess.Read)) 
{ 
    file.CopyTo(client.GetStream()); 
} 

客戶端的結果:

C:\temp>csc send.cs 
Microsoft (R) Visual C# 2010 Compiler version 4.0.30319.1 
Copyright (C) Microsoft Corporation. All rights reserved. 


C:\temp>send send.exe 

C:\temp> 

服務器端結果:

C:\temp>javac.exe Server.java 

C:\temp>java Server 
size: 2048 read(): 2048 
size: 2048 read(): 2048 
size: 2048 read(): 512 
size: 2048 read(): -1 

C:\temp>test.exe 
Usage: send.exe <executable>