目录
IO流
一、IO流概述
1、IO:指输入输出
Input:输入,从外界到程序,读取数据(将文件中的内容通过程序呈现给我们)
Output:输出,从程序到外界,写出数据(将程序的内容写进文件)
2.流的分类
- 2.1 字节流和字符流
- ①字节流:传输数据的最小单位时字节(以字节byte进行读写)
- ②字符流:传输数据的最小单位时字符(以字符char进行读写)
- 速记:以 Stream 结尾的都是字节流,以 Reader 和 Writer 结尾的都是字符流
- 2.2 节点流和处理流
- ①节点流(低级流):可以向一个特点的地方读写数据
- ②处理流(高级流或过滤流):封装了节点流,通过封装的流的功能调用实现数据读写
- PS:高级流是以低级流为载体的--->高级流对象传的参数是低级流对象
二、常用IO流
1.FIS和FOS
FIS: FileInputStream,文件输入流
①FileInputStream(File file)
通过打开一个到实际文件的连接来创建一个FileInputStream,该文件通过文件系统中的 File对象file指定。
②FileInputStream(String name)
通过打开一个到实际文件的连接来创建一个FileInputStream,该文件通过文件系统中的路径 名name指定。
FOS:FileOutputStream, 文件输出流
①FileOutputStream(File file)
创建一个向指定File对象表示的文件中写入数据的文件输出流。
②FileOutputStream(File file, boolean append)
创建一个向指定File对象表示的文件中写入数据的文件输出流。
③FileOutputStream(String name)
创建一个向具有指定名称的文件中写入数据的输出文件流。
④FileOutputStream(String name, boolean append)
创建一个向具有指定name的文件中写入数据的输出文件流。
write():把括号内的东西写入文件
read():把内容写进括号内的载体
//1.创建File对象
File file=new File("demo\\fosfis.txt");
//2.创建文件输出流
FileOutputStream fos = new FileOutputStream(file);
//3.写出一组字节(把 HelloWorld 写入demo.txt文件)
fos.write("HelloWorld".getBytes());
fos.close();//关闭流,释放资源
//读取数据到控制台(从文件获取数据展示到控制台)
//4.创建文件输入流
FileInputStream fis = new FileInputStream(file);
//read()方法返回值是int型,为字符的ASCII码,当读取到文件末尾时,返回值为-1
int i = -1;
byte[] bus = new byte[1024];//创建数接收数据
//read()方法中,自带有循环,所以不需要再写循环也可完成全部读取
if ((i = fis.read(bus)) != -1){
System.out.println(new String(bus));//以字符串形式输出
}
fis.close();
2.BIS和BOS
缓冲流
①内部定义了一个缓冲区
②优势:减少读写次数
③示意图:输入输出的内容先写入缓冲区,待缓冲区满了之后会自动进行读写,或者手动刷 新/清空即flush()缓冲区。一般地,缓冲区默认初始大小是很大的,所以 正常情况下都是手动 清空缓冲区。
④close()的底层其实就是flush(),所以close()也能起到清空缓冲区的作用
BIS:BufferedInputStream 缓冲输入流
①BufferedInputStream(InputStream in)
创建 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。
②BufferedInputStream(InputStream in, int size)
创建具有指定缓冲区大小的 BufferedInputStream,并保存其参数,即输入流 in,以便将来使用。
BOS:BufferedOutputStream 缓冲输出流
①BufferedOutputStream(OutputStream out)
创建一个新的缓冲输出流,以将数据写入指定的基础输出流。
②BufferedOutputStream(OutputStream out, int size)
创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的基础输出流。
/1.创建File对象
File file=new File("demo\\bosbis.txt");
//2.创建缓冲输出流
BufferedOutputStream bos = new BufferedOuputStream(new FileOutputStream(file));//流的链接
//3.写出一组字节(把 HelloWorld 写入缓冲区)
bos.write("HelloWorld".getBytes());
bos.close();//关闭流,释放资源,亦即清空缓冲区,此时才把内容真正写入文件
//读取数据到控制台(从文件获取数据展示到控制台)
//4.创建缓冲输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
int i = -1;
//读单个,一个个的读取
//while ((i = bis.read()) != -1){
// System.out.println((char) i);
//}
//读byte[],以数组为单位读取
byte[] bus = new byte[1024];
if ((i = bis.read(bus)) != -1) {
System.out.println(new String(bus));
}
3.OIS和OOS
序列化与反序列化
①概述
序列化:对象转化为字节序列
反序列化:字节序列转化为对象
②目的:能将对象保存在磁盘(或外部存储设备)中
③实现方法
必须实现Serializable接口,该接口无任何方法需要实现,只是可以序列化和反序列化的标志
序列化:writeObject(Object object)
反序列化:readObject()
④反序列化时两种存在的问题
- 序列化后改变文件内容:运行后会抛出异常 StreamCorruptedException,即使改回来也会报错
- 序列化后改变对象属性名称,会抛出异常InvalidClassException
1.改回来即可
2.添加序列化接口版本号,可解决兼容性问题,在反序列化时如果改变对象的属性名,程序不会报错,但是被改变的属性反序列化后没有值了
private static final long serialVersionUID = 1009021700170338002L;
//每台设备的版本号是不一样的
⑤对象的瘦身
transient关键字:专门针对对象的瘦身,表示不需要序列化的对象可以省略属性的序列化,减少字节序列的生成
public class TestOOSAndOIS {
File file;
ObjectOutputStream oos;
ObjectInputStream ois;
@Before
public void getFile()throws Exception{
file = new File("E:\\Shixun\\huaqingWorkspace\\Day_14_test_io\\src\\www\\hqyj\\io\\testio\\oisoos.txt");
}
@Test
public void testPerson()throws Exception{
//序列化
oos = new ObjectOutputStream(new FileOutputStream(file));
Person person = new Person();
oos.writeObject(person);
}
@Test
public void testPerson2()throws Exception{
//反序列化
ois = new ObjectInputStream(new FileInputStream(file));
Object o = ois.readObject();
System.out.println((Person) o);//Person{name='zhangsan', age=null}
// Person p = (Person)ois.readObject();
// System.out.println(p);
// System.out.println(ois.readObject());
}
@After
public void close()throws Exception{
if (ois != null) ois.close();
if (oos != null) oos.close();
}
}
public class Person implements Serializable {
private static final long serialVersionUID = 1009021700170338002L;
//
private String name = "zhangsan";
private transient Integer age = 18;
//假设我有10000个属性
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
IDEA添加serivalVersionUID
4.ISR和OSW
字符流
字符流的底层是字节流,每次处理一个字符(char)
ISR:InputStreamReader,字符输入流
①InputStreamReader(InputStream in)
创建一个使用默认字符集的 InputStreamReader
②InputStreamReader(InputStream in, String charsetName)
创建使用指定字符集的 InputStreamReader。
OSW:OutputStreamWriter,字符输出流
①OutputStreamWriter(OutputStream out)
创建使用默认字符编码的 OutputStreamWriter
②OutputStreamWriter(OutputStream out, String charsetName)
创建使用指定字符集的 OutputStreamWriter
@Test //写
public void write()throws Exception{
osw = new OutputStreamWriter(new FileOutputStream(file));
osw.write("HelloWorld");
}
@Test //读
public void read()throws Exception{
isr = new InputStreamReader(new FileInputStream(file));
char[] chars = new char[1024];
isr.read(chars);
System.out.println(new String(chars));//HelloWorld
}
5.PW和BR
PW:PrintWriter,输出打印流
--构造方法
①PrintWriter(File file)
使用指定文件创建不具有自动行刷新的新 PrintWriter
②PrintWriter(File file, String csn)
创建具有指定文件和字符集且不带自动刷行新的新 PrintWriter
③PrintWriter(OutputStream out)
根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。
④PrintWriter(OutputStream out, boolean autoFlush)
通过现有的 OutputStream 创建新的 PrintWriter。
⑤PrintWriter(String fileName)
创建具有指定文件名称且不带自动行刷新的新 PrintWriter。
⑥PrintWriter(String fileName, String csn)
创建具有指定文件名称和字符集且不带自动行刷新的新 PrintWriter。
⑦PrintWriter(Writer out)
创建不带自动行刷新的新 PrintWriter
⑧PrintWriter(Writer out, boolean autoFlush)
创建新 PrintWriter。
--常用方法
①PW提供了丰富的print方法和println方法的重载方法
BR:BufferedReader:缓冲字符输入流
--构造方法
①BufferedReader(Reader in)
创建一个使用默认大小输入缓冲区的缓冲字符输入流
②BufferedReader(Reader in, int sz)
创建一个使用指定大小输入缓冲区的缓冲字符输入流
--常用方法
①String readLine()
连续读取一行字符串,直到读取到换行符为止,返回的字符串中不包含该换行符
public class TestPWAndBR {
public static void main(String[] args) throws IOException {
File file = new File("E:\\Shixun\\huaqingWorkspace\\Day_15_test_io\\src\\www\\hqyj\\io\\testio/pwbr.txt");
//写入内容后要清空缓冲区才能真正写入文件,PrintWriter可以使用printf、println、format方法来清空,或者直接调用close()清空,这时才真正写入文件
PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file)),true);
pw.print("123");
pw.print("456");
pw.print("789");
pw.println("abc");//多了个换行
pw.println("def");
// pw.close();
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
System.out.println(br.readLine());
char[] chars = new char[1024];
br.read(chars);
System.out.println(new String(chars));
//
// File file2 = new File("E:\\Shixun\\huaqingWorkspace\\Day_15_test_io\\src\\www\\hqyj\\io\\testio/pwbr_copy.txt");
// PrintWriter pw2 = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file2)),true);
// pw2.write(chars);
// pw2.close();
}
}