Java 使用FileInputStream/ObjectOutputStream发送大文件
我的家庭作业需要帮助,任何帮助都将不胜感激。我可以毫无问题地发送小文件。但当我尝试发送时,比如说1GB文件字节数组发送OutOfMemoryError,所以我需要一个更好的解决方案将文件从服务器发送到客户端。如何改进此代码并发送大文件,请帮助我 服务器代码:Java 使用FileInputStream/ObjectOutputStream发送大文件,java,bytearray,inputstream,outputstream,Java,Bytearray,Inputstream,Outputstream,我的家庭作业需要帮助,任何帮助都将不胜感激。我可以毫无问题地发送小文件。但当我尝试发送时,比如说1GB文件字节数组发送OutOfMemoryError,所以我需要一个更好的解决方案将文件从服务器发送到客户端。如何改进此代码并发送大文件,请帮助我 服务器代码: FileInputStream fis = new FileInputStream(file); byte[] fileByte = new byte[fis.available()]; //This causes the
FileInputStream fis = new FileInputStream(file);
byte[] fileByte = new byte[fis.available()]; //This causes the problem.
bytesRead = fis.read(fileByte);
oos = new ObjectOutputStream(sock.getOutputStream());
oos.writeObject(fileByte);
bos= new BufferedOutputStream(sock.getOutputStream());
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
int n=-1;
byte[] buffer = new byte[8192];
while((n = bis.read(buffer))>-1)
bos.write(buffer,0,n);
客户端代码:
ois = new ObjectInputStream(sock.getInputStream());
byte[] file = (byte[]) ois.readObject();
fos = new FileOutputStream(file);
fos.write(file);
bis=new BufferedInputStream(sock.getInputStream());
fos = new FileOutputStream(file);
int n;
byte[] buffer = new byte[8192];
while ((n = bis.read(buffer)) > 0){
fos.write(buffer, 0, n);}
只需将数组分割成更小的块,这样就不需要分配任何大数组 例如,您可以将数组拆分为16Kb的块,例如
新字节[16384]
,然后逐个发送它们。在接收端,您必须等待一个块被完全读取,然后将它们存储在某个地方,然后从下一个块开始
但是,如果您无法在服务器端分配所需大小的整个阵列,那么您将无法存储您将要接收的所有数据
您还可以在发送数据之前对其进行压缩,以节省带宽(和时间),查看并。只需将阵列拆分为较小的块,这样就不需要分配任何大阵列 例如,您可以将数组拆分为16Kb的块,例如
新字节[16384]
,然后逐个发送它们。在接收端,您必须等待一个块被完全读取,然后将它们存储在某个地方,然后从下一个块开始
但是,如果您无法在服务器端分配所需大小的整个阵列,那么您将无法存储您将要接收的所有数据
您也可以在发送数据之前对其进行压缩,以节省带宽(和时间),查看和。不要将整个文件读入内存,在读取文件时使用一个小缓冲区并进行写入:
BufferedOutputStream bos = new BufferedOutputStream(sock.getOutputStream())
File file = new File("asd");
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
byte[] buffer = new byte[1024*1024*10];
int n = -1;
while((n = bis.read(buffer))!=-1) {
bos.write(buffer,0,n):
}
使用Buffered*优化流的写入和读取不要将整个文件读取到内存中,在读取文件时使用一个小的缓冲区进行写入:
BufferedOutputStream bos = new BufferedOutputStream(sock.getOutputStream())
File file = new File("asd");
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
byte[] buffer = new byte[1024*1024*10];
int n = -1;
while((n = bis.read(buffer))!=-1) {
bos.write(buffer,0,n):
}
使用Buffered*优化流的写入和读取取决于您是否必须自己编写代码,现有库可以解决此问题,例如。如果不使用RMI,只使用普通java序列化,那么可以使用,这有点像可序列化的InputStream。(该库还支持自动神奇地压缩数据) 实际上,如果您只发送文件数据,那么最好放弃对象流并使用DataInput/DataOutput流。首先写入一个表示文件长度的整数,然后将字节直接复制到流中。在接收端,读取整数文件长度,然后精确读取那么多字节
在流之间复制数据时,请使用固定大小的小字节[]在循环中的输入流和输出流之间移动数据块。在线提供了许多关于如何正确执行此操作的示例(例如@ErikFWinter的答案)。根据您是否必须自己编写代码,现有的库可以解决此问题,例如。如果不使用RMI,只使用普通java序列化,那么可以使用,这有点像可序列化的InputStream。(该库还支持自动神奇地压缩数据) 实际上,如果您只发送文件数据,那么最好放弃对象流并使用DataInput/DataOutput流。首先写入一个表示文件长度的整数,然后将字节直接复制到流中。在接收端,读取整数文件长度,然后精确读取那么多字节
在流之间复制数据时,请使用固定大小的小字节[]在循环中的输入流和输出流之间移动数据块。在线提供了许多正确执行此操作的示例(例如@ErikFWinter的答案)。以下是我解决此问题的方法: 客户端代码:
ois = new ObjectInputStream(sock.getInputStream());
byte[] file = (byte[]) ois.readObject();
fos = new FileOutputStream(file);
fos.write(file);
bis=new BufferedInputStream(sock.getInputStream());
fos = new FileOutputStream(file);
int n;
byte[] buffer = new byte[8192];
while ((n = bis.read(buffer)) > 0){
fos.write(buffer, 0, n);}
服务器代码:
FileInputStream fis = new FileInputStream(file);
byte[] fileByte = new byte[fis.available()]; //This causes the problem.
bytesRead = fis.read(fileByte);
oos = new ObjectOutputStream(sock.getOutputStream());
oos.writeObject(fileByte);
bos= new BufferedOutputStream(sock.getOutputStream());
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
int n=-1;
byte[] buffer = new byte[8192];
while((n = bis.read(buffer))>-1)
bos.write(buffer,0,n);
我是这样解决的: 客户端代码:
ois = new ObjectInputStream(sock.getInputStream());
byte[] file = (byte[]) ois.readObject();
fos = new FileOutputStream(file);
fos.write(file);
bis=new BufferedInputStream(sock.getInputStream());
fos = new FileOutputStream(file);
int n;
byte[] buffer = new byte[8192];
while ((n = bis.read(buffer)) > 0){
fos.write(buffer, 0, n);}
服务器代码:
FileInputStream fis = new FileInputStream(file);
byte[] fileByte = new byte[fis.available()]; //This causes the problem.
bytesRead = fis.read(fileByte);
oos = new ObjectOutputStream(sock.getOutputStream());
oos.writeObject(fileByte);
bos= new BufferedOutputStream(sock.getOutputStream());
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
int n=-1;
byte[] buffer = new byte[8192];
while((n = bis.read(buffer))>-1)
bos.write(buffer,0,n);
“发送内存不足异常”在Java中没有这样的事情,DYM?如果是,请具体说明,如果不是,请解释(也特别说明)。顺便说一句,您的第一个代码似乎暗示输入文件始终包含序列化对象。这里是这样吗?哦,对不起,这是OutOfMemoryError,不例外。我不知道您的意思,如果文件包含序列化对象,服务器将发送客户端请求的任何文件。
ObjectOutputStream
和ObjectInputStream
用于序列化对象。如果内容是“任何旧字节”,代码就不应该使用它们。好的,我会这样做,谢谢你,我是新来这里的。“发送内存不足异常”在Java中没有这样的事情,DYM?如果是,请具体说明,如果不是,请解释(也特别说明)。顺便说一句,您的第一个代码似乎暗示输入文件始终包含序列化对象。这里是这样吗?哦,对不起,这是OutOfMemoryError,不例外。我不知道您的意思,如果文件包含序列化对象,服务器将发送客户端请求的任何文件。ObjectOutputStream
和ObjectInputStream
用于序列化对象。如果内容是“任何旧字节”,则代码不应使用它们。好的,我将这样做,谢谢,我是新来的。非常感谢,我将尝试此方法。非常感谢,我将尝试此方法。我遵循此示例,在接收端的while循环中,我打印“编写文件…”。我看到的是,接收器最终处于无限循环中,永远不会完成接收。我可以看到它接收到的文件,文件大小最终达到它应该有多大,然后它停止了,但客户端从未停止思考它接收的数据。如果我关闭接收器并尝试打开文件,则文件已损坏。我遵循此示例,在接收端的while循环中,我打印“Writing file…”。我看到的是,接收器最终处于无限循环中,永远不会完成接收。我可以看到它收到的文件和f