[英]Error while sending large files through socket
我正在尝试通过套接字发送大文件。 该程序适用于较小的文件(例如html页面或pdf),但是当我发送超过3/4 mb的文件时,输出始终会损坏(使用文本编辑器查看它时,我注意到最后几行始终会丢失)。
这是服务器的代码:
BufferedInputStream in = null;
FileOutputStream fout = null;
try {
server = new ServerSocket(port);
sock = server.accept();
in = new BufferedInputStream(sock.getInputStream());
setPerc(0);
received = 0;
int incByte = -1;
fout = new FileOutputStream(path+name, true);
long size = length;
do{
int buffSize;
if(size >= 4096){
buffSize = 4096;
}else{
buffSize = 1;
}
byte[] o = new byte[buffSize];
incByte = in.read(o, 0, buffSize);
fout.write(o);
received+=buffSize;
setPerc(calcPerc(received, length));
size -= buffSize;
//d("BYTE LETTI => "+incByte);
}while(size > 0);
server.close();
} catch (IOException e) {
e("Errore nella ricezione file: "+e);
}finally{
try {
fout.flush();
fout.close();
in.close();
} catch (IOException e) {
e("ERRORE INCOMINGFILE");
}
}
pr.release(port);
这是客户端的代码:
FileInputStream fin = null;
BufferedOutputStream out = null;
try {
sock = new Socket(host, port);
fin = new FileInputStream(file);
out = new BufferedOutputStream(sock.getOutputStream());
long size = file.length();
int read = -1;
do{
int buffSize = 0;
if(size >= 4096){
buffSize = 4096;
}else{
buffSize = (int)size;
}
byte[] o = new byte[buffSize];
for(int i = 0; i<o.length;i++){
o[i] = (byte)0;
}
read = fin.read(o, 0, buffSize);
out.write(o);
size -= buffSize;
//d("BYTE LETTI DAL FILE => "+read);
}while(size > 0);
} catch (UnknownHostException e) {
} catch (IOException e) {
d("ERRORE NELL'INVIO DEL FILE: "+e);
e.printStackTrace();
}finally{
try {
out.flush();
out.close();
fin.close();
} catch (IOException e) {
d("Errore nella chiusura dei socket invio");
}
}
我认为这与缓冲区大小有关,但我无法弄清这里出了什么问题。
这是不正确的:
byte[] o = new byte[buffSize];
incByte = in.read(o, 0, buffSize);
fout.write(o);
您正在阅读最多 buffSize
字节,然后写准确 buffSize
字节。
您在另一端也正在做相同的事情。
您可以从文件中读取1时逃脱。但是,当你从一个套接字读那么read
容易给你一个部分填充缓冲,特别是如果写到底能不能始终保持阅读的未来最终,因为您正在通过大量传输来锤击网络。
正确的方法是:
incByte = in.read(o, 0, buffSize);
fout.write(o, 0, incByte);
1-已经观察到,当您从本地文件read
, read
调用通常会为您提供所请求的所有字节(取决于文件大小等)。 因此,如果将buffSize
设置为文件的长度,则从本地文件读取该代码可能会起作用。 但这是一个坏主意,因为您所依赖的行为是Java或典型操作系统无法保证的。
您可能在这里遇到问题。
read = fin.read(o, 0, buffSize);
out.write(o);
在这里, read提供了您实际上刚刚读取的字节数。 在下一行,您应该只写出已读取的字节数。
换句话说,您不能期望正在读取的文件的大小是缓冲区大小的倍数。
同样,请检查您的服务器代码。
在Java中复制流的正确方法如下:
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
其中count
是一个int,
buffer
是一个长度大于0(通常为8k)的byte[]
数组。 您不需要在循环内分配字节数组,也不需要特定大小的字节数组。 具体地说,分配与文件一样大的缓冲区完全浪费了空间。 它仅适用于Integer.MAX_VALUE
字节的文件,并且无法缩放。
您确实需要保存“ read()”返回的计数,并在“ write()”方法中使用它,如上所示。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.