IO流也称为输入、输出流,就是用来读写数据的。
一.概述:
1.IO流的作用?
读写文件数据的
2.IO流是怎么划分的,大体分为几类,各自的作用?
- 字节流:字节输入流,字节输出流(读写字节数数据的)
- 字符流:字符输入流,字符输出流(读写字符数据的)
3.意义
- I表示intput,是数据从硬盘文件读入到内存的过程,称之输入,负责读。
- O表示output,是内存程序的数据从内存到写出到硬盘文件的过程,称之输出,负责写。
二.分类
1.按流的方向分:
输入流,输出流;
2.按流中的最小单位分:
字节流:操控所以类型的文件;
字符流:只能操控重文本文件;
3.总结流的四大类: ? ? ? ? ?字节流? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 字节输入流 ? ? ? ? ? ?字节输出流 ? ? ? ? ? ? ? ? ? ? ? InputStream ? ? ? ? ?OutputStream ? ? ? ? ? ? ? ? ? FileInputStream ? ? ?FileOutputStream ? ?
?字符流?
字符输入流 ? ? ? ?字符输出流
Reader ? ? ? ? ? Writer ?(抽象类)
FileReader ? ? ? FileWriter(实现类,可以使用的)
? ? 文件字节输入流:FileInputStream(负责读取数据)
? ? ? ? -- 作用:以内存为基准,把磁盘文件中的数据以字节的形式读取到内存中去。
? ? ? ? ? ? ? ? 按照字节读文件数据到内存中。
? ? ? ? -- 构造器:
? ? ? ? ? ? public FileInputStream(File file):创建字节输入流管道与源文件对象接通
? ? ? ? ? ? public FileInputStream(String pathname):创建字节输入流管道与源文件路径接通。
? ? ? ? -- 方法:
? ? ? ? ? ? public int read(): 每次读取一个字节返回,读取完毕返回-1。
? ? 小结: ? ? ? ? 一个一个字节读取中文数据输出其实是被淘汰的,性能极差! ? ? ? ? ?一个一个字节读取中文数据输出,会出现截断中文字节的情况,无法避免读取中文输出乱码的问题。
public static void main(String[] args) throws Exception {
// 1、创建一个文件字节输入流管道与源文件接通。
// InputStream is = new FileInputStream(new File("file-io-app\\src\\data.txt"));
// 简化写法
InputStream is = new FileInputStream("file-io-app\\src\\data.txt");
// 2、读取一个字节返回 (每次读取一滴水)
// int b1 = is.read();
// System.out.println((char)b1);
//
// int b2 = is.read();
// System.out.println((char)b2);
//
// int b3 = is.read();
// System.out.println((char)b3);
//
// int b4 = is.read(); // 读取完毕返回-1
// System.out.println(b4);
// 3、使用循环改进
// 定义一个变量记录每次读取的字节 a b 3 爱
// o o o [ooo]
int b;
while (( b = is.read() ) != -1){
System.out.print((char) b);
}
}
文件字节输出流: ?FileOutputStream(可以直接创建文件,并存数据)
?-- 作用:以内存为基准,把内存中的数据,按照字节的形式写出到磁盘文件中去。 ? ? ? ? ? ? ? ? ?简单来说,把内存数据按照字节写出到磁盘文件中去。 ? ? ? ? -- 构造器: ? ? ? ? ? ? public FileOutputStream(File file):创建一个字节输出流管道通向目标文件对象。 ? ? ? ? ? ? public FileOutputStream(String file):创建一个字节输出流管道通向目标文件路径。 ? ? ? ? ? ? public FileOutputStream(File file , boolean append):创建一个追加数据的字节输出流管道通向目标文件对象。 ? ? ? ? ? ? public FileOutputStream(String file , boolean append):创建一个追加数据的字节输出流管道通向目标文件路径。 ? ? ? ? -- 方法: ? ? ? ? ? ?public void write(int a):写一个字节出去 。 ? ? ? ? ? ?public void write(byte[] buffer):写一个字节数组出去。 ? ? ? ? ? ?public void write(byte[] buffer , int pos , int len):写一个字节数组的一部分出去。 ? ? ? ? ? ? ? ? ? ? ? ? ? ?参数一,字节数组;参数二:起始字节索引位置,参数三:写多少个字节数出去。 ? ? 小结: ? ? ? ? 换行: ?os.write("\r\n".getBytes()); // 换行 ? ? ? ? 追加数据管道: OutputStream os = new FileOutputStream("day10_demo/out01.txt" , true); // 追加管道!!
public static void main(String[] args) throws Exception {
// 1、创建一个文件字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream("file-io-app/src/out04.txt" , true); // 追加数据管道
// OutputStream os = new FileOutputStream("file-io-app/src/out04.txt"); // 先清空之前的数据,写新数据进入
// 2、写数据出去
// a.public void write(int a):写一个字节出去
os.write('a');
os.write(98);
os.write("\r\n".getBytes()); // 换行
// os.write('徐'); // [ooo]
// b.public void write(byte[] buffer):写一个字节数组出去。
byte[] buffer = {'a' , 97, 98, 99};
os.write(buffer);
os.write("\r\n".getBytes()); // 换行
byte[] buffer2 = "我是中国人".getBytes();
// byte[] buffer2 = "我是中国人".getBytes("GBK");
os.write(buffer2);
os.write("\r\n".getBytes()); // 换行
// c. public void write(byte[] buffer , int pos , int len):写一个字节数组的一部分出去。
byte[] buffer3 = {'a',97, 98, 99};
os.write(buffer3, 0 , 3);
os.write("\r\n".getBytes()); // 换行
// os.flush(); // 写数据必须,刷新数据 可以继续使用流
os.close(); // 释放资源,包含了刷新的!关闭后流不可以使用了
}
文件字符输入流:FileReader ? ? ? ? ?-- 作用:以内存为基准,把磁盘文件的数据以字符的形式读入到内存。 ? ? ? ? ? ? 简单来说,读取文本文件内容到内存中去。
? ? ? ? ?-- 构造器: ? ? ? ? ? ? public FileReader(File file):创建一个字符输入流与源文件对象接通。 ? ? ? ? ? ? public FileReader(String filePath):创建一个字符输入流与源文件路径接通。
? ? ? ? ?-- 方法: ? ? ? ? ? ? public int read(): 读取一个字符的编号返回! 读取完毕返回-1 ? ? ? ? ? ? public int read(char[] buffer):读取一个字符数组,读取多少个字符就返回多少个数量,读取完毕返回-1 ? ? ?小结: ? ? ? ? 字符流一个一个字符的读取文本内容输出,可以解决中文读取输出乱码的问题。 ? ? ? ? 字符流很适合操作文本文件内容。 ? ? ? ? 但是:一个一个字符的读取文本内容性能较差!!
public static void main(String[] args) throws Exception {
// 目标:每次读取一个字符。
// 1、创建一个字符输入流管道与源文件接通
Reader fr = new FileReader("file-io-app\\src\\data06.txt");
// 2、读取一个字符返回,没有可读的字符了返回-1
// int code = fr.read();
// System.out.print((char)code);
//
// int code1 = fr.read();
// System.out.print((char)code1);
// 3、使用循环读取字符
int code;
while ((code = fr.read()) != -1){
System.out.print((char) code);
}
}
文件字符输出流的使用:FileWriter ? ? ? ? -- 作用:以内存为基准,把内存中的数据按照字符的形式写出到磁盘文件中去。 ? ? ? ? ? ? 简单来说,就是把内存的数据以字符写出到文件中去。 ? ? ? ? -- 构造器: ? ? ? ? ? ?public FileWriter(File file):创建一个字符输出流管道通向目标文件对象。 ? ? ? ? ? ?public FileWriter(String filePath):创建一个字符输出流管道通向目标文件路径。 ? ? ? ? ? ?public FileWriter(File file,boolean append):创建一个追加数据的字符输出流管道通向目标文件对象。 ? ? ? ? ? ?public FileWriter(String filePath,boolean append):创建一个追加数据的字符输出流管道通向目标文件路径。 ? ? ? ? -- 方法: ? ? ? ? ? ? ?a.public void write(int c):写一个字符出去 ? ? ? ? ? ? ?b.public void write(String c)写一个字符串出去: ? ? ? ? ? ? ?c.public void write(char[] buffer):写一个字符数组出去 ? ? ? ? ? ? ?d.public void write(String c ,int pos ,int len):写字符串的一部分出去 ? ? ? ? ? ? ?e.public void write(char[] buffer ,int pos ,int len):写字符数组的一部分出去 ? ? ?小结: ? ? ? ? 字符输出流可以写字符数据出去,总共有5个方法写字符。 ? ? ? ? 覆盖管道: ? ? ? ? ? ? ? Writer fw = new FileWriter("Day10Demo/src/dlei03.txt"); // 覆盖数据管道 ? ? ? ? 追加数据管道: ? ? ? ? ? ? ? Writer fw = new FileWriter("Day10Demo/src/dlei03.txt",true); // 追加数据管道 ? ? ? ? 换行: ? ? ? ? ? ? ?fw.write("\r\n"); // 换行 ? ? ? ? 结论:读写字符文件数据建议使用字符流。复制文件建议使用字节流。
public static void main(String[] args) throws Exception {
// 1、创建一个字符输出流管道与目标文件接通
// Writer fw = new FileWriter("file-io-app/src/out08.txt"); // 覆盖管道,每次启动都会清空文件之前的数据
Writer fw = new FileWriter("file-io-app/src/out08.txt", true); // 覆盖管道,每次启动都会清空文件之前的数据
// a.public void write(int c):写一个字符出去
fw.write(98);
fw.write('a');
fw.write('徐'); // 不会出问题了
fw.write("\r\n"); // 换行
// b.public void write(String c)写一个字符串出去
fw.write("abc我是中国人");
fw.write("\r\n"); // 换行
// c.public void write(char[] buffer):写一个字符数组出去
char[] chars = "abc我是中国人".toCharArray();
fw.write(chars);
fw.write("\r\n"); // 换行
// d.public void write(String c ,int pos ,int len):写字符串的一部分出去
fw.write("abc我是中国人", 0, 5);
fw.write("\r\n"); // 换行
// e.public void write(char[] buffer ,int pos ,int len):写字符数组的一部分出去
fw.write(chars, 3, 5);
fw.write("\r\n"); // 换行
// fw.flush();// 刷新后流可以继续使用
fw.close(); // 关闭包含刷线,关闭后流不能使用
}
三.编码和解码
我们正常写一个字节流输出“abc”还好,但是我们输出我们中国的文化瑰宝,汉字的时候为何会变成不知名的字符:
String s="中国";
byte[] by=s.getBytes(StandardCharsets.UTF_8);
byte[] by1=s.getBytes("GBK");
System.out.println(Arrays.toString(by));
System.out.println(Arrays.toString(by1));
?这个时候我们就需要到了编码和解码
GBXXX字符集:
Unicode字符集:?
?我们通常使用的是GBK和UTF-8;
第一种:直接型
????????编码
????????●byte[] getBytes0:使用平台的默认字符集将该String编码为-系列字节, 将结果存储到新的字节数组中
????????●byte[] getBytes(String charsetName):使用指定的字符集将该String编码为-系列字节,将结果存储到新的字节数组中
????????解码
????????●String(byte[] bytes):通过使用平台的默认字符集解码指定的字节数组来构造新的String
?????????●String(bytel[] bytes, String charsetName):通过指定的字符集解码指定的字节数组来构造新的String
?第二种:字符流
?????????字符输入转换流InputStreamReader
???????? ?-- 作用:可以解决字符流读取不同编码乱码的问题。 ? ? ? ? ? ? ? ? ? 也可以把原始的字节流按照指定编码转换成字符输入流
? ? ? ? ? -- 构造器: ? ? ? ? ? ? ? ? public InputStreamReader(InputStream is):可以使用当前代码默认编码转换成字符流,几乎不用! ? ? ? ? ? ? ? ? public InputStreamReader(InputStream is,String charset):可以指定编码把字节流转换成字符流(核心)
? ? ? ? ? 小结: ? ? ? ? 字符输入转换流InputStreamReader:作用:可以解决字符流读取不同编码乱码的问题。 ? ? ? ? public InputStreamReader(InputStream is,String charset):可以指定编码把字节流转换成字符流(核心)
????????? 字符输出转换流:OutputStreamWriter
? ? ? ? ? ?-- 作用:可以指定编码把字节输出流转换成字符输出流。 ? ? ? ? ? ? ? ? ? ?可以指定写出去的字符的编码。 ? ? ? ? ? ?-- 构造器: ? ? ? ? ? ? ? ? public OutputStreamWriter(OutputStream os) : ? 用当前默认编码UTF-8把字节输出流转换成字符输出流 ? ? ? ? ? ? ? ? public OutputStreamWriter(OutputStream os , String charset):指定编码把字节输出流转换成字符输出流 ? ? ? ? ? ?小结: ? ? ? ? ? 字符输出转换流OutputStreamWriter可以指定编码把字节输出流转换成字符输出流。 ? ? ? ? ? 从而实现指定写出去的字符编码!
四.缓冲流
1.概述
?????????缓冲流也称为高效流、或者高级流。之前学习的字节流可以称为原始流。
????????作用:缓冲流自带缓冲区、可以提高原始字节流、字符流读写数据的性能
?
?2.缓冲流的作用:
?????????缓冲流自带缓冲区、可以提高原始字节流、字符流读写数据的性能
?3.缓冲流种类:
????????字节缓冲流 字节缓冲输入流: BufferedInputStream ?
????????字节缓冲输出流:BufferedOutputStream
????????字符缓冲流 字符缓冲输入流:BufferedReader
????????字符缓冲输出流:BufferedWriter
4.字节缓冲流:
(1).字节缓冲流性能优化原理:
????????字节缓冲输入流自带了8KB缓冲池,以后我们直接从缓冲池读取数据,所以性能较好。
????????字节缓冲输出流自带了8KB缓冲池,数据就直接写入到缓冲池中去,写数据性能极高了。
(2).缓冲输入,输出流
?????????字节缓冲输入流:BufferedInputStream,提高字节输入流读取数据的性能,读写功能上并无变化。 ?
????????字节缓冲输出流:BufferedOutputStream,提高字节输出流读取数据的性能,读写功能上并无变化。
构造器 | 说明 | public?BufferedInputStream ?(InputStream?is) | 可以把低级的字节输入流包装成一个高级的缓冲字节输入流管道, 从而提高字节输入流读数据的性能 | public?BufferedOutputStream?(OutputStream?os) | 可以把低级的字节输出流包装成一个高级的缓冲字节输出流, 从而提高写数据的性能 |
5.字符缓冲输入流
(1)字符缓冲输入流:BufferedReader。
???????? 作用:提高字符输入流读取数据的性能,除此之外多了按照行读取数据的功能。?
构造器 | 说明 | public?BufferedReader?(Reader?r) | 可以把低级的字符输入流包装成一个高级的缓冲字符输入流管道, 从而提高字符输入流读数据的性能 |
字符缓冲输入流新增功能:?
方法 | 说明 | public?String?readLine() | 读取一行数据返回,如果读取没有完毕,无行可读返回null |
(2)字符缓冲流算解答:
字符缓冲流为什么提高了操作数据的性能?
????????字符缓冲流自带8K缓冲区 可以提高原始字符流读写数据的性能
字符缓冲流的功能如何使用?
???????? public BufferedReader?(Reader r) 性能提升了,多了readLine()按照行读取的功能(一次读取一行数据)
???????? public BufferedWriter?(Writer w) 性能提升了,多了newLine()换行的功能?
????????
|