如何正确写入文件数据?

时间:2011-07-06 14:59:16

标签: java io filestream large-files

我的应用程序无法通过套接字连接正确传输数据并将其正确写入文件。大约65,535字节的文件被破坏,并且不再被设计用于运行它们的程序识别。

我已经能够成功发送小的.doc和.txt文件,但.mp3 .wmv .m4a .avi以及其他任何内容都不起作用。也没有更大的文档。

我已经在互联网上寻找解决这个问题的方法。我已经多次调整I / O代码来解决问题,但它仍然无效!以下是处理发送和接收文件的超类中的I / O代码。如果您需要更多信息/代码的其他部分,请告诉我。

protected void sendFile() throws IOException {
    byte[] bytes = new byte[(int) file.length()];
    buffin = new BufferedInputStream(new FileInputStream(file));
    int bytesRead = buffin.read(bytes,0,bytes.length);
    System.out.println(bytesRead);
    out = sock.getOutputStream();
    out.write(bytes,0,fileBytes);
    out.flush();
    out.close();
}

protected void receiveFile() throws IOException {
    byte[] bytes = new byte[fileBytes];
    in = sock.getInputStream();
    for(int i=0;i<fileBytes;i++) {
        in.read(bytes);
    }
    fos = new FileOutputStream("/Datawire/"+fileName);
    buffout = new BufferedOutputStream(fos);
    buffout.write(bytes,0,fileBytes);
    buffout.flush();
    buffout.close();
}

更新的代码(有效):

    protected void sendFile() throws IOException {
    if((file.length())<63000) {
        byte[] bytes = new byte[(int)file.length()];
        buffin = new BufferedInputStream(new FileInputStream(file));
        buffin.read(bytes,0,bytes.length);
        out = sock.getOutputStream();
        out.write(bytes,0,bytes.length);
        out.close();
    } else {
        byte[] bytes = new byte[32000];
        buffin = new BufferedInputStream(new FileInputStream(file));
        out = sock.getOutputStream();
        int bytesRead;
        while((bytesRead = buffin.read(bytes))>0) {
            out.write(bytes,0,bytesRead);
        }
        out.close();
    }
}

protected void receiveFile() throws IOException {
    if(fileBytes<63000) {
        byte[] bytes = new byte[32000];
        in = sock.getInputStream();
        System.out.println(in.available());
        in.read(bytes,0,fileBytes);
        fos = new FileOutputStream("/Datawire/"+fileName);
        buffout = new BufferedOutputStream(fos);
        buffout.write(bytes,0,bytes.length);
        buffout.close();
    } else {
        byte[] bytes = new byte[16000];
        in = sock.getInputStream();
        fos = new FileOutputStream("/Datawire/"+fileName);
        buffout = new BufferedOutputStream(fos);
        int bytesRead;
        while((bytesRead = in.read(bytes))>0) {
            buffout.write(bytes,0,bytesRead);
        }
        buffout.close();
    }
}

5 个答案:

答案 0 :(得分:2)

问题是你只发送它的大块。也就是说,你只发送了64k的文件。如果文件大于64k,则另一端永远不会看到它。

您希望从BufferedInputStream继续读取,直到read()返回的长度小于-1或小于-1。

答案 1 :(得分:1)

我建议您使用一些好的库来读取和写入文件内容以及套接字读/写。例如Apache Commons IO。如果您自己坚持使用写代码,请立即执行较小的块而不是整个文件。

答案 2 :(得分:1)

您的代码完全错误。这是如何在Java中复制流:

int count;
byte[] buffer = new byte[8192]; // more if you like but no need for it to be the entire file size
while ((count = in.read(buffer)) > 0)
{
  out.write(buffer, 0, count);
}

您应该在发送文件和接收文件时使用它。目前你的发送方法希望整个文件适合内存;适合INTEGER_MAX字节;并且通过read方法读取一个块,甚至不检查结果。你不能假设任何这些东西。你的接收方法是完全垃圾:它只是不断覆盖同一个数组,而不检查任何read()结果。

编辑:您修改的代码同样糟糕或更糟。您正在调用read()来检查EOS,然后抛弃该字节,然后再次调用read()并丢弃它返回的读取计数。你毫无意义地为文件提供了不同的路径&lt; 64000,或63000,或者它是什么,除了给你两个代码路径测试,或者可能是四个,而不是一个,没有任何好处。无论如何,网络最多只能给你1460个字节,那有什么意义呢?您已经有(a)BufferedInputStream,其默认缓冲区大小为8192,以及(b)我的代码使用您喜欢的任何大小的byte []缓冲区。上面的代码适用于两行可执行代码中的任何数据量。你的是20. QED。

答案 3 :(得分:0)

您必须考虑InputStream.read返回读取的字节数,该字节数可能小于文件中的总字节数。

CopyUtils.copy之类的东西为你处理这件事可能会更好。

答案 4 :(得分:0)

你需要循环直到bytesRead&lt;你需要确保 fileBytes 是=&gt;而不是转移的文件。

protected void receiveFile() throws IOException {
    byte [] bytes  = new byte [fileBytes];
    InputStream is = sock.getInputStream();
    FileOutputStream fos = new FileOutputStream("/Datawire/"+fileName);
    BufferedOutputStream bos = new BufferedOutputStream(fos);

    int bytesRead = is.read(bytes,0,bytes.length);
    int current = bytesRead;

    do {
       bytesRead =
          is.read(bytes, current, (bytes.length-current));
       if(bytesRead >= 0) current += bytesRead;
    } while(bytesRead > -1);

    bos.write(bytes, 0 , current);
    bos.flush();
    bos.close();

}