2012-01-18 105 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>