input 输入–所有的往内存中送数据都是输入
output 输出–所有从内存中取数据都是输出
本地流
内存 --> 外存(硬盘,U盘,光盘)本地流输出
外存 --> 内存 本地流输入
网络流(结合socket)
内存 --> 网络 网络流输出
网络 --> 内存 网络流输入
Java I/O流
数据的持久化
- 数据长时间保留在硬盘上
- 数据长时间保存在数据库上,数据库的本质是以数据文件的方式持久化到硬盘上,
根据文件内容操作分为两种方式
- 字节流:对文件的内容读写是用字节的方式操作
- 字符流:对文件的内容读写是用字符 ( ascii ) 的方式操作,其本质还是字节流
Java.io.File类
用于操作文件的目录信息和文件信息,不能操作文件内容
注意一个问题:不同操作系统上,目录的间隔符不同
windows:C:\aa\bb\cc.txt
linux:/home/aa/bb/cc.txt
在Java中对路径的分隔符的表示
windows:C:\aa\bb\cc.txt
C:/aa/bb/cc.txt
linux:C:/aa/bb/cc.txt
如果下那个兼容windows和linux:
“aa”+File.separator+“bb”+File.aeparator+“cc.txt”
File的API
File(String filePath) | 构建File对象 |
File(File parent,String child) | 构建File对象 |
File(String parentName,String child) | 构建File对象 |
isFile() | 判断是否是目录 |
isDirector() | 判断是否是目录 |
length() | 获取文件的长度 |
exists() | 判断文件或目录是否存在 |
createNewFile() | 创建一个空文件,返回值是boolean,如果指定的文件不存在,就创建文件,并返回true,如果指定的文件存在,则返回false |
delete() | 删除文件,如果File表示的是一个目录,删除的时候要保证目录必须是空的 |
mkdir() | 创建目录 |
mkdirs() | 创建多个目录 |
listFiles() | 返回指定目录中的所有文件和目录 |
listFiles(FileFilter) | 返回指定目录中的部分文件和目录,用FileFilter设定筛选条件 |
listfiles(FilenameFilter) | 返回指定目录中的部分文件和目录,用FilenameFilter设定筛选条件 |
RandomAccessFile类
- 可以操作文件的内容
- 按照字节操作,字节流
- read读,write写,在此类中都有对用的API方法
- 能够通过seek方法随意移动改变文件的指针
RandomAccessFile类对文件的随机访问有两种模式
只读模式(r)、读写模式(rw)
创建对象 | |
---|---|
RandomAccessFile(File file,String mode) | 创建从中读取和向其中写入的随机访问流,文件通过File指定,模式通过String指定 |
RandomAccessFile(String name,String mode) | 创建从中读取和向其中写入的随机访问流,文件通过String指定,模式通过String指定 |
写入操作 | |
---|---|
void write(int d); | 此方法会在当前的指针所在的位置,写入一个字节,只能使用整型的低八位 |
void write(byte[] d); | 此方法会在当前的指针所在的位置,写入组个字节 |
void write(byte[] d,int offset,int len); | 此方法会将len个字节从指定的byte数组,从偏移量offset处开始,写入文件 |
读取操作 | |
---|---|
int read(); | 从文件中读取出一个byte字节,填充到整型的低八位,如果返回-1,表示读取到了文件的末尾 EOF(End Of File) |
int read(byte[] d); | 从指针执行的位置开始读取若干字节,存储到字节数组中,将读取到的字节按照顺序放在字节数组的对应位置上,返回值为读取到的字节数,也可以说成是长度,如果返回值为-1,则读取到文件的末尾 |
void write(byte[] d,int offset,int len); | 此方法会将len个字节从指定的byte数组,从偏移量offset处开始存储 |
其他操作 | |
---|---|
void getFilePointer(); | 返回此文件当前的偏移量 |
void seek(long poeition); | 设置到此文件开头0到文件指针的偏移量,在该位置发生下一个读取或写入操作 |
int skipBytes(int n); | 用此方法可以跳过一些字节,正数 |
字节流
字节流可以从 或 象一个特定的方法读写数据,数据是字节
封装流 / 处理流
针对字节流进行封装,即,对一个已经存在的流进行封装,通过所有的封装流,能够对数据更有效的读写,封装流的底层还是字节流,
通常字节流被称为低级流,封装流被称为高级流或过滤流
InputStream
是所有输入字节流的父类,其定义了基础的读取方法
int read(); | 读取一个字节。以int的形式返回,该int的低8位有效(字节),否则返回-1,表示文件末尾 EOF |
int read(byte[] b); | 尝试最多读取给定数组的length个字节,并存入该数组,返回值为实际读取的字节量的长度,否则返回-1,到文件末尾 |
int read(byte[] b,int offset,int len); | 将输入流中的最多len个数据字节写入byte的数组,从offset位置写入数组,len不能超过数组的实际长度,如果超过会报数组下标越界 |
void close(); | 关闭此输入流,并释放与该流关联的所有的系统资源 |
OutputStream
是所有输出字节流的父类,其定义了基础的写出方法
void write(int b) | 写出整型数据的低8位 |
void write(byte[] b) | 将给定的字节数组的数据全部写出 |
void write(byte[] b,int offset,int len) | 将给定的字节数组从偏移量offset开始的len个字节写入输出流 |
void flush() | 不能关流,刷新此输出流,并强制写出所有的缓冲的输出字节 |
void close(); | 关闭此输出流,并释放与该流关联的所有的系统资源 |
文件流
- 可以操作文件内容
- 操作的是字节流
- 低级流
FileInputStream | FileOutputStream |
---|---|
继承自InputStream抽象类 | 继承自OutputStream抽象类 |
缓冲流 Buffer缓冲 高级流之一
缓冲流的原理:
- 向硬件存储设备操作数据,导致跟硬件的交互次数增多
- 会降低读写的速度,做缓冲流的目的就是为了尽量减少和硬件的交互次数
- 靠牺牲内存来提高i/o的读写效率
BufferedOutputStream缓冲输出流
- 内部会维护一个缓冲区,每当我们向该流读出数据时,都会先将数据存入缓冲区
- 当缓冲区已满的时候,缓冲流会将数据一次性写出。
- 注意:void flush();是清除缓冲区,将缓冲区中的数据强制写出,保证数据的完整
BufferedInputStream缓冲输入流
- 内部维护一个缓冲区,没当我们向该流写入数据时,都会先将数据存入缓冲区
- BufferedInputStream的read方法,会从缓冲区读取数据,当缓冲区全部读取完
- 如果再次read时,再一次把缓冲区填满,read再逐一读取,以此往复
对象流 高级流之一
把内存的对象数据序列化到硬盘上,也可以把硬盘上的文件反序列化回内存的对象
序列化:把内存的对象,序列化到硬盘上,以字节的方式体现
反序列化:是把硬盘上的字节序列反序列化回内存中的对象
如果要实现对象的序列化和反序列化,就必须对序列化的对象所对应的类,实现java.io.Serializable接口,且类中最好给提供一个long类型的序列化的版本号
public class Student implements Serializable{
private long id=XXL;//长整形数据
//fileld 属性
//method 方法
}
java.io.Serializable接口
- 此接口仅表示可序列化语义,某个类实现这个接口,就是说这个类表示了可序列化这个语义
- 这个类的子类也同样具备序列化语义,
- 这个类需要提供一个常量,serializable
- 用来表示本类的序列化版本号,如果想跨平台,就需要显示声明一个版本号,且平台两边的版本必须相同
序列化类中可以有很多的属性,但部分属性不想被序列化和反序列话,把类中不需要序列化的属性前加上transient修饰符
transient:瞬间的,短暂的,临时的
public class Student implements Serializable{
private long id=1L;
private transient String name;//不可序列化
private int age;//能序列化
//fileld 属性
//method 方法
}
数据流 高级流之一
DataInputStream 数据输入流
适合对java基本数据类型的输入
//构造函数
DataInputStream(InputStream);
//api方法:
readInt();
//类似的方法 readXXX(); xxx代表某种类型
DataOutPutStream 数据输出流
适合对java基本数据类型的输出
//构造函数
DataOutputStream(OutputStream);
//api方法:
writeInt();
类似的方法 writeXXX(); xxx代表某种类型
字符流:高级流
针对字符流做低级流的二次或三次的封装处理,字符流也是高级流,其本质还是字节流,
Reader类:
- 是所有字符流输入的父类
- 是一个抽象类
int read() | 读取一个字符,是占用整形数据的低16位,低16位有效 |
int read(char[] chars) | 从流中读取一个字符数组的length个字符,并存储到字符数组中,返回的是实际读取的字符量 |
int read(char[] chars,int offset,int len) | 读取len个字符存储进字符数组中,以offset位置为起点 |
Writer类:
- 是所有字符流输出的父类
- 是一个抽象类
void write(int c) | 写出一个字符 |
void write(char[] chars) | 写出一个数组的字符数据 |
void write(char[] chars,int offset,int len) | 写出数据,从offset开始,取len个字符 |
void write(String str | 写出一个字符串 |
void write(void write(String str,int offset,int len) | 写出字符串,从offset开始,取len个字符 |
InputStreamReader类 字符输入流 高级流
- 可以设置字符集,
- 按照指定的字符集输入数据
- 将字节按照指定的字符集读入字符串数据
- 继承自Reader类
OutputStreamWriter 字符输出流 高级流
- 可以设置字符集,
- 按照指定的字符集输出数据
- 将字节按照指定的字符集写出字符串数据
- 继承自Writer类
缓冲字符流
缓冲字符流字节维护一个缓冲字符数组,用法与上述相似
- BufferedReader类。缓冲字符流输入
- BufferedWriter类,缓冲字符流输出
PrintWriter类
- 是一个特殊的类。只有输出,没有输入。
- 是具有自动刷新的缓冲字符输出流