文件操作IO 流
一、Java中文件的描述
1. File类的概述
- Java中采用File类的方法来描述一个文件
- 对于File而言,其封装的并不是一个真正存在的文件,仅仅是一个路径名而已.它可以是存在的,也可以是不存在的.将来是要通过具体的操作把这个路径的内容转换为具体存在的
2.File类的常用构造方法和常用方法
- 构造方法
- File类创建相关的方法
- File获取相关的方法
- File类判断相关的方法
3.相对路径与绝对路径
- 绝对路径:以C:/ 、D:/ 盘符开头的路径就叫绝对路径
- 相对路径:先指定一个工作目录,然后用 . 或者… 开头的路径,表示一个具体的文件位置,相对路径的参照点就是当前的工作目录
4.[练习]罗列出当前目录中都包含哪些文件和目录
二、文件数据的读写----IO流
2.1IO流的概述和分类
- IO流的概述
1.IO:输入/输出(Input/Output)
2.流:是一种抽象概念,是对数据传输的总称.也就是说数据在设备间的传输称为流,流的本质是数据传输
3.IO流就是用来处理设备间数据传输问题的.常见的应用: 文件复制; 文件上传; 文件下载 - IO流的分类
1.字节流:读写数据是以字节为基本单位 (byte)
2.字符流:读写数据是以字符为基本单位(char) - 使用场景:
1.字节流:处理二进制文件/数据的时候(操作的是图片、视频、音频等二进制文件)
2.字符流:处理文本文件/数据的时候(操作的是纯文本文件)
3.如果不确定文件类型,优先使用字节流.字节流是万能的流
(拿一个记事本打开一个文件,能看懂叫文本文件,看不懂叫二进制文件)
2.2复制一个二进制文件
-
读取原来文件,然后依次写入目标文件
-
方法介绍:
读完后则返回-1,用来判断是否读完文件
-
操作流程:
1.打开文件(构造方法)
2.read:从文件中将数据读到内存中
3.write:把数据从文件中写入内存中
4.close:关闭文件
如果不关闭文件,就会造成文件资源泄露 -
文件资源泄露
当一个进程中打开一个文件的时候,就会在PCB中进行一定的记录,本质上就是在文件描述符表中创建一个项,每次关闭一个文件,就是在文件描述符表中删除相应的项,文件描述符表相当于PCB中的属性,一个进程可能对应多个线程(每个PCB对应一个线程),同一个进程中若干PCB共享一个文件描述符表.
文件资源泄露关键在于,文件描述符表是有上限的,一旦文件描述符满了后之后想打开文件就会失败
2.2.1不带缓存的字节流实现
- 代码一:
当出现异常情况下,不会执行关闭文件操作,所以需要try catch finally - 代码二:
public static void main(String[] args) {
//0.打开文件
FileInputStream fileInputStream=null;
FileOutputStream fileOutputStream=null;
try {
fileInputStream=new FileInputStream("d:/testdemo/rou.jpg");
fileOutputStream=new FileOutputStream("d:/testdemo/rou3.jpg");
byte[] buffer=new byte[1024];
int len=-1;
while ((len = fileInputStream.read(buffer)) != -1){
fileOutputStream.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileInputStream.close();
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
代码逻辑复杂可进一步优化
- 代码三:
try()语句会在执行代码后,自动调用close方法(前提这个类必须实现Closable接口)
public static void main(String[] args) {
try(FileInputStream fileInputStream=new FileInputStream("d:/testdemo/rou.jpg");
FileOutputStream fileOutputStream=new FileOutputStream("d:/testdemo/rou2.jpg")){
byte[] buffer=new byte[1024];
int len=-1;
while ((len = fileInputStream.read(buffer)) != -1){
fileOutputStream.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
2.2.2带缓存的字节流实现(更高效)
public static void main(String[] args) {
try(FileInputStream fileInputStream=new FileInputStream("d:/testdemo/rou.jpg");
FileOutputStream fileOutputStream=new FileOutputStream("d:/testdemo/rou2.jpg");
BufferedInputStream bufferedInputStream=new BufferedInputStream(fileInputStream);
BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(fileOutputStream)){
byte[] buffer=new byte[1024];
int len=-1;
while ((len = bufferedInputStream.read(buffer)) != -1){
bufferedOutputStream.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
2.2.3字符流实现
public static void main(String[] args) {
try(FileReader fileReader=new FileReader("d:/testdemo/123/1.txt");
FileWriter fileWriter=new FileWriter("d:/testdemo/123/2.txt");){
char[] buffer=new char[1024];
int len=-1;
while ((len = fileReader.read(buffer)) != -1){
fileWriter.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
- IO流总结
三、序列化和Java如何实现序列化
- 序列化:序列化是一种用来处理对象流的机制,所谓对象流也就是将对象的内容流化。可以对流化后的对象进行读写操作,也可以将流化后的对象传输与网络之间。序列化是为了解决在对对象进行读写操作时所引发的问题。
- Java中实现序列化
1.调用java中OutputStream的writeObject方法来做
- 需要序列化的类必须实现Serializable接口,该接口没有实现方法。implements Serializable:只是标记了该对象可被序列化。