// 上传文件练习(+文件名重复)
// 客户端:数据来自于本地文件,接收服务器反馈
// 服务器:接收到的数据写入本地文件,给出反馈
代码没错但图片不能显示的bos缓存输出流记得调用flush()方法,可能丢失数据
下面是步骤:
先建立serverdir和clientdir文件夹
server.java(运行时要先运行serve服务器再运行client客户端)
package net.test03;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.UUID;
public class server {
public static void main(String[] args) throws IOException {
// 上传文件练习(+文件名重复)
// 客户端:数据来自于本地文件,接收服务器反馈
// 服务器:接收到的数据写入本地文件,给出反馈
// 1.创建对象并绑定端口
ServerSocket ss=new ServerSocket(10000);//和客户端连接的10000端口一致
// 2.等待客户端连接
Socket socket = ss.accept();//如果有客户端连接就会返回客户端的连接对象socket
// 3.读取数据并保存到本地文件
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
//BufferedOutputStream跟本地文件关联,从网络里接收一点数据立马就写到本地文件
String name= UUID.randomUUID().toString().replace("-","");
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("serverdir\\"+name+".png"));
int len;
byte[] bytes = new byte[1024];
while((len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);
}
bos.flush();
// 4.回写数据(给出反馈)
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("上传成功");
bw.newLine();
bw.flush();//输出流自带缓冲区,需要读满缓冲区或者手动刷新或释放资源才能写到文件中
// 5.释放资源
socket.close();
ss.close();
}
}
String name= UUID.randomUUID().toString().replace("-","");
UUID类的random方法在于随机生成不重复的文件名
client.java
package net.test03;
import java.io.*;
import java.net.Socket;
public class client {
public static void main(String[] args) throws IOException {
// 客户端:数据来自于本地文件,接收服务器反馈
// 服务器:接收到的数据写入本地文件,给出反馈
// 1.创建socket对象,并连接服务器
Socket socket=new Socket("127.0.0.1",10000);
// 2.读取本地文件中的数据,并写道服务器
// 因为文件太大所以不用FileInputStream 一个字地读,可以用缓冲流
BufferedInputStream bis=new BufferedInputStream(new FileInputStream("clientdir\\sds.png"));
//获取输出流,准备向服务器写数据
// socket.getOutputStream()字节流一个字节读太慢,所以还用BufferedOutputStream包裹
BufferedOutputStream bos=new BufferedOutputStream(socket.getOutputStream());
byte[] bytes = new byte[1024];
int len;
while((len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);//从本地文件读多少就立马写到服务器中
}
bos.flush();
//往服务器写出结束标记,告诉他文件已经传完了
socket.shutdownOutput();
//3.接收服务器的回写数据 (获得连接通道里的字节流,转成字符流,再用缓冲流包裹,主要想调用其中readline方法)
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line=br.readLine();//就是服务器回写的数据
System.out.println(line);
//4.释放资源
socket.close();
}
}
值得注意的是:在用缓冲输出流时,在关闭输出流前要先调用flush方法,强制缓冲区中的内容输出,并清空缓冲区(因为向某个file写入内容时是先将输出流写到缓冲区,缓冲区写满了才将缓冲区的内容输出到file)当缓冲区没满,部分数据在缓冲区呆着还没满不能输出时,没写到file里面就关流的话会造成数据丢失