为什么要学习IO流
文件在程序中是以流的形式来操作的(流也是Java程序和磁盘文件交互的方式)
IO流则是针对程序而已,I是输入,O是输出
IO流的知识体系
字节流与字符流
- 字节流输入:FileInputStream
public void readFile02() {
String filePath = "F:\\hello.txt";
//定义一个字节数组(一次读取8个字节)
byte[] bytes = new byte[8];
int readLen = 0;//这里表示读取的长度
FileInputStream fileInputStream = null;//创建空输入流
try {
fileInputStream = new FileInputStream(filePath);//创建输入流
while((readLen = fileInputStream.read(bytes)) != -1){//这里是按数组读取,一个回车直接读了一行
System.out.println(new String(bytes,0,readLen));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileInputStream.close();//关闭输入流
} catch (IOException e) {
e.printStackTrace();
}
}
}
小TIPS:这里的read()方法读取换行符会直接读取为一个空行,readline()方法在包装流bufferreader会用到,届时再详细区分。
- 字节流输出:FileoutputStream
public void writeFile(){
String filrepath = "F:\\hello.txt";
FileOutputStream fileOutputStream = null;
//创建一个写入对象
try {
fileOutputStream = new FileOutputStream(filrepath,true);
String str = "hsp!world!";
//也可以定义一个字节数组,提高写入的效果
byte[] buf = new byte[1024];
int readLen = 0;
while ((readLen = fileInputStream.read(buf)) != -1) {
fileOutputStream.write(buf, 0, readLen);//一定要使用这个方法
}
fileOutputStream.write(str.getBytes());//写入一个字符串数组,这里记住必须是字节数组
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileOutputStream.close();//关闭字符串流
} catch (IOException e) {
e.printStackTrace();
}
}
}
其实就是根据文件路径创建流,然后使用read()和write()方法
- 字符流输入: FileReader
public void readFile02(){
String filePath = "F:\\hello.txt";
FileReader fileReader = null;
//设置读取的字符
int readLen = 0;
char[] chars = new char[9];
//创建读取对象
try {
fileReader = new FileReader(filePath);//原理跟字节流的一模一样!!!
while((readLen = fileReader.read(chars))!= -1){
System.out.println(new String(chars,0,readLen));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 字符流输出:FileWriter
public void fileWriter(){
String filePath = "F:\\hello.txt";
FileWriter fileWriter = null;
char[] chars = {'a','b','c'};
try {
fileWriter = new FileWriter(filePath);
fileWriter.write(chars);//默认是覆盖写入,也可以直接用数组写入
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
字节流与字符流的区别
1、定义
字节流是一种执行8位字节输入和输出的机制,基本单元为字节;而字符流是Java中执行16位Unicode输入和输出操作的机制,基本单元为Unicode码元。
2、结尾
字节流以stream结尾;而字符流以reader和writer结尾
3、处理方式
字节流是最基本的,采用ASCII编码;它通常用于处理二进制数据,它是按字节来处理的,实际上它可以处理任意类型的数据,但它不支持直接写入或读取Unicode码元。
字符流采用Unicode编码,它是按虚拟机的encode来处理,也就是要进行字符集的转化;它通常处理文本数据,它支持写入及读取Unicode码元。
4、缓冲区
字节流默认不使用缓冲区;字符流使用缓冲区。
节点流与包装流
在实际应用中,通常使用包装流来对底层的字节流进行包装,比如增加缓冲区,换行读取等方法,提高输入输出的效率。
-
BufferedReader(在基础字符流上FileReader包装得到)
public void BufferFile02(){ String filePath = "F:\\hello.txt"; FileReader fileReader = null; //设置读取的字符 String line; //创建读取对象 try { fileReader = new FileReader(filePath);//原理跟字节流的一模一样!!! BufferedReader bos = new BufferedReader(fileReader);//对字节流进行包装 while((line = bos.readLine())!= null){ System.out.println(line);//直接按行读取,极大地提高了读取的效率 } } catch (IOException e) { e.printStackTrace(); } finally { try { bos.close();//只需要关闭包装流就好,节点流可以自动关闭 } catch (IOException e) { e.printStackTrace(); } } }
-
BufferWriter (在基础字符流上FileWriter修饰得到)
String filePath = "e:\\ok.txt"; //创建 BufferedWriter //说明: //1. new FileWriter(filePath, true) 表示以追加的方式写入 //2. new FileWriter(filePath) , 表示以覆盖的方式写入 BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath)); bufferedWriter.write("hello, 韩顺平教育!");//直接写入 bufferedWriter.newLine();//插入一个和系统相关的换行 bufferedWriter.write("hello3, 韩顺平教育!"); bufferedWriter.newLine(); //说明:关闭外层流即可 , 传入的 new FileWriter(filePath) ,会在底层关闭 bufferedWriter.close();
———此外,为了防止每一次输入输出都要从底层调用数据,buffer流设置了缓冲区,这个在网络通讯中起到了很大的作用。
序列化与对象流(包装流的一部分)
由于ObjectOutputStream实现了Serializable,因此常用来进行数据的序列化
String filePath = "e:\\data.dat";
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
oos.writeInt(100);// int -> Integer (实现了 Serializable)数据的序列化
oos.writeBoolean(true);// boolean -> Boolean (实现了 Serializable)
转换流(包装流)
相当于writer和reader的子类,可以把字节流转换编码格式,同时转化为字符流。
//2. 指定编码 gbk
InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), "gbk");
//3. 把 InputStreamReader 传入 BufferedReader
BufferedReader br = new BufferedReader(isr);
br.close();//只需要关闭外层流
close()和flush()的区别
close包含flush功能,但是flush具备刷新完,还可以继续写操作,close执行完了就流关闭了,不能再写入,所以,不能用close来代替flush。
此处贴个链接,学习一下大佬通过动手来分清两者差异的真操作
Properties
其实就是一个键值对的配置文件
//1. 创建 Properties 对象,读取配置文件
Properties properties = new Properties();
//2. 加载指定配置文件
properties.load(new FileReader("src\\mysql.properties"));
//3. 把 k-v 显示控制台
properties.list(System.out);
//4. 根据 key 获取对应的值
String user = properties.getProperty("user");
String pwd = properties.getProperty("pwd");
System.out.println("用户名=" + user);
System.out.println("密码是=" + pwd);
网络通讯中IO流的应用
服务器端与客户端的数据传输:
这里就是用了包装流对于基本的输入输出流进行包装
//服务器端代码:接受并输出
//创建一个serverSocket对象,在本机的8888端口监听(serverSocket相当于一个服务)
ServerSocket serverSocket = new ServerSocket(8888);
//返回客户端连接的对象(找到socket)
Socket socket = serverSocket.accept();
//将客户端写入数据通道的数据接口,或者socket接口的输入流
InputStream ios = socket.getInputStream();
//将基础字节流转换为字符流(涉及到两个包装流)
BufferedReader bos = new BufferedReader(new InputStreamReader(ios));
//服务器端的处理逻辑
String s = bos.readLine();//直接来读取方法
String answer = "";
if("name".equals(s)){
answer = "我是本机";
}else if("hobby".equals(s)){
answer = "编写计算机程序";
}else{
answer = "我听不懂你说的话";
}
//5. 获取socket相关联的输出流(因为默认是字节传输的方式,所以需要努努力改成字符传输的方式)
OutputStream outputStream = socket.getOutputStream();
// 使用字符输出流的方式回复信息
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write(answer);
bufferedWriter.newLine();// 插入一个换行符,表示回复内容的结束
bufferedWriter.flush();//清空缓冲区数据,但是不关闭流
//关闭外层流
bos.close();
bufferedWriter.close();
//关闭网络服务
socket.close();
serverSocket.close();
//客户端代码
//连接到服务端的8888接口,产生socket对象
Socket socket = new Socket(InetAddress.getLocalHost(),8888);
OutputStream outputStream = socket.getOutputStream();
BufferedWriter bof = new BufferedWriter(new OutputStreamWriter(outputStream));//转化为字符流
//从键盘读取用户问题
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你的问题:");
String question = scanner.next();
bof.write(question);
bof.newLine();
bof.flush();//字符流必须得手动刷新一下才能写入数据通道(不然的话容易缓冲区堵塞)
//4. 获取和socket关联的输入流. 读取数据(字符),并显示
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();
System.out.println(s);
//关闭外层流和对象
bof.close();
bufferedReader.close();
socket.close();
System.out.println("客户端退出!");
标签:读取,Java,字节,filePath,--,Robyn,close,new,String
From: https://www.cnblogs.com/robyn2022/p/16728302.html