目录
💕💕一、数据流
编辑
为什么input是读取,output是写入?
💕💕二、InputStream 概述
😘😘1. 方法
😘😘2. FileInputStream 子类
👻👻①构造方法👻👻
👻👻②代码案例👻👻
代码1:试用 read()
代码2:尝试读取中文字符
代码3:使用 Scanner 读取
💕💕三、OutputStream概述
😘😘1. 方法
😘😘2. FileInputStream 子类
👻👻1. 构造方法👻👻
👻👻2.代码案例👻👻
代码1:写入文件
代码2:利用 PrintWriter 这种高效的方法完成输出
一、数据流
文件的读写采用数据流的方式,类似于一个储水池,输入的一端叫做 输入流,输出的一端叫做 输出流。而输入流和输出流采用的是 不同的类。如下图的关系。
为什么input是读取,output是写入?
程序和运行时数据是在内存中驻留的,而 input,output都是相对内存来说 的,input是从磁盘读取到内存 ,output是从内存写到磁盘.
二、InputStream 概述
1. 方法
InputStream 只是一个抽象类,如果要创建实例化还需要具体的实现类。关于InputStream 的实现类有很多,而我们只关心从文件中读取,所以通常用 FileInputStream 实现
read() -
从文件输入流中读取一个字节。read(byte[] b)
-从此输入流中读取最多b.length
个字节的数据到一个字节数组中。read(byte[] b, int off, int len)
-从此输入流中读取最多len
个字节的数据到一个字节数组中。
2. FileInputStream 子类
①构造方法
FileInputStream(File file)
-创建文件输入流以从File
对象读取。FileInputStream(String name)
-创建文件输入流以从指定的文件名读取。FileInputStream(FileDescriptor fdObj)
-创建从指定文件描述符读取的文件输入。
②代码案例
注意 !!!!
~ ~ 为什么每次关闭代码一定要关闭文件?
- 每个进程对应着一个PCB,而PCB里有一个文件描述符表(同一个进程中多个PCB共同使用一份文件描述符表),文件描述附表其实就相当于一个 数组\顺序表。每次进程打开一个文件,都会在这个表里创建一个项,这个项就表示一个文件。
- 表的项最大容量,可以进行配置。
- 如果关闭一个文件就相当于把表里对应的项 给释放掉,但是如果一直不关闭,就会一直占用。这就意味着一直打开都不关闭,就会导致 表项被耗尽~~这是一个非常严重的bug
~ ~ 所以才能每次都关闭呢?
1. 使用 close() , 但是要注意每次一定能执行到这一条语句
2. 使用 try-with-resource 结构(推荐使用!),try结束就能保证关闭文件,不用考虑是否执行到close 语句。(下面的代码案例就是这样写的)
代码1:试用 read()
public class Demo1 {public static void main(String[] args) throws IOException {try (InputStream stream = new FileInputStream("./文件部分/测试.txt")) {while (true) {int b = stream.read();System.out.print(b);if (b == -1) {//代表文件已经读完break;}}}} }
文件中的内容是: Hello word.
输出结果是
代码2:尝试读取中文字符
public static void main(String[] args) throws IOException {try (InputStream stream = new FileInputStream("./文件部分/测试.txt")){byte[] b = new byte[12];int len;while (true){len = stream.read(b);//每次读取一个字节,返回刚读到的字节if (len == -1){break;}}for (int i =0;i< b.length;i+=3){////每次读取3字节进行TTF-8解码,得到中文字符//利用String的构造方法完成,这个方法不是通用解法,知道就行String s = new String(b,i,3,"UTF-8");System.out.printf("%s",s);}}}
文件中的内容是: 你好中国
输出结果是:
代码3:使用 Scanner 读取
- Scanner(InputStream ,String charset) --使用charset字符集进行 is 的扫描读取
public static void main(String[] args) throws IOException {try (InputStream is = new FileInputStream("./文件部分/测试.txt")){Scanner s = new Scanner(is);while (s.hasNext()){String ch = s.next();System.out.println(ch);}}}
文件中的内容是: 你好中国
输出结果是:
三、OutputStream概述
1. 方法
write() -
写入要给字节的数据。read(byte[] b)
-将b这个字符数组中的数据全部写入OS(OutputStream)中。read(byte[] b, int off, int len)
-将b这个字符数组中从off开始的数据写入OS中,一共写len个close() -
关闭字节流。flush()
-重要!我们知道I/O操作是比较慢的,大多的OutputStream为了减少设备操作的次数,在写数据的时候会 先暂时写入内存的一个指定区域,知道这个区域满了以后才一起写入设备中,而这个区域一般称为 缓冲区。但是因此我们的部分数据可能会留在缓冲区,因此我们在一段代码完成的时候,记得进行 flush(刷新) 操作。
2. FileInputStream 子类
1. 构造方法
FileOutputStream(File file)
-从File
对象读取。FileOutputStream(String name)
-从指定的文件名读取。FileOutputStream(FileDescriptor fdObj)
-从指定文件描述符读取。
2.代码案例
代码1:写入文件
public static void main(String[] args) throws IOException {try (OutputStream os = new FileOutputStream("./文件部分/测试.txt")){os.write('I');//传入一个字符os.write(' ');byte[] am = {'a','m',' '};//传入一个 byte类型的数组os.write(am);String str = "a boy.";byte[] boy = str.getBytes();//将字符串转换为 数组os.write(boy);//再从内存写入到文件中String s = "你呢?";byte[] b = s.getBytes("utf-8");//使用utf-8将其转换为中文传入os.write(b);os.flush();//不要忘记 flush}}
程序运行结束后,文件内容发生改变:
代码2:利用 PrintWriter 这种高效的方法完成输出
public static void main(String[] args) throws IOException {//创建一个文件流实例os 与本地文件 对应try (OutputStream os = new FileOutputStream("./文件部分/测试.txt")){//这个构造是 把输入的内容存放到os这个实例中,才用utf-8编码try(OutputStreamWriter osWriter= new OutputStreamWriter(os,"utf-8")){//这个构造 封装了print等输入方法,print到osWrite这个实例中try (PrintWriter printWrite = new PrintWriter(osWriter)){printWrite.println("第一行!");printWrite.print("第二行\n");printWrite.flush();}}}}
程序运行结束后,文件内容发生改变: