IO流
什么是流?
io流就是Java中运输数据的一种载体,它能够吧数据从一个地方运输到另一个地方
流的分类:
a.根据数据运输的方向划分:
input输入 和 output输出
所有的往内存中送数据都是输入
所有的 往内存中出数据都是输出
b.根据传输数据的类型
字节流
字符流
File操作目录和文件信息
- File的api
//构建File类对象
File(String filePath);
File(File parent,String child);
File(String parentName,String child);
//判断是否是文件
.isFile()
//判断是否是目录
.isDirectory()
//获取文件的长度
.length()
//判断文件或目录是否存在
.exists()
//创建一个空文件,返回值boolean
// 如果指定的文件不存在,就创建文件返回true
// 如果指定的文件存在,就返回flase
.createNewFile()
//删除文件
//注意:
//如果File表示一个目录
//删除的时候,要保证目录必须是空的
.delete()
//创建目录
.mkdir()
//创建多个目录
.mkdirs()
//返回指定目录中的所有文件和目录
.listFiles()
//返回指定的目录中的部分文件和目录,用FileFileter设定筛选条件
.listFiles()
//返回指定的目录中的部分文件和目录,用FilenameFileFileter设定筛选条件
.listFile(FilenameFilter)
字节流
字节流:可以从或向一个特定的方向读写数据,数据是字节
封装流/处理流:针对字节流进行封装,即对一个已经存在的流进行封装,通过所有的封装流能够对数据更有效的读写,封装流的底层还是字节流
通常字节流被称之为低级流
处理流被称之为高级流或过滤流
- 低级流(InputStream/OutputStream)
InputStream 所有字节输入流的父类,其定义了基础的读取方法
-int read() 抽象类
读取一个字节,以int的形式放回,该int的第8位有效
否则返回-1,表示文件末尾EOF end of file
-int read(byte[] b)
尝试最多读取给定数组length个字节,并存入该数组
返回值为实际读取字节量的长度,否则返回-1,到文件末尾
-int read(byte[] b , int offest , int len)
将输入流中的最多len个数据字节,写入byte数组
将从offset的位置开始写入数组,len不能超过数组的实际长度
如果超过会报数组下边越界异常
-void close()
关闭此输入流并释放与该流关联的所有的系统资源
OutputStream 所有字节输出流的父类,其定义了基础的写出方法
-void write(int d)写出整型数据的低8位
-void write(byte[] b)将给定的字节数组的数据全部写出
-void write(byte[] b , int offest , int len)
将给定的字节数组从偏移量offset开始的len个自己写入输出流
-void flush()
刷新此输出流并强制写出所有缓冲的输出字节
-void close()
关闭此输出流并释放与此输出流有关的所有的系统资源
- 低级流-文件输出流(FileInputStream/FileOutputStream)
FileOutputStream:文件输输出流-可以操作文件内容-低级流-字节流
//创建了一个输出流的对象,此对象跟硬盘的某个文件关联,对文件只能做输出操作
OutputStream os = new FileOutputStream(new File("D://aa//fos.txt"));
//把字符串转换成字节数组并写到os流对象中
os.write("hello world!".getBytes());
//清除缓冲,数据回写硬盘
os.flush();
//关闭流,并释放资源
os.close();
FileInputStream:文件输入流-可以操作问价那内容-低级流-字节流
//创建了一个输入流的对象,此对象跟硬盘的某个文件关联,对文件做输入操作
InputStream is = new FileInputStream("d:/aa/fos.txt");
int d = -1;
while((d=is.read())!=-1){
System.out.println((char)d);
}
is.close();
- 高级流-缓冲流(ObjectInputStram/ObjectOutputStream)
缓冲流的原理:
向硬件存储设备操作数据,导致增大跟硬件的交互次数,会降低读写的速度,做缓冲流的目的就是为了尽量减少跟硬件的交互次数
缓冲是靠牺牲内存来提升io的读写效率
BufferedOutputStream 缓冲输出流原理:
缓冲输出流内部会维护一个缓冲区,每当我们向该流写出数据时,都会先将数据存入缓冲区,当缓冲区已满的时候,缓冲流会将数据一次性写出
注意:
void flush(),清除缓冲区,将缓冲区中的数据强制写出,以保证数据完整
BufferedInputStream 缓冲输入流原理:
缓冲输入流内部会维护一个缓冲区,每当我们向该流读入数据时,都会先将数据存入缓冲区,BufferedInputStream的read方法会从缓冲
区读取数据,当缓冲区全部读取完毕,如果再次read的时候,会在一次把缓冲区填满,read在逐一从缓冲区读取数据,以此往复
/**
* 用缓冲流的方式来复制文件
* 多字节
* 1.已经减少了和硬盘的交互次数
* 2.人为自己做了一个缓冲,减少循环数
* @throws IOException
*/
@Test
public void testMethod4() throws IOException {
System.out.println("文件开始复制...");
long begin = System.currentTimeMillis();
// 构建输入低级流
InputStream is = new FileInputStream("D:/aa/te du.zip");
// 构建输入高级流
BufferedInputStream bis = new BufferedInputStream(is);
// 构建输出低级流
OutputStream os = new FileOutputStream("D:/aa/tedu5.zip");
// 构建输出高级流
BufferedOutputStream bos = new BufferedOutputStream(os);
// 多字节复制数据
byte[] buf = new byte[1024 * 1024 * 4];
int len = -1;
while ((len = bis.read(buf)) != -1) {
bos.write(buf, 0, len);
}
bis.close();
is.close();
bos.close();
os.close();
long end = System.currentTimeMillis();
System.out.println("文件复制结束..." + (end - begin));
}
- 高级流-对象流(ObjectInputStram/ObjectOutputStream)
把内存的对象数据,序列化到硬盘上,也可以把硬盘上的文件反序列化回内存的对象
序列化:
把内存的对象序列化到硬盘上,以字节的方式体现
反序列化:
把硬盘上的字节序列,反序列化回内存中的对象
比如:
Student stu = new Student("张三",20,"S001");
stu-->硬盘(序列化)-->内存堆中出现stu对象(反序列化)
注意:
如果要实现对象的序列化和反序列化,就必须对序列化的对象所对应的类实现java.io.Serializable接口
且类中最好给一个long类型的序列化的版本号
比如:
public class Student implements Serializavle{
private static final long serialVersionUID = 1L;
fileld 属性
method 方法
}
java.io.Serializable接口:
此接口仅表示可序列化语义,某个类实现这个接口,就是说这个类表示了可以序列化这个语义,这个类的子类也同样
具备序列化语义,这个类需要提供一个常量SerializableUID用来表示本类的序列化版本号,如果想跨平台,就需要
显示声明一个版本号,且平台两端的版本必须相同
序列化类中可以有很多的属性,但部分属性不想被序列化和反序列化,把类中的不需要序列化的属性前加上transient修饰符
transient:瞬间的,短暂的.临时的
public class Student implements Serializable{
private static final long serialVersionUID = 1L;
private transient String name; //不可以序列化
private int age;//能序列化
field 属性
methd 方法
}
比如:有一个student类实现了Serializable接口并添加了版本号
属性:private String name;//可以序列化
private int age;//可以序列化
private transient String stuNo;//不可以序列化
方法:有getter和setter还有toString
//序列化对象到硬盘中
Student stu1 = new Student();
stu1.setName("张三");
stu1.setAge(20);
stu1.setStuNo("S001");
//构建低级输出流
OutputStream os = new FileOutputStream("d:/aa/student.data");
//构建高级流,对象输出流
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(stu1);
oos.flush();
oos.close();
os.close();
// 反序列化操作
try {
//构建低级输入流
InputStream is = new FileInputStream("d:/aa/student.data");
//构建高级流 ,对象输入流
ObjectInputStream ois = new ObjectInputStream(is);
Student stu = (Student) ois.readObject();
System.out.println(stu);
ois.close();
is.close();
} catch (Exception e) {
e.printStackTrace();
}
- 高级流-数据流(DataInputStream/DataOutputStream)
DataInputStream 数据输入流,适合对java基本数据类型的输入
-构造函数
DataInputStream(InputStream)
-readInt();
类似的方法 readXXX(); XXX代表具体的某种类型
比如
//构建低级流
InputStream is = new FileInputStream("D:/aa/dos.txt");
//构建高级流
DataInputStream dis = new DataInputStream(is);
int value = dis.readInt();
String str = dis.readUTF();
//输出顺序的类型要和文件存储位置的数据一致
System.out.println(value+" "+str);
dis.close();
is.close();
DataOutputStream 数据输出流,适合对java基本数据类型的输出
-构造函数
DataOutputStream(OutputStream)
-writeInt();
类似的方法 writeXXX(); XXX代表具体的某种类型
比如:
//构建低级流
OutputStream os = new FileOutputStream("D:/aa/dos.txt");
//构建高级流
DataOutputStream dos = new DataOutputStream(os);
dos.writeInt(1000);
dos.writeUTF("Hello World!");
dos.flush();
dos.close();
os.close();
字符流
字符流: 高级流之一
针对字符流做低级流的两次或三次的封装处理,字符流也是高级流字符流的本质还是字节流
Reader 所有字符输入流的父类
-是一个抽象类
-常用api:
-int read()
读取一个字符,是占用整型数据的低16位,低十六位有效
-int read(char[] chars)
读取一个字符数组的length个字符,并存储到字符数组中
返回的实际读取的字符量
-int read(char[] chars , int offset , int len)
读取len个字符,存储到字符数组中,以offset位置为起点
writer 所有字符输出流的父类
-是一个抽象类
-常用api:
-void write()
写出一个字符
-void write(char[] chars)
写出一个字符数组
-void write(char[] chars , int offset , int len)
写数组,从offset开始写len个字符到字符数组
-void write(String str);
写出一个字符串
-void write(String str , int offset , int len)
写出字符串数据中的部分数据
- 高级流-字符流(InputStreamReader/OutputStreamWriter)
InputStreamReader类: 字符输入流
-可以设置字符集,
-按照指定的字符集输入数据
-将字节按照指定的字符集读入字符串数据
-继承自Reader
//字符输入流,多字符读取
InputStream is = new FileInputStream("D:/aa/osw.txt");
InputStreamReader isr = new InputStreamReader(is,"UTF-8");
char[] chars = new char[13];
int len = -1;
while((len = isr.read(chars))!= -1){
System.out.println(new String(chars).substring(0,len));
}
isr.close();
is.close();
OutputStreamWriter类: 字符输出流
-可以设置字符集,
-按照指定的字符集输出数据
-将字节按照指定的字符集写出字符串数据
-继承自Writer
//将字节流转换成字符流
OutputStream os = new FileOutputStream("D:/aa/osw.txt");
OutputStreamWriter osw = new OutputStreamWriter(os,"UTF-8");
osw.write("Hello World!,我们爱java");
osw.flush();
osw.close();
os.close();
- 高级流-缓冲字符流(BufferedReader/BufferedWriter)
缓冲字符流:缓冲字符流自己维护一个缓冲字符数组
BufferedReader类:缓冲字符流输入
-String readLine();//读取一行字符,读到末尾为null
BufferedWriter类:缓冲字符流输出
//构建一个低级输入流
InputStream is = new FileInputStream("D:/aa/dw.txt");
//构建高级流 第二次封装
Reader isr = new InputStreamReader(is);
//第三层封装
BufferedReader br = new BufferedReader(isr);
char[] chars = new char[5];
int len = -1;
while((len = br.read(chars))!=-1){
System.out.println(new String(chars).substring(0,len));
}
br.close();
isr.close();
is.close();
- 特殊的类PrintWriter类
特殊的类,只有输出,没有输入
是具有自动行刷新的缓冲字符输出流
例如:
OutputStream os = new FileOutputStream("D:/aa/pw.txt");
Writer osw = new OutputStreamWriter(os,"UTF-8");
PrintWriter pw = new PrintWriter(osw,true);//代表自动行刷新
PrintWriter pw1 = new PrintWriter(osw);
pw.println("不是用write写出的,用println方法写的,是可以用write写的");
pw.flush();
pw.close();
osw.close();
os.close();
- 总结
对于一些IO流的知识点的总结,前面还有一个RandomAccessFile随机读写类
这些常用的IO流需要记住,欢迎大家补充