【问题标题】:Receiving files over socket通过套接字接收文件
【发布时间】:2014-04-11 07:44:31
【问题描述】:

我正在实现一个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 库解压缩文件。

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)

【问题讨论】:

  • 好吧,给定文件名,它看起来像是用 bzip2 压缩的。有没有试过解压看看内容是否符合你的要求?
  • 我试过了,没用。还有,你是说不解压就不能简单地接收和保存bz2文件吗?
  • (怎么没有帮助?)我没这么说。您可以毫无问题地保存压缩文件。因此,您似乎没有保存您认为保存的内容...需要更多代码(您如何处理命令等)
  • 你是怎么得到接收端的文件大小的?
  • 正如代码中的 cmets 突出显示的那样,来自其他客户端的 $ADCSND 响应包括文件大小。响应的示例是 $ADCSND file files.xml.bz2 0 29725 ZL129715 是以字节为单位的大小。

标签: java xml sockets io


【解决方案1】:

available(). 的常见典型误用在 Java 中复制流所需的内容如下:

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

将此用于任何大小大于零的缓冲区,但最好是几千字节。每次迭代都不需要一个新的缓冲区,也不需要知道有多少数据可以在没有阻塞的情况下读取,因为你必须阻塞,否则你只是在消耗 CPU。但是您确实需要知道每次迭代实际读取了多少数据,这是您的代码首先出现问题的地方。

【讨论】:

  • 感谢您和@fge 的回答,但是,错误Stream is not in the BZip2 format 是由BZip2CompressorInputStream 的构造函数生成的,因此它甚至没有到达你们所指的while 循环。不过我修正了我的错误。
【解决方案2】:

错误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 指定正在发送的文件的压缩(不是必需的)。

【讨论】:

    猜你喜欢
    • 2011-07-28
    • 1970-01-01
    • 2016-12-08
    • 1970-01-01
    • 1970-01-01
    • 2020-12-21
    • 2021-09-15
    • 1970-01-01
    相关资源
    最近更新 更多