【问题标题】:Java program won't transfer files larger than 64KBJava 程序不会传输大于 64KB 的文件
【发布时间】:2015-03-27 10:40:07
【问题描述】:

我正在制作一个将文件从服务器发送到客户端的程序。该程序本身运行,适用于任何 64KB 及以下的文件,但是当我尝试发送大于该文件的文件时,它只传输 64KB,例如,我尝试发送一个 232KB 的文件 test.txt,程序只输出了一个 64KB文件收到Test.txt。

这是服务器代码

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class FileTransferServer {

public static void main(String[] args) throws IOException {
    ServerSocket servsock = new ServerSocket(1234);
    File myFile = new File("C:/Users/Owner/Downloads/test.txt");
    while (true) {
      Socket sock = servsock.accept();
      byte[] mybytearray = new byte[(int) myFile.length()];
      BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myFile));
      bis.read(mybytearray, 0, mybytearray.length);
      OutputStream os = sock.getOutputStream();
      os.write(mybytearray, 0, mybytearray.length);
      os.flush();
      sock.close();
    }
}
}

这是客户

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.Socket;

public class FileTransferClient {
public static void main(String[] argv) throws Exception {
Socket sock = new Socket("127.0.0.1", 1234);
byte[] mybytearray = new byte[409600];
InputStream is = sock.getInputStream();

FileOutputStream fos=newFileOutputStream("C:/Users/Owner/Downloads/receivedTest.txt");
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    int bytesRead = is.read(mybytearray, 0, mybytearray.length);
    bos.write(mybytearray, 0, bytesRead);
    bos.close();
    sock.close();
  }
}

任何帮助将不胜感激,无法找出发生了什么。

编辑:谢谢大家,它现在可以工作了,我将客户端代码更改为:

import java.io.*;
import java.net.*;

public class FileTransferClient {
  public static void main(String[] argv) throws Exception {
    Socket sock = new Socket("127.0.0.1", 1234);
    byte[] mybytearray = new byte[1024];
    int count;
    InputStream is = sock.getInputStream();
    FileOutputStream fos = new FileOutputStream("C:/Users/Owner/Downloads/receivedTest.jpg");
    BufferedOutputStream bos = new BufferedOutputStream(fos);

    while ((count = is.read(mybytearray)) > 0)
    {
        bos.write(mybytearray, 0, count);
    }
    bos.close();
    sock.close();
  }
}

【问题讨论】:

  • 您是否尝试过分块而不是整体地写入/读取文件?另外,当文件超过 400kb 时会发生什么?
  • 你知道is.read 不会读取整个数组,对吧?它读取“1 到 mybytearray.length 之间的任意数量的字节”。服务器上的bis.read 相同。 (write 像你期望的那样工作,并且写了整个事情)

标签: java sockets limit file-transfer


【解决方案1】:

常见问题。

  1. 您假设该文件适合内存。
  2. 您假设文件大小适合 int。
  3. 您假设read() 填满了缓冲区。

java中复制流的规范方法如下:

byte[] buffer = new byte[8192]; // any size greater than 0 will work
int count;
while ((count = in,read(buffer)) > 0)
{
    out.write(buffer, 0, count);
}

我很惊讶您从代码中获得了多达 64k 的数据。如果没有循环,您只会得到一个套接字接收缓冲区满,在 Windows 上可能低至 8k。

【讨论】:

  • 谢谢,它成功了,我把客户端代码改成了这个,它能够传输一个 160KB 的文件。
【解决方案2】:

你不应该一次写整个东西,尤其是不要写到一个套接字上。你想做一些类似的事情

byte[] buf = new byte[4096];
int bytesRead = 0;
while((bytesRead = is.read(buf)) > 0){
    os.write(buf, 0, bytesRead);
}

通过这种方式,您可以读取/写入任何大小而不会出现错误,也不必担心内存不足或尝试向服务器发送过大请求时出错。

【讨论】:

    【解决方案3】:

    你尝试它的方式会给你OutOfMemoryError,因为你试图将整个文件读入内存,直到它被发送,这完全没有必要。

    最好的方法是读取和写入块,就像在接收代码中所做的那样。

    【讨论】:

    • 我很想解释一下这些反对意见。点赞这个。他的接收代码中没有循环,但是说 OP 必须读取和写入块并没有错。没有其他办法。
    • 这是一个很好的建议,但显然不是问题的答案。将整个文件读入内存是否是一个好主意完全取决于文件的大小,并且在小文件大小上耗尽内存的可能性很小。
    • @PeterWalser 分块读取和写入文件,正确, 问题的答案。跨度>
    猜你喜欢
    • 1970-01-01
    • 2020-03-23
    • 2021-03-08
    • 2020-12-06
    • 1970-01-01
    • 2013-10-25
    • 1970-01-01
    • 1970-01-01
    • 2010-12-08
    相关资源
    最近更新 更多