当前位置: 代码迷 >> J2SE >> 使用BufferedOutputStream的write(byte[] b, int off, int len) 是否会复制不完整
  详细解决方案

使用BufferedOutputStream的write(byte[] b, int off, int len) 是否会复制不完整

热度:102   发布时间:2016-04-23 19:58:42.0
使用BufferedOutputStream的write(byte[] b, int off, int len) 是不是会复制不完整?
我写了一个TCP的客户端从cmd命令行接收一个jpg文件的路径,
然后发送数据到服务端,服务端再输出到指定的路径,代码如下:

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

public class Client {
public static void main(String[] args) throws UnknownHostException,IOException {


if(args.length!=1){
System.out.println("Please entry fileName.");
return;
}
File file = new File(args[0]);
if(!file.exists()){
System.out.println("File is not existed.");
return;
}
if(!file.getName().endsWith(".jpg")){
System.out.println("File is not a jpg file.");
return;
}
if(file.length()>1024*1024){
System.out.println("must more than 1M.");
return;
}

Socket s = new Socket(InetAddress.getByName("localhost"),9999);
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(out);


byte[] buf = new byte[1024];
int len = 0;
int lenCount = 0;
while((len = bis.read(buf))!=-1){
//bos.write(buf,0,len);//NOT OK
out.write(buf,0,len);//OK
lenCount = lenCount + len;
}
System.out.println(lenCount);
s.shutdownOutput();

fis.close();
bis.close();
bos.close();
//s.close();
}
}


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

public class Server {
public static void main(String[] args)  throws UnknownHostException,IOException {

ServerSocket ss = new ServerSocket(9999);
Socket s = ss.accept();

String IP = s.getInetAddress().getHostAddress();
int count = 1;

File file = new File("C:\\"+IP+".jpg");

while(file.exists()){
file = new File("C:\\"+IP+"_"+(count++)+".jpg");
}


InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();

BufferedInputStream bis = new BufferedInputStream(in);
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fos);



byte[] buf = new byte[1024*1024*3];
int len = 0;
int lenCount = 0;
while((len = bis.read(buf))!=-1){
System.out.println("A:"+len);//test
bos.write(buf,0,len);
lenCount = lenCount + len;
System.out.println("B:"+lenCount);//test
}

System.out.println(lenCount);

}
}


然后,经过测试,发现BufferedOutputStream对象用write(byte[] b, int off, int len) 方法,
图片总是有一片灰色没有被复制出来。
查阅API文档,该方法“如果请求的长度至少与此流的缓冲区大小相同,则此方法将刷新该缓冲区并将各个字节直接写入底层输出流。因此多余的 BufferedOutputStream 将不必复制数据。 ”

但是查看源码,还是看不懂为什么会这样,
请各位帮忙解答一下,谢谢。
------解决思路----------------------
BufferedOutputStream在发送时会在内部保有一个缓存,以防写入太频繁达到一定量时才会写入底层,在你这里就是out.

你在最后才关掉bos之前就s.shutdownOutput(),等你调用bos.close()时需要把没有刷入的数据刷入底层通道时发现..你TMD居然给我关掉了.

要么就在所有s.shutdownOutput()之前调用bos.flush()或者bos.close().

  相关解决方案