~~
程序运行期间,在进行文件的读取,信息的传递,数据的交换时,往往需要进行各种流的操作。流看似有很多,但只要你学会分类,记住他们的功能特性就能很好的使用他们。接下来就让我们看看java中都有哪些常见的流吧。
首先,我们可以先给流做一个分类,所有的流总体都可以分为两大类,一类是输入流InputStream,一类是输出流OutputStream,输入流进行读操作,把所有的数据读进来,输出流进行写操作,把所有读到的数据写出去。
那么输入和输出又分为两种形式:一种是以字节的形式进行输入输出,另一种是以字符的形式输入输出。
所有输入流都是抽象类InputStream(字节输入流)或Reader(字符输入流)的子类,而所有输出流都是抽象类OutputStream(字节输出流)或抽象类Writer(字符输出流)的子类。
~~接下来,由于篇幅原因和一些流的功能大体相似,不可能全部一一细讲,所以我只简单讲一下后面程序所用到的一些流。想了解两台机子是如何连接的可以关注上一篇文章
链接: https://blog.csdn.net/qq_41512314/article/details/107636086
抽象类,所有字节输入流的父类,不能实例化,InputStream的作用是标志那些从不同数据起源产生输入的类。这些数据起源包括(每个都有一个相关的InputStream子类):
(1) 字节数组
(2) String对象
(3) 文件
(4) “管道”,它的工作原理与现实生活中的管道类似:将一些东西一端置入,它们在另一端输出。
(5) 一个由其他种类的流组成的序列,以便我们将其统一收集合并到一个流内。
(6) 其他数据集,如Internet连接等。
抽象类,所有字节输出流的父类,不能实例化,其作用与InputStream相似
数据输入流,允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。例如文件存取,有时只是要存储一个对象的
成员数据,而不是整个对象的信息,成员数据的类型假设都是Java的基本数据类型,这样的需求不必要使用到与输入、输出相关的流对象,
可以使用DataInputStream、DataOutputStream来写入或读出数据。
参考DataInputStream,只是把输入变成了输出,另外要注意的是DataInputStream和DataOutputStream都是高级流
是线程安全的缓冲字节输入流BufferedInputStream是高级流,不能直接对文件进行操作,只有低级流才能直接与文件相连,所以需套接一个低级流
例如:DataInputStream fis = new DataInputStream(new BufferedInputStream(new FileInputStream(filePath)));
与缓冲字节输入流相似,不能直接对文件进行操作,需要套接一个低级流
文件字节输入流,可以对文件数据以字节的形式进行读取操作如读取图片视频等,另外注意的是FileInputStream是一个低级流
与FileInputStream相似,是对文件数据以字节形式进行写入操作,是低级流
补充:
~~字符流
Reader与Writer 带有缓冲区。
Reader:抽象类,所有字符输入流的父类,不能实例化
常用的低级流有:FileReader等
高级流有:BufferedReader、InputStreamReader等
以readLine()方法读一行字符。
Writer:抽象类,所有字符输出流的父类,不能实例化
常用的低级流有:StringWriter、FileWriter等
高级流有:BufferedWriter、PrintWriter等
以writer()和print()方法写入。
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 文件传输服务器端
*/
public class FileServer {
int port=8089;//设置端口号
/*
* 接收客户上传的文件并保存
*/
public void UploadFile() {
try {
ServerSocket server=new ServerSocket(port);
while(true) {
Socket socket = server.accept();
//数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。
DataInputStream dataIs=new DataInputStream(socket.getInputStream());
//获取socket的输出流进行写操作
OutputStream os=socket.getOutputStream();
/*
* 1.获取文件名
*/
String filename="E:\\";
//使用UTF-8的编码格式读取数据
filename += dataIs.readUTF();
System.out.println("文件名:"+filename);
//文件输出流,进行写操作
FileOutputStream fos=new FileOutputStream(filename);
//创建缓冲区,关联输入流与输出流
byte[] bs = new byte[1024];
int length = 0;
//一次读取b个字节数据直到末尾
while((length=dataIs.read(bs))!=-1) {
fos.write(bs, 0, length);
}
fos.close();
os.close();
dataIs.close();
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
/*
* 接收客户端的下载请求,将本地文件传输给客户端
*/
public void DownFiles(String filePath) {
try {
while(true) {
ServerSocket server = new ServerSocket(port);
//选择进行传输的文件
File file = new File(filePath);
System.out.println("文件长度:"+(int)file.length());
Socket socket = server.accept();
System.out.println("建立socket链接");
//BufferedInputStream是高级流,不能直接对文件进行操作,只有低级流才能直接与文件相连,所以需套接一个低级流
//是线程安全的缓冲字节流
DataInputStream fis = new DataInputStream(new BufferedInputStream(new FileInputStream(filePath)));
DataOutputStream ps = new DataOutputStream(socket.getOutputStream());
//将文件名及长度传给客户端
ps.writeUTF(file.getName());
System.out.println(file.getName());
ps.flush();
byte[] buf = new byte[8 * 1024];
while (true) {
int read = 0;
if (fis != null) {
read = fis.read(buf);
}
if (read == -1) {
break;
}
ps.write(buf, 0, read);
}
ps.flush();
//关闭socket连接
fis.close();
socket.close();
System.out.println("文件传输完成");
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new FileServer().UploadFile();
}
}
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.Socket;
/**
* 文件传输客户端
* @author 凌风
*
*/
public class FileClient {
private String ip="localhost";//设置成服务器ip,此处先设为本地ip进行一台电脑上传测试
private int port = 8089;//设置端口号
public void UploadFile(String filePath) {
try {
//将本地文件上传到服务器端
Socket socket=new Socket(ip,port);
while(true) {
//选择传输文件
File file=new File(filePath);
System.out.println("文件长度"+(int)file.length());
//读取上传的文件
DataInputStream dis=new DataInputStream(new BufferedInputStream(new FileInputStream(filePath)));
//写操作
DataOutputStream dos=new DataOutputStream(socket.getOutputStream());
dos.writeUTF(file.getName());
dos.flush();
byte [] bs=new byte[8*1024];
while(true) {
int read=0;
if(dis!=null) {
dis.read(bs);
}
if(dis==null) {
break;
}
dos.write(bs, 0, read);
}
dos.flush();
dis.close();
socket.close();
System.out.println("文件传输完成");
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 从服务器端下载文件
*/
public void DownFiles(String filePath) {
try {
Socket socket=new Socket(ip,port);
while(true){
DataInputStream dis=new DataInputStream(new FileInputStream(filePath));
DataOutputStream dos=new DataOutputStream(socket.getOutputStream());
//1.获取文件名
String filename="E:\\";
filename +=dis.readUTF();
System.out.println("文件名:"+filename);
//文件输出流,进行写操作
FileOutputStream fos=new FileOutputStream(filename);
byte [] bs=new byte[1024];
int lenght=0;
while((lenght=dis.read(bs))!=-1) {
//2、把socket输入流写到文件输出流中去
fos.write(bs, 0, lenght);
}
fos.close();
dos.close();
dis.close();
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String arg[]) {
Scanner sc=new Scanner(System.in);
//写出你要传输文件的路径
String filePath=sc.nextLine();
//String filepath="D:\\test.txt";
new FileClient().UploadFile(filePath);
}
}
测试步骤请参考:
链接: https://blog.csdn.net/qq_41512314/article/details/107636086