我写了一个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().