通过套接字接收文件

时间:2014-04-11 07:44:31

标签: java xml sockets io

我正在实施Direct Connect客户端。我正在使用NMDC protocol。我可以连接到集线器和其他连接的客户端。我试图从每个客户端检索文件列表,我知道为了做到这一点,必须从另一个客户端下载文件files.xml.bz2。下载文件的协议如下:

  ->   $ADCGET file <filename> <params>|
  <-   $ADCSND file <fileName> <params>|
  <-   (*** binary data is now transfered from client B to client A ***)

我正在尝试使用收到的二进制数据创建名为files.xml.bz2的文件。这是我的代码:

//filesize is provided through the $ADCSND response from other client
byte[] data = new byte[filesize];
/*

Reading binary data from socket inputstream

*/
int read = 0;                       
for (int i=0; read<filesize;){
    int available = in2.available();
    int leftspace = filesize-read;
    if (available>0){
        in2.read(data, read, available>leftspace? leftspace:available);
        ++i;
    }
    read += (available>leftspace? leftspace:available)+1;
}
/*
writing the bytes to an actual file
*/
ByteArrayInputStream f = new ByteArrayInputStream(data);
FileOutputStream file = new FileOutputStream("files.xml.bz2");
file.write(data);
file.close();

创建文件,但内容(files.xml)不可读。在firefox中打开它:

XML Parsing Error: not well-formed

查看终端中的内容只读取二进制数据。我做错了什么?

修改

我还尝试使用Apache Ant的bz2 libray解压缩文件。

ByteArrayInputStream f = new ByteArrayInputStream(data);
BZip2CompressorInputStream bzstream = new BZip2CompressorInputStream(f);
FileOutputStream xmlFile = new FileOutputStream("files.xml");
byte[] bytes = new byte[1024];
while((bzstream.read(bytes))!=-1){
    xmlFile.write(bytes);
}
xmlFile.close();
bzstream.close();

我收到错误,这是堆栈跟踪:

java.io.IOException: Stream is not in the BZip2 format
    at org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream.init(BZip2CompressorInputStream.java:240)
    at org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream.<init>(BZip2CompressorInputStream.java:132)
    at org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream.<init>(BZip2CompressorInputStream.java:109)
    at control.Controller$1.run(Controller.java:196)

2 个答案:

答案 0 :(得分:0)

通常,available().的典型误用你需要用Java复制流所需的全部内容如下:

while ((count = in.read(buffer)) >= 0)
{
     out.write(buffer, 0, count);
}

使用大于零的任何大小的缓冲区,但最好是几千字节。每次迭代都不需要新的缓冲区,并且您不需要知道有多少数据可以无阻塞地读取,因为您必须阻止,否则您只是在吸烟。但是你确实需要知道每次迭代实际读取了多少数据,这是你的代码首次出现故障的地方。

答案 1 :(得分:0)

错误java.io.IOException: Stream is not in the BZip2 format由类BZip2CompressorInputStream的构造函数生成。我决定扫描字节,寻找magic number以确保文件是bz2格式,结果证明Java是对的 - 它不是bz2格式。

在检查Jucy的源代码后,我看到原因是我发送给其他客户端的命令略有错误,实质上,这个错误导致我的协议实现出错。解决方案是:

替换:

$ADCGET file files.xml.bz2 0 -1 ZL1|

使用:

$ADCGET file files.xml.bz2 0 -1|

ZL1指定压缩正在发送的文件(不是必需的)。