IO流
什么是IO流?
IO流也称为输入、输出流,就是用来读写数据的。
-
I:表示input,是数据从硬盘读入到内存中的过程,称为输入,负责读
-
O:表示output,是内存程序的数据从内存到硬盘的过程,称之为输出,负责写。
I: 硬盘→→内存(读入) O:内存→→硬盘(读出)
IO流的分类
方向分 输入流 输出流
按数据最小单位分 字节流 字符流
字节流 更适合 读写 —— 音视频文件
字符流 更适合读写 —— 文本内容
IO流的体系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X6bu5Fvi-1677152619915)(D:\JAVA笔记(第一遍)\assets\1673509259137.png)]
字节输入流 —FileInputStream
一、单字节读取
1、创建一个文件字节输入流管道,与源文件连通
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZeLOFGvO-1677152619916)(D:\JAVA笔记(第一遍)\assets\1673510319527.png)]
// 创建一个文件字节输入流管道 ,与源文件连接
InputStream is = new FileInputStream("file-io-app\\src\\date");
2、读取一个字节并返回
// 读取一个字节返回
int b1 = is.read();
System.out.println((char) b1);
int b2 = is.read(); // 长度
System.out.println((char) b2);
3、使用循环读取所有字节
// 循环不能读取中文字符,会乱码,因为每次只读取一个字节,中文字符在UTF-8中占三个字节
int n ;
while ((n = is.read())!=-1){
System.out.println(n);
}
没有字节可读,则返回-1
public int read(); // 每次读取一个字节,如果字节没有则返回 -1
单字节读取弊端:
- 性能较慢
- 读取中文出现乱码现象
二、数组字节读取
1、创建一个文件字节输入流管道,与源文件连通
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c7ANUazX-1677152619916)(D:\JAVA笔记(第一遍)\assets\1673513652772.png)]
// 创建一个文件字节输入流管道 ,与源文件连接
InputStream is = new FileInputStream("file-io-app\\src\\date");
2、定义一个数组,用于读取字节
// 定义一个数组,用于读取字节数组
byte[] buffer = new byte[3];
int len = is.read(buffer); //每次读取的字节个数
System.out.println(len);
// 解码
String rs = new String(buffer);
System.out.println(rs);
3、使用循环读取所有字节
int len; // 记录每次读取的字节数
// 相当于一个长度为3的容器 是 byte 类型的
byte[] buffer = new byte[3];
while ((len = is.read(buffer)) != -1) {
// 读取多少倒出多少 String sc = new String (byte[] , 开始位置 , 结束位置 );
System.out.println(new String(buffer,0,len));
}
总结 :
①磁盘跟内存连同
②创造一个有容器
③每次从内存中装入设定容器大小的数据
④解码输出
三、定义数组与文件相同
自定义总结:
定义一个数组,大小和文件大小一致,这样就不会出现乱码情况
①先拿到文件大小
File f = new File("file-io-app\\src\\date2");
System.out.println(f.length());
②创建流通管道
InputStream is = new FileInputStream(f);
③创建一个跟文件大小一样的数组
byte[] buffer = new byte[(int) f.length()];
④ 解码并输出
String rs = new String(buffer);
System.out.println(rs);
官方API
// 读取所有字节
byte[] bytes = is.readAllBytes();
// 解码
String sc = new String(bytes);
System.out.println(sc);
字节输出流—FileOutputStream
一、基本写法
创建字节文件输出管道,与目标文件连通
OutputStream os = new FileOutputStream( "file-io-app/src/out04.txt",true);
//true 代表append,不加直接覆盖重新写,加上代表接着写
1、单个字节写进去
os.write(98);
os.write(97);
os.write(99);
os.write(100);
2、数组写进去
byte[] bytes = {102,103};
os.write(bytes);
3、中文写进去
// 中文可以解码写进去
String name = "我和你子啊一起";
byte[] bytes1 = name.getBytes();
os.write(bytes1);
4、可以写一部分进去
byte[] bytes3 = {102,103,97,98,99};
os.write(bytes,0,3);
二、自我总结
①换行
os.write("\r\n".getBytes());
②写完必须刷新
os.flush();
③用完流要关闭
os.close();
④关闭可以自动刷新
拷贝文件
一、自己思路
①创建一个输入流管道,负责读取源文件的数据
InputStream is = new FileInputStream("D:\\JAVA\\文件名.mp4");
②创建一个输出流管道,负责写入目标文件的数据
OutputStream os = new FileOutputStream("D:\\JAVA\\newMov.mp4");
③定义一个数组,负责转移数据(中转站)
byte[] buffer = new byte[1024];
int len;// 记录每次读取的字节数,用于最后装不满,导致数据错误
④开是运转,读数据→放数组中→写到目的地 (读→中转→写)
// 4、 从源文件中读取数据,并装入数组中
while ((len = is.read(buffer)) != -1) {//
// 5、数组中的数据写入到目标文件中
os.write(buffer, 0, len);
}
⑤最后,先关闭输出流 ,再关闭输入流
os.close();
is.close();
二、整体代码
package com.maoteng.d4_byte_stream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class CopyDemo5 {
public static void main(String[] args) throws Exception {
// 1、 创建一个字节输入流管道与源文件连通
InputStream is = new FileInputStream("D:\\JAVA\\17、总结:数据类型、运算符.mp4");
// 2、创建一个字节输出流管道与目标文件连通
OutputStream os = new FileOutputStream("D:\\JAVA\\newMov.mp4");
// 3、定义一个数组,负责转移(中转站)
byte[] buffer = new byte[1024];
int len;// 记录每次读取的字节数,用于最后装不满,导致数据错误
// 4、 从源文件中读取数据,并装入数组中
while ((len = is.read(buffer)) != -1) {
// 5、数组中的数据写入到目标文件中
os.write(buffer, 0, len);
}
System.out.println("复制完成");
os.close();
is.close();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cT3PMrow-1677152619917)(D:\JAVA笔记(第一遍)\assets\1673518651351.png)]
三、易错点
单字节读取,int b1 接收的是字节
int b1 = is.read();
System.out.println(b1);
数组读取 , int len 接收的是字节数
byte[] buffer = new byte[1024];
int len;// 记录每次读取的字节数,用于最后装不满,导致数据错误
资源释放
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6FddiyH2-1677152619917)(D:\JAVA笔记(第一遍)\assets\1673576654158.png)]
一、手动释放
1、格式
try {
// 易错代码体
} catch (Exception e) {
// 打印错误信息
e.printStackTrace();
} finally {
// 肯定回执行的代码体,一般是释放资源
// 实现(implements) closeable接口的是资源
public abstract class OutputStream implements Closeable {
}
}
二、自动释放资源①
1、格式
// 资源文件 实现(implements) closeable接口的是资源
try (资源文件,用完自动释放) {
// 易错代码体
} catch (Exception e) {
// 打印错误信息
e.printStackTrace();
}
二、自动释放资源②
1、格式
public static void main(String[] args) throws Exception {
InputStream is = new FileInputStream("地址");// 资源文件
OutputStream os = new FileOutputStream("地址");// 资源文件
try (is; os) {
// 易错代码体
// 可以直接使用 is os
} catch (Exception e) {
e.printStackTrace();
}
}
自动释放②缺点 :异常信息必须要抛出,不能try catch ,否则下面又访问不了。
字符流
一、字符输入流
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6Qq92vsl-1677152619917)(D:\JAVA笔记(第一遍)\assets\1673578946656.png)]
1、单字节读取
1、创建一个字符输入管道,与源文件对象连通
Reader reader = new FileReader("file-io-app\\src\\out04.txt");
2、读取字符
int read = reader.read();
3、转成字符形式展现
System.out.println((char) read);
4、用循环展现全部
int len;
while ((len = reader.read())!=-1){
System.out.print((char) len);
}
整体代码
package com.maoteng.d6_char_stream;
import java.io.FileReader;
import java.io.Reader;
public class CharStream01 {
/*
* 读取一个字符
*/
public static void main(String[] args) {
// 1、 创建一个字符输入管道,与源文件对象连通
try {
Reader reader = new FileReader("file-io-app\\src\\out04.txt");
// 2、读取字符
int read = reader.read();
// 3、转成字符形式展现
System.out.println((char) read);
// 4 用循环读取全部
int len;
while ((len = reader.read())!=-1){
System.out.print((char) len);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
2、数组读取
1、创建一个字符输入管道,与源文件对象连通
Reader reader = new FileReader("file-io-app\\src\\out04.txt");
2、定义一个数组,用于存放数据
char[] buffer = new char[1024];
3、定义一个变量,记录每次读取的个数
int len;
4、利用循环,开始读取数据,并放入数组中
while ((len = reader.read(buffer))!=-1){
// 5 进行解码
String rs = new String(buffer,0,len);
System.out.print(rs);
}
整体代码
package com.maoteng.d6_char_stream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.Reader;
import java.util.Date;
public class CharStream02 {
/*
* 数组读取字符
*/
public static void main(String[] args) {
try {
Date date = new Date();
System.out.println(date.getTime());
// 1、 创建一个字符输入管道,与源文件对象连通
Reader reader = new FileReader("file-io-app\\src\\out04.txt");
// 2 定义一个数组用于存放接收的数据
char[] buffer = new char[1024];
// 3 定义一个长度,记录每次读取的个数
int len;
// 4 利用循环开始读取数据 读到的数据放在 buffer里面
while ((len = reader.read(buffer))!=-1){
// 5 进行解码
String rs = new String(buffer,0,len);
System.out.print(rs);
}
Date date1 = new Date();
System.out.println(date1.getTime());
} catch (Exception e) {
e.printStackTrace();
}
}
}
二、字符输出流
1、创建一个字符输出流,与目标文件连通
Writer fw = new FileWriter("file-io-app/src/date5.txt",true);
2、写一个字符
fw.write('a');
fw.write('1');
fw.write("\r\n");
fw.write('我');
3、写一个字符串
fw.write("我和你子啊一起");
4、写一个字符数组
char[] chars = {'a','b','c'};
5、写字符串的一部分
fw.write("我爱你憨憨",0,3);
6、字符数组的一部分
fw.write(chars,0,2);
7、刷新关闭流
// 刷新流
fw.flush();
// 关闭流
fw.close();
整体代码
package com.maoteng.d6_char_stream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class CharStream03 {
// 文件字符输出流,写数据方法
public static void main(String[] args) {
// 创建一个字符输出流,与目标文件连通
try {
Writer fw = new FileWriter("file-io-app/src/date5.txt",true);
// 写一个字符
fw.write('a');
fw.write('1');
fw.write("\r\n");
fw.write('我');
// 写一个字符串
fw.write("我和你子啊一起");
// 写一个字符数组
char[] chars = {'a','b','c'};
fw.write(chars);
fw.write("\r\n");
// 写一个字符串的一部分
fw.write("我爱你憨憨",0,3);
// 写一个字符数组的一部分
fw.write(chars,0,2);
fw.write("\r\n");
// 刷新流
fw.flush();
// 关闭流
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
个人总结
字节流
① 更适合一切文件数据的拷贝——音视频、文本
② 字节流不适合中文内容的输出,容易出现乱码现象
字符流
① 更适合做文本文件的操作(读 、写)
fw.write("我和你子啊一起");
// 写一个字符数组
char[] chars = {‘a’,‘b’,‘c’};
fw.write(chars);
fw.write(“\r\n”);
// 写一个字符串的一部分
fw.write(“我爱你憨憨”,0,3);
// 写一个字符数组的一部分
fw.write(chars,0,2);
fw.write(“\r\n”);
// 刷新流
fw.flush();
// 关闭流
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
#### 个人总结
字节流
① 更适合一切文件数据的拷贝——音视频、文本
② 字节流不适合中文内容的输出,容易出现乱码现象
字符流
① 更适合做文本文件的操作(读 、写)