IO流
IO就是输入输出,IO设备在计算机中起着举足轻重的作用,IO流也就是输入输出流,用来交互数据,程序和程序交互,程序也可以和网络等媒介交互。
一、IO流的分类
要分类,肯定得站得不同角度来看这个问题。
- 根据流向划分,分为输入流和输出流
- 根据数据的单位来分划,分为字节流和字符流
- 根据功能划分,分为节点流和包装流
- 还有很多
二、四大基本流
在java中IO流非常之多,但都继承于这四大基流,分别为,字节输入流
(InputStream),字节输出流
(OutputStream),字符输入流
(Reader)和字符输出流
(Writer).
它们都是抽象类,不能创建对象,只能创建它们的子类对象,阅读API发现,它们都有一个共同的方法close方法,用来关闭流,如果不关闭流的话程序会一直引用着文件。
三、模板操作
- 创建源和目标
- 创建流对象
- 具体的IO操作
- 关闭流
在下面的例子中穿插讲述
四、文件流
文件流操作是是文件。分为字符流和字节流,字节流操作是所有的二进制文件包括视频啊,图片啊什么的。字符流主要解决的还是中文的一些问题,因为中文多个字节(GBK是2个字节,UTF-8是3个字节),所有可能出现读一半或者写一半就不读了或者不写了,这样就出现乱码了。具体用字符流还是字节流得具体选择,字节流是可以操作字符流的,但是反过来就可能出现问题。输入就是从文件中读到程序中来,而输出就是从程序中输出到文件中。在这样章节记住一句话:读进来,写出去。下面操作一下各个流的常用方法,
文件字节输入流(FileInputStream)
1
2
3
4> int read() 从此输入流中读取一个数据字节。
> int read(byte[] b) 从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中
> int read(byte[] b, int off, int len)从此输入流中将最多 len 个字节的数据读入一个 byte 数组中
>读取文件中所有的数据,用到了一个缓冲数组,也就是每次读取5个字节,直到读完为止有个len返回当前读了几个字节,如果后面没有字节了,那么它就返回-1
1
2
3
4
5
6
7//读取文件中所有的数据
byte[] buffer = new byte[5];//定义一个缓冲数组长度为5,每次只能读取5个字节
int len = 0;//当前读取的字节数,没有字节就返回 -1
while((len = in.read(buffer))!= -1 ){
String str = new String(buffer,0,len);
System.out.println(str);
}文件字节输出流(FileOutputStream)
1
2
3
4
5
6
7> 1.void write(byte[] b)
> 将 b.length 个字节从指定 byte 数组写入此文件输出流中。
> 2.void write(byte[] b, int off, int len)
> 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
> 3.void write(int b)
> 将指定字节写入此文件输出流。
>输出就是想文件中写数据,可以一次写一个字节,也可以写一个数组中的元素,这个比较简单。可以用一下四个步骤操作一下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class FileOutputStreamDemo {
public static void main(String[] args) throws Exception {
//1.创建源
File f = new File("C:/Users/15626/Desktop/test/123.txt");
//2.创建输出流对象
FileOutputStream out = new FileOutputStream(f);
//3.写操作
out.write(97);//只能一个一个的写
//将buffer数组中的数据写在文件中
byte[] buffer = "ABCDEF".getBytes();
out.write(buffer);
//从索引1开始的3个字节写在文件中
out.write(buffer, 1, 3);
//4.关闭资源
out.close();
}
}
文件字符输入流(FileReader)
字符流的方法是从父类中继承过来的,也和上面字节流的方法大同小异
1
2int read() 读取单个字符。
int read(char[] cbuf, int offset, int length) 将字符读入数组中的某一部分。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18//文件字符输入流
public class FileReaderDemo {
public static void main(String[] args) throws IOException {
//1.创建源
File src = new File("C:/Users/15626/Desktop/新建文件夹 (2)/test.txt");
//2.创建字符输入流对象
FileReader in = new FileReader(src);
//3.读操作
char[] buffer = new char[10];
int len = -1;
while((len = in.read(buffer)) != -1){
String str = new String(buffer,0,len);
System.out.println(str);
}
//4.关闭流
in.close();
}
}文件字符输出流(FileWriter)
1
2
3void write(char[] cbuf, int off, int len) 写入字符数组的某一部分。
void write(int c) 写入单个字符。
void write(String str, int off, int len) 写入字符串的某一部分。
文件的拷贝操作
把指定目录的.java文件拷贝到指定的目录
1 |
|
文件夹的拷贝
https://www.cnblogs.com/tfper/p/9855228.html
文件流正确关闭资源
https://www.cnblogs.com/tfper/p/9833722.html
五、缓冲流
缓冲流是一个包装流,目的起缓冲作用.操作流的时候,习惯定义一个byte/char数组. int read():每次都从磁盘文件中读取一个字节. 直接操作磁盘文件性能极低,为了解决这个问题,我们 定义一个数组作为缓冲区. byte[] buffer = new byte[1024]; 该数组其实就是一个缓冲区. 一次性从磁盘文件中读取1024个字节. 如此以来,操作磁盘文件的次数少了,性能得以提升,java提供的默认缓存区大小是8192(1024*8),我们一般不用修改大小.
缓冲流也有四种,分别是 BufferedInputStream,BufferedOutputStream,BufferedReader,BufferedWriter.操作方法都和文件流差不多,我们来看一下缓冲流到底快了多少?
1 | /** |
缓冲流的效率很高,所有以后操作字符字节流都可以用缓冲流包装起来。
六、内存流
内存流就是把程序中的数据暂存在内存中,在这里也就是数组中,或者把内存中的数据输出到其他媒介,内存流也是分为字节流,字符流还有一个字符串流(保存在字符串中)。简单操作一下,熟悉一个方法
1 | import java.io.*; |
1 | /** |
1 | /** |
要注意的关闭流无效,但是为了追求完美的格式,防止忘记了其他流的关闭,我还还是自娱自乐的关一下吧!
七、对象流
对象流包括ObjectInputStream和ObjectOutputStream,名字起得很有范,肯定是字节流
一般用对象流进行序列化和反序列化通过writeObject方法做序列化操作的,通过readObject方法做反序列化操作
1.序列化
指把堆内存中的Java对象数据,通过某种方式把对象存储到磁盘文件中或者传递给其他网络的节点(在网络上传输). 我们把这个过程称之为序列化.
需要做序列化的对象的类,必须实现序列化接口:java.io.Serializable接口(标志接口[没有抽象方法]). 底层会判断,如果当前对象是Serializable的实例,才允许做序列化.大多数类都已经实现了这个接口了
2.反序列化
把磁盘文件中的对象数据或者把网络节点上的对象数据,恢复成Java对象的过程.
1 | import java.io.File; |
可以看到里面有两个重要的问题,一个是反序列化对象需要对象的字节码文件,需要提供序列化ID固定这份字节码文件,还有一个是transient瞬息字段是不能序列化.
八、打印流
1.字节打印流
1 | import java.io.File; |
2.字符打印流
1 | /** |