基于白嫖:2020最新版 Java基础-IO框架
1 概述
- 流:内存和存储设备之间传输数据的通道;
- 输入流:将存储设备中的内容读入到内存中;
- 输出流:将内存中的内容写入到存储设备中;
- 字节流:以字节为单位,可以读写所有数据;
- 字符流:以字符为单位,只能读写文本数据;
- 节点流:具有实际传输数据的读写功能;
- 过滤流:在节点流的基础之上增强功能;
2 继承关系
3 字节流
3.1 抽象父类InputStream
字节输入流父类抽象类InputStream
实现了Closeable
接口,定义了一个输入流应该具有的方法。
int available()
:返回估计可以访问的字节数;void close()
:关闭此输入流并释放相关资源;void mark(int readlimit)
:标记当前位置;boolean markSupported()
:测试该输入流是否支持mark
和reset
方法;abstract int read()
:读入下一个字节;int read(byte[] b)
:读入一定数量的字节,并将其缓存在b
中,返回读到的个数;int read(byte[] b, int off, int len)
:讲输入流中最多len
个数据读入到b
中,返回读到的个数;void reset()
:重新定位到最新的mark
位置;long skip(long n)
:跳过和丢弃n
个字节;
3.2 抽象父类OutputStream
字节输出流父类抽象类实现了Closeable
和Flushable
接口。
void close()
:关闭输出流并释放资源;void flush()
:刷新强制所有的缓冲写出输出字节;void write(byte[] b)
:将b
写入到输出流;void write(byte[] b, int off, int len)
:指定b
中[off,off+len)
长的字节写出流;abstract void write(int b)
:抽象方法,将指定一个字节输出到流;
3.3 文件字节流
FileInputStream
和FileOutputStream
分别继承InputStream
和OutputStream
实现其方法,用于从文件读入和写出字节;
3.3.1 FileInputStream
可以直接使用文件名路径字符串来实例化:
FileInputStream fileInputStream = new FileInputStream("data.txt");
如果文件不存在,抛出FileNotFoundException
;
一般采用读入到byte
数组的方式进行读取数据;
3.3.2 FileOutputStream
FileOutputStream outputStream = new FileOutputStream("data.txt");
String data = "aaAA";
outputStream.write(data.getBytes());
可以覆盖和追加内容,写入字节或者字节数组;
3.3.3 文件复制
public static void main(String[] args) {
try {
FileInputStream fileInputStream = new FileInputStream("data.txt");
FileOutputStream fileOutputStream=new FileOutputStream("out.txt");
//假设数组是3
byte[] buf=new byte[3];
int num=0;
while ((num=fileInputStream.read(buf))!=-1){
fileOutputStream.write(buf,0,num);
}
fileInputStream.close();
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
建立缓冲区,每次读入到buf,把实际读入的个数返回给num,然后同时写入到输出流,注意写出的参数是左闭右开的;
3.4 字节缓冲(buffer)流
数据存储在缓冲区中,提高效率。
3.4.1 BufferedInputStream
要学习BufferedInputStream
先学习FilterInputStream
(过滤器输入流),FilterInputStream
过滤器流继承自InputStream
,内部还含有一个InputStream
成员变量,这是典型的装饰器模式
,当调用对外显示的方法时候,一方面执行成员变量的方法,另一方面添加自己的私货;
BufferedInputStream
继承自FilterInputStream
,构造方法需要传入一个InputStream
(装饰器模式的上一级对象),内部成员变量有一个byte[]
类型的缓冲区。
为什么需要使用缓冲区?使用FileInputStream
时候,每一次read()
都会直接去磁盘进行读取文件操作,消耗较大的IO时间,而使用了BufferedInputStream
,会先读入一部分到缓冲区(内存),当read()
的时候先去缓冲区(内存)找,如果没有才继续又读入下一批数据到缓冲区,然后返回read()
需要的值,减少了IO次数。
3.4.2 BufferedOutputStream
public static void main(String[] args) {
try {
FileOutputStream outputStream = new FileOutputStream("data.txt");
BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(outputStream);
bufferedOutputStream.write(65);//不会立即写入,先放缓存区
bufferedOutputStream.write(66);//不会立即写入,先放缓存区
bufferedOutputStream.flush();//刷新一下才回存入硬盘
bufferedOutputStream.close();//会主动关闭FileOutputStream,也会调用flush
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
当写入的时候,不会立即写入到磁盘,而是先写入缓存区,当缓存区满的时候再写入磁盘或者主动调用flush()
或者close()
,减少IO次数,提高效率;
3.5 对象流(序列化)
3.5.1 Serializable接口
public interface Serializable {
}
该接口,没有定义任何抽象方法,对于实现这个接口的类来说就是一个标记类,标记这个类可以被序列化。
如果不想序列化某一个属性使用关键字:transient
,静态属性不属于对象所以也不能序列化;
3.5.2 ObjectInputStream
继承InputStream
抽象类,实现ObjectInput
和ObjectStreamConstants
接口;使用了缓冲区功能;增强了读写8种基本类型和字符串功能;增强了读写对象的功能。
FileInputStream fileInputStream=new FileInputStream("stu.object");
ObjectInputStream objectInputStream =new ObjectInputStream(fileInputStream);
Student student= (Student) objectInputStream.readObject();
System.out.println(student.toString());
3.5.3 ObjectOutputStream
FileOutputStream fileOutputStream=new FileOutputStream("stu.object");
ObjectOutputStream objectOutputStream=new ObjectOutputStream(fileOutputStream);
Student stu=new Student(1,"Tom");
objectOutputStream.writeObject(stu);
objectOutputStream.close();
注意初始化对象输出流的时候需要有一个基流对象作为其成员变量(装饰者模式),由于Collection
接口下面的实体类基本上都实现了Serializable
接口,所以可以传入一个集合实体类。
3.6 字节数组流(ByteArrayStream)
ByteArrayInputStream
和ByteArrayOutputStream
**字节数组输入流在内存中创建一个字节数组缓冲区,从输入流读取的数据保存在该字节数组缓冲区中。**该流的目的内存to内存,适用于内存到内存的一些操作,比如对象的复制clone()
。最重要的就是一个字节数组作为中间的媒介。
4 字符流
4.1 字符编码
- ISO-8859-1:收录ASCII外,还包括西欧、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号;
- UTF-8:针对Unicode码表的可变长字符编码;国际上多一些,最长使用3 Bytes来表示一个字符;
- GB2312:简体中文;
- GBK:简体中文、扩充;
- BIG5 台湾,繁体中文;
4.2 抽象父类Reader和Writer
和字节流的抽象父类差不多也是定义了一些基本的想读写方法;
4.3 文件字符流
4.3.1 FileReader
FileReader
继承自InputStreamReader
。默认的字符编码使用UTF-8
;
FileReader fileReader =new FileReader("data.txt");
char[] buf=new char[4];
int readNum= 0;
while ((readNum=fileReader.read(buf))!=-1){
String s=new String(buf,0,readNum);
System.out.println(s);
}
fileReader.close();
注意字节流读到缓冲区使用的是byte[]
,而字符流读到的是char[]
,这就是为什么要字节流和字符流了,在java中char类型用2个字节表示;
4.3.2 FileWriter
FileWriter fileWriter=new FileWriter("file.txt");
for(int i=0;i<10;i++){
fileWriter.write("我爱你中国\n");
}
fileWriter.close();
可以写入字符串、字符数组、字符等。
4.4 字符缓冲流
BufferedReader
和BufferedWriter
支持高效读写、支持输入换行符、支持读一行写一行。也是装饰者模式,需要有一个基的输入输出流。缓冲流多的方法:
- 读流中
readLine()
:一行一行的读,返回String
,行末返回的null
; - 写流中
newLine()
:写入一个换行符;
4.5 打印流PrintWriter
PrintWriter
封装了print()/println()
方法,可以像print一行输出到文本;
4.6 转换流
InputStreamReader
和OutputStreamWriter
可以将字节流转换成字符流,可以设计字符的编码方法;类名的设计刚好是字节流和字符流的两个抽象父类组合在一起。
InputStreamReader
:从磁盘到内存,可以指定读入文件的编码格式,返回的是一个编码格式的字符;OutputStreamWriter
:从内存到磁盘,可以指定写文件的编码格式;
5 File类
5.1 概述
FIle
类代表了物理盘符中的一个文件或者一个文件夹;
5.2 常见方法
- mkdir():创建一个新目录;
- delete():删除文件或者空目录;
- exists():判断文件对象是否存在;是
- getName():获得名字;
- isFile():是否是文件;
- length():获得文件的长度;
- renameTo():修改文件名为;
- createNewFile():创建新文件;
- deleteOnExit():JVM退出时删除;
注意:File对象表示的不仅仅是文件,还可以表示文件夹及相关操作;
5.3 例子:打印目录下全部文件
public class Main {
public static void main(String[] args) {
File dir0=new File("/home/lwj/IdeaProjects/javaIO/");
//遍历这个目录
show(dir0);
}
public static void show(File dir){
//获得该目录全部列表
File[] files=dir.listFiles();
for(File file:files){
if(file.isFile()) System.out.println(file.getAbsolutePath());
else show(file);
}
}
}
6 properties
使用方法上和hashset差不多,但是它常和流相关,所以经常被用来作为一些框架的配置文件.properties
。