【问题标题】:Java Read File Larger than 2 GB (Using Chunking)Java 读取大于 2 GB 的文件(使用分块)
【发布时间】:2012-01-05 17:07:07
【问题描述】:

我正在实现一个文件传输服务器,但在通过网络发送大于 2 GB 的文件时遇到了问题。当我得到我想使用的File 并尝试将其内容读入byte[] 时,问题就开始了。我有一个 for 循环:

for(long i = 0; i < fileToSend.length(); i += PACKET_SIZE){
    fileBytes = getBytesFromFile(fileToSend, i);  


其中getBytesFromFile()fileToSend 读取PACKET_SIZE 字节数,然后在for 循环中将其发送到客户端。 getBytesFromFile() 使用 i 作为偏移量;但是,FileInputStream.read() 中的偏移变量必须是 int。我确信有更好的方法可以将这个文件读入数组,我只是还没有找到它。

我宁愿不使用 NIO,尽管我将来会改用 NIO。放纵我的疯狂:-)

【问题讨论】:

  • 你的文件传输服务器是用什么写的?你使用 servlet 吗?如果是这样,只需使用HttpServletResponse.getOutputStream() 方法并将文件内容直接流式传输到输出流...您不必自己进行任何分块工作。
  • 我用的是SocketsServerSockets,据我所知只能发byte[]。我错过了什么吗?
  • 不,您没有使用 servlet :) 我想我现在看到了您的问题。因为文件太大,int 变得太小。让我写一个答案
  • 您最有可能发现最有效的缓冲区大小约为 32 KB(L1 缓存的大小)

标签: java networking io bytebuffer


【解决方案1】:

您似乎没有正确地从文件中读取数据。在 Java 中从流中读取数据时,标准做法是将数据读入缓冲区。缓冲区的大小可以是您的数据包大小。

File fileToSend = //...
InputStream in = new FileInputStream(fileToSend);
OutputStream out = //...
byte buffer[] = new byte[PACKET_SIZE];
int read;
while ((read = in.read(buffer)) != -1){
  out.write(buffer, 0, read);
}
in.close();
out.close();

请注意,缓冲区数组的大小保持不变。 但是--如果缓冲区不能被填满(比如当它到达文件末尾时),数组的剩余元素将包含来自最后一个数据包的数据,所以你必须忽略这些元素(这个是我的代码示例中的out.write() 行所做的)

【讨论】:

  • 非常感谢!这个 sn-p 真的会派上用场:)
  • @Eliezer 选择自己的“数据包大小”是徒劳的。数据将被缓冲到本地套接字发送缓冲区,以 MTU 大小的块发送到接收器,然后缓冲到套接字接收缓冲区。在数据进入网络之前,所有关于“数据包大小”的痕迹都会消失。只需将上面的缓冲区视为文件读取缓冲区。正如 Peter Lawrey 建议的那样,32k 是一个不错的尺寸。
  • @EJP 有人向我建议,在读/写磁盘时 4096 是一个很好的缓冲区大小,因为这是许多文件系统使用的块大小。不过32k听起来也不错。 :)
  • @Michael 大约 20 年前是这样。如今,磁盘子系统中有如此多的缓存,以至于集群大小几乎无关紧要。更多的是一次获得足够的数据以保持输出缓冲区满。许多年前,我处理过一次打印一行的打印机假脱机程序。它占用了 CPU,因为它被安排在每一行,所以在重负载下系统运行缓慢,打印机运行非常缓慢。我们切换到了一个写入 8192 字节块的假脱机程序,它经常只安排 132/8192:系统运行得更快,打印机运行得快得多
  • @EJP 所以我会直接将缓冲区初始化为 32k 还是必须先执行socket.setSendBufferSize(32k) 之类的操作?我使用 PACKET_SIZE 以防万一该值因任何原因而必须更改,这没什么大不了的。我从学校带过来的东西钻进了我的身体:)
【解决方案2】:

嗯,意识到你对变量 i 的处理不正确..

Iteration 0: i=0
Iteration 1: i=PACKET_SIZE
...
...
Iteration n: i=PACKET_SIZE*n

【讨论】:

  • 我不太确定你在说什么。需要解释一下吗?
  • 如果我没有上面的正确答案,这正是我想要的值。你为什么不告诉我为什么这会是一个问题而不是神秘呢?
猜你喜欢
  • 2014-10-03
  • 2017-10-02
  • 1970-01-01
  • 1970-01-01
  • 2013-08-15
  • 1970-01-01
  • 2015-07-07
  • 2019-05-17
  • 2012-10-13
相关资源
最近更新 更多