文章目录
- 二十七.I/O流
- 27.1概述
- 27.2 分类
- 27.3 字节输出流
- 27.3.1 数据写入本地文件
- 27.3.2 换行、续写
- 27.4字节输入流
- 27.4.1 读取数据到程序
- 27.4.2 循环读取
- 27.4.3 拷贝数据
- 27.4.4 一次读取多个
- 27.6 字符输入流
- 27.6.1 FileReader的使用
- 27.7 字符输出流
- 27.8. 缓冲流
- 27.8.1 字节缓冲流
- 27.8.1.1拷贝文件(一)
- 27.8.1.2 拷贝文件(二)
- 27.8.2字符缓冲流
- 27.8.2.1字符缓冲输入流
- 27.8.2.2 字符缓冲输出流
- 27.8.3 Test
- 27.9 转换流
- 27.9.1概述
- 27.9.2Test
- 27.9.2.2 test02
- 27.9.2.3 test03
- 27.9.2.4 test04
- 27.10 序列化流
- 27.11 反序列化流
二十七.I/O流
(遇见异常直接抛,默认采用alt+enter提示的第一种方式处理异常)
27.1概述
什么是I/O流:存储和读取数据的解决方案
作用:用于读写数据
27.2 分类
按照流向区分:
- 输入流 :把数据从
其他设备
上读取到内存
中的流。 - 输出流 :把数据从
内存
中写出到其他设备
上的流。
按照操作文件的类型分:
- 字节流:操作所有类型的文件,以字节为单位,读写数据的流。
- 字符流:只能操作纯文本文件,以字符为单位,读写数据的流。
用windows系统自带的记事本打开且能读懂的文件为纯本文文件,包括txt文件,md文件,xml文件,lrc文件,等等…
27.3 字节输出流
FileOutStream:字节输出流
27.3.1 数据写入本地文件
FileOutStream:可以把程序中的数据写到本地文件上,是字节流的基本流。
-
创建字节输出流对象
细节1:参数是字符串表示的路径或者是File对象都是可以的 细节2:如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的。 细节3:如果文件已经存在,则会清空文件.(如果文件已经存在内容,则会清空文件原有内容,然后写入的新内容)
-
写数据
write方法的参数是整数,但是实际上写到本地文件中的是整数在ASCII上对应的字符
-
释放资源
每次使用完流之后都要释放资源,解除占用
方法名 | 说明 |
---|---|
void write(int b) | 一次写一个字节数据 |
void write(byte[] b) | 一次写一个字节数组数据 |
void write(byte[] b, int off, int len) | 一次写一个字节数组的部分数 |
import java.io.FileOutputStream;
import java.io.IOException;public class Test01 {public static void main(String[] args) throws IOException {FileOutputStream fos = new FileOutputStream("code_java02\\kwh.txt");byte[] bytes = {97,98,99};fos.write(97);// afos.write(bytes);// a b c fos.write(bytes,0,2);// a bfos.close();}
}
27.3.2 换行、续写
import java.io.FileOutputStream;
import java.io.IOException;public class Test02 {public static void main(String[] args) throws IOException {//默认false:关闭续写,会清空文件// true:打开续写开关,不会清空文件FileOutputStream fos = new FileOutputStream("code_java02\\kwh.txt",true);String str = "nihao";// 将字符串编程字节数组byte[] bytes1 = str.getBytes();fos.write(bytes1);// 换行String str2 = "\r\n";byte[] bytes2 = str2.getBytes();fos.write(bytes2);String str3 = "tianqihenhao";byte[] bytes3 = str3.getBytes();fos.write(bytes3,0,bytes3.length);fos.close();}
}
27.4字节输入流
FileInputStream:字节输入流
27.4.1 读取数据到程序
操作本地的字节输入流,把本地文件的数据读取到程序中。
-
创建字节输入流对象
如果文件不存在,就直接报错。
-
读数据
一次读一个字节,读出来的是数据在ASCII上对应的数字
读到文件末尾处没有数据,read方法返回-1
-
释放资源
import java.io.FileInputStream;
import java.io.IOException;public class Test03 {public static void main(String[] args) throws IOException {// 创建字节输入流对象; kwh.txt里有abcFileInputStream fis = new FileInputStream("code_java02\\kwh.txt");// 读数据int read = fis.read();System.out.println(read);//97fis.close();}
}
27.4.2 循环读取
一次循环读取一个字节
import java.io.FileInputStream;
import java.io.IOException;public class Test04 {public static void main(String[] args) throws IOException {// 创建对象 kwh.txt里有abcFileInputStream fls = new FileInputStream("code_java02\\kwh.txt");// 定义变量,记录读取的数据int b ;// b =fls.read();// System.out.println(b);//97// 循环读取//read :表示读取数据,而且是读取一个数据就移动一次指针while ((b =fls.read()) != -1){System.out.print((char) b);}// 释放资源fls.close();}
}
27.4.3 拷贝数据
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;public class Test05 {public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream("E:\\software\\ideak\\ideapro\\kwhcode\\code_java02\\kkk.txt");FileOutputStream fos = new FileOutputStream("code_java02\\www.txt");// 定义变量,记录读取的数据int b;// 边读边写//一次读写一个字节while ((b= fis.read()) != -1){fos.write(b);}// 释放资源fis.close();fos.close();}
}
27.4.4 一次读取多个
方法 | 说明 |
---|---|
public in read() | 一次读取一个字节 |
public int read(byte[] buffer) | 一次读一个字节数组数据 |
import java.io.FileInputStream;
import java.io.IOException;public class Test06 {public static void main(String[] args) throws IOException {// kwh.txtl里有abcFileInputStream fis = new FileInputStream("code_java02\\kwh.txt");// 定义一个长度为2的字符数组,表示每次读取2个字节//将读到的数据再返回到数组bytes中byte[] bytes = new byte[2];//一次读取多个字节数据,具体读多少,跟数组的长度有关//返回值:本次读取到了多少个字节数据int len1 = fis.read(bytes);System.out.println(len1);//2//将bytes数组从0索引开始,一共把len1个字节变成字符串String str1 = new String(bytes,0,len1);System.out.println(str1);//abint len2 = fis.read(bytes);System.out.println(len2);// 1String str2 = new String(bytes,0,len2);System.out.println(str2);//c// int len3 = fis.read(bytes);// System.out.println(len3);//-1// String str3 = new String(bytes);// System.out.println(str3);//cbfis.close();}
}
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;public class Test07 {public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream("E:\\software\\ideak\\ideapro\\kwhcode\\code_java02\\hhh.txt");FileOutputStream fos = new FileOutputStream("code_java02\\hhh02.txt");byte[] bytes = new byte[1024 * 1024 * 5];// 定义要读取的数据的长度,即字节数int len;while ((len = fis.read(bytes)) != -1){// 都多少写多少fos.write(bytes,0 ,len);}//释放资源fos.close();fis.close();}
}
27.6 字符输入流
FileReader:字符输入流
使用场景:对纯文本文件进行读写操作。
字符流的底层就是字节流
字符流 = 字节流+字符集
特点:
- 输入流:一次读一个字节,遇到中文时,一次读多个字节。
- 输出流:底层会把数据按照指定的编码方式进行编码,变成字节再写到文件中。
27.6.1 FileReader的使用
-
创建字符输入流对象
构造方法 说明 public FileReader(File file) 创建字符输入流关联本地文件 public FileReader(String Path) 创建字符输入流关联本地文件 如果文件不存在,就直接报错。
-
读取数据
成员方法 说明 public int read() 读取数据,读到末尾返回-1 public int read(char[] buffer) 读取多个数据,读到末尾返回-1 细节1: 按照字节进行读取,遇到中文,一次读多个字节。读取后解 码。返回一个整数。
细节2: 读到文件末尾,read方法返回-1
-
释放资源
import java.io.FileReader;
import java.io.IOException;public class Test09 {public static void main(String[] args) throws IOException {// 创建字符输入流对象FileReader fr = new FileReader("code_java02\\a.txt");// 定义读取的字节数// // 记录读取的汉字解码后的十进制数int ch;//2.读取数据 read()//字符流的底层也是字节流,默认也是一个字节一个字节的读取的。//如果遇到中文就会一次读取多个,GBK一次读两个字节,UTF-8一次读三个字节//read()细节://1.read():默认也是一个字节一个字节的读取的,如果遇到中文就会一次读取多个//2.在读取之后,方法的底层还会进行解码并转成十进制。// 最终把这个十进制作为返回值// 这个十进制的数据也表示在字符集上的数字// 英文:文件里面二进制数据 0110 0001// read方法进行读取,解码并转成十进制97// 中文:文件里面的二进制数据 11100110 10110001 10001001// read方法进行读取,解码并转成十进制27721// 想看到中文汉字,就是把这些十进制数据,再进行强转就可以了// 循环读取while ((ch = fr.read()) != -1){// System.out.println(ch);十进制数//把解码出的十进制数强转成对应的字符System.out.print((char) ch);}// 释放资源fr.close();}
}
import java.io.FileReader;
import java.io.IOException;public class Test10 {public static void main(String[] args) throws IOException {FileReader fr = new FileReader("code_java02\\a.txt");// 记录读取的个数int len;// 一次读取两个,并把数据返回到chars数组里char[] chars = new char[2];//read(chars):读取数据,解码,强转三步合并了,把强转之后的字符放到数组当中//相当于空参的read + 强转类型转换while ((len = fr.read(chars)) != -1){// System.out.println(len);//2// 将读取的数据放到chars数组后变成字符串输出System.out.print(new String(chars));}fr.close();}
}
27.7 字符输出流
FileWriter:字节输出流
构造方法 | 说明 |
---|---|
public FileWriter(File file) | 创建字符输出流关联本地文件 |
public FileWriter(String pathname) | 创建字符输出流关联本地文件 |
public FileWriter(File file, boolean append) | 创建字符输出流关联本地文件,续写 |
public FileWriter(String pathname, boolean append) | 创建字符输出流关联本地文件,续写 |
成员方法 | 说明 |
---|---|
void write(int c) | 写出一个字符 |
void write(String str) | 写出一个字符串 |
void write(String str, int off, int len) | 写出一个字符串的一部分 |
void write(char[] cbuf) | 写出一个字符数组 |
void write(char[] cbuf, int off, int len) | 写出字符数组的一部分 |
import java.io.FileWriter;
import java.io.IOException;public class Test11 {public static void main(String[] args) throws IOException {FileWriter fw = new FileWriter("code_java02\\a.txt",true);//根据字符集进行编码,编码成三个字节写入文件fw.write(25105);fw.write("你好");char[] chars = {'今','天','好'};fw.write(chars);fw.write(chars,0,1);fw.write(chars,1,2);String str = "苹果葡萄";fw.write(str,0,2);fw.close();}
}
27.8. 缓冲流
高级流
27.8.1 字节缓冲流
原理:底层自带了长度为8192的缓冲区提高性能。
方法名称 | 说明 | |
---|---|---|
public BufferedInputStream(InputStream is) | 把基本流包装成高级流,提高数去数据性能 | |
public BufferedOutputStream(OutputStream os) | 把基本流包装成高级流,提高数去数据性能 | |
字节缓冲输入流的构造方法:
public BufferedInputStream(InputStream is)字节缓冲输出流的构造方法:
public BufferedOutputStream(OutputStream os)
27.8.1.1拷贝文件(一)
一次读写一个字节
import java.io.*;public class Test01 {public static void main(String[] args) throws IOException {//利用字节缓冲流拷贝文件//将a.txt里的内容写到aa.txt,aa.txt不存在BufferedInputStream bis = new BufferedInputStream(new FileInputStream("code_java02\\filedemo\\a.txt"));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("code_java02\\filedemo\\aa.txt"));// 记录读取的数据,一次读写一个字节int b;// 循环读取,读取的是缓冲区中数据,一次性读取8192个字节数据while ((b= bis.read()) != -1){// 将读取的数据再写入目的地bos.write(b);}// 关闭流bos.close();bis.close();}
}
27.8.1.2 拷贝文件(二)
一次读写多个字节
package bufferedstreamdemo;import java.io.*;public class Test02 {public static void main(String[] args) throws IOException {// 创建缓冲流对象BufferedInputStream bis = new BufferedInputStream(new FileInputStream("code_java02\\filedemo\\a.txt"));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("code_java02\\filedemo\\a2.txt"));// 定义数组,将读取的数据存入字节数组//一次读取多个字节byte[] bytes = new byte[1024];//记录读取的数据(字节)int len;// 循环将读取的字节数据写入字节数组while ((len = bis.read(bytes)) != -1){// 写入目的文件,一次写一个字节数组bos.write(bytes,0,len);}// 关闭流bos.close();bis.close();}
}
27.8.2字符缓冲流
构造方法
方法名称 | 说明 | |
---|---|---|
public BufferedReader(Reader r) | 把基本流变成高级流 | |
public BufferedWriter(Writer r) | 把基本流变成高级流 | |
27.8.2.1字符缓冲输入流
构造方法:public BufferedReader(Reader r)
特有方法:public String readLine() 读一整行
package bufferedstreamdemo;import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;public class Test03 {public static void main(String[] args) throws IOException {// 创建字符缓冲输入流对象BufferedReader br = new BufferedReader(new FileReader("code_java02\\filedemo\\a.txt"));String line;while ((line = br.readLine()) != null){System.out.println(line);}// 释放资源br.close();}
}
27.8.2.2 字符缓冲输出流
构造方法:public BufferedWriter(Writer r)
特有方法:public void newLine() 跨平台的换行
package bufferedstreamdemo;import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;public class Test04 {public static void main(String[] args) throws IOException {// 创建字符输出流对象//a3.txt 不存在则会直接创建FileWriter fw = new FileWriter("code_java02\\filedemo\\a3.txt",true);BufferedWriter bw = new BufferedWriter(fw);// 写入内容bw.write("数风流人物,还看今朝。");// 换行bw.newLine();bw.write("俱往矣");// 释放资源bw.close();}
}
27.8.3 Test
27.9 转换流
高级流
字符转换输入流:InputStreamReader
字符转换输出流:OutputStreamWriter
27.9.1概述
是字符流和字节流之间的桥梁。
将字节流转换成字符流就可以拥有字符流的特性,同时字节流可以使用字符流中的方法。
字符流特性,比如:
- 不会乱码
- 根据字符集一次读取多个数据
示意图:
27.9.2Test
27.9.2.1test01
利用转换流按照指定字符编码读取
package convertstream;import java.io.*;public class Test01 {public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream( "code_java02\\filedemo\\gbkfile.txt");// 创建转换流对象InputStreamReader isr = new InputStreamReader(fis,"GBK");int b;while ((b = isr.read()) != -1){System.out.print((char) b);}isr.close();}
}
27.9.2.2 test02
利用转换流按照指定字符编码写出
package convertstream;import java.io.*;public class Test03 {public static void main(String[] args) throws IOException {// gbkfile02.txt 不存在则创建FileOutputStream fos = new FileOutputStream("code_java02\\filedemo\\gbkfile02.txt",true);// 创建转换流对象OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK");osw.write("吃了么");osw.close();}
}
27.9.2.3 test03
将本地文件中的GBK文件,转成UTF-8
package convertstream;import java.io.*;public class Test04 {public static void main(String[] args) throws IOException {// gbkfile03.txt 不存在 则创建// 创建转换流读出FileInputStream fis = new FileInputStream("code_java02\\filedemo\\gbkfile.txt");InputStreamReader isr = new InputStreamReader(fis,"GBK");// 创建转换流写入FileOutputStream fos = new FileOutputStream("code_java02\\filedemo\\gbkfile03.txt");OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF-8");//一次读写一个字节// int b;// while ((b=isr.read()) != -1){// osw.write(b);// }//一次读写多个字节char[] chars = new char[2];int b;while ((b = isr.read(chars)) != -1){osw.write(chars);}osw.close();isr.close();}
}
27.9.2.4 test04
利用字节流读取文件中的数据,每次读一整行,而且不能出现乱码
package convertstream;import java.io.*;public class Test05 {public static void main(String[] args) throws IOException {/*利用字节流读取文件中的数据,每次读一整行,而且不能出现乱码1.字节流在读取中文的时候,是会出现乱码的,但是字符流可以搞定2.字节流里面是没有读一整行的方法的,只有字符缓冲流才能搞定*/// 创建字节流对象FileInputStream fis = new FileInputStream("code_java02\\filedemo\\a.txt");// 将字节流转换成字符流InputStreamReader isr = new InputStreamReader(fis);// 将字符流包装成字符缓冲流BufferedReader br = new BufferedReader(isr);String line;while ((line = br.readLine()) != null){System.out.println(line);}// 释放资源br.close();}
}
27.10 序列化流
也叫 对象操作输出流
可以把Java中的对象写到本地文件中
高级流,也是用来包装基本流的
构造方法:public ObjectOutputStream(OutputStream out) 把基本流变成高级流成员方法:public final void writeObject(Object obj) 把对象序列化(写出)到文件中去
//Student的标准JavaBean类
// Student实现Serializable接口
//Serializable接口里面是没有抽象方法,标记型接口一旦实现了这个接口,那 么就表示当前的Student类可以被序列化
//属性:学生姓名,学生年龄
=================================================//测试类
package objectstream.test01;import java.io.*;public class StudentTest {public static void main(String[] args) throws IOException {// 创建学生对象Student stu1 = new Student("小明",18);// 创建序列化流的对象ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("code_java02\\filedemo\\objfile.txt"));// 写出数据oos.writeObject(stu1);// 释放资源oos.close();}
}
27.11 反序列化流
也叫对象操作输入流,把序列化到本地文件中的对象读取到程序中。
构造方法:public ObjectInputStream(InputStream out) 把基本流变成高级流
成员方法:public Object readObject() 把序列化到本地文件中的对象,读取到程序中来
//同27.10中的JavaBean类
=================================================
package objectstream.test01;import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;public class StudentTest02 {public static void main(String[] args) throws IOException, ClassNotFoundException {// 创建反序列流对象ObjectInputStream ois = new ObjectInputStream(new FileInputStream("code_java02\\filedemo\\objfile.txt"));// 读出数据// Object o = ois.readObject();//想看到真正的对象需要强转Student stu = (Student) ois.readObject();// 打印对象System.out.println(o);// 释放资源ois.close();}
}
化到本地文件中的对象读取到程序中。
构造方法:public ObjectInputStream(InputStream out) 把基本流变成高级流
成员方法:public Object readObject() 把序列化到本地文件中的对象,读取到程序中来
//同27.10中的JavaBean类
=================================================
package objectstream.test01;import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;public class StudentTest02 {public static void main(String[] args) throws IOException, ClassNotFoundException {// 创建反序列流对象ObjectInputStream ois = new ObjectInputStream(new FileInputStream("code_java02\\filedemo\\objfile.txt"));// 读出数据// Object o = ois.readObject();//想看到真正的对象需要强转Student stu = (Student) ois.readObject();// 打印对象System.out.println(o);// 释放资源ois.close();}
}