IO技术主要的作用是解决设备与设备之间的数据传输问题。
File类
sun使用了一个File类描述了文件或者文件夹的,File类可以描述一个文件或者一个文件夹。
File类的构造方法:
File(String pathname) 指定文件或者文件夹的路径创建一个File对象
File(File parent, String child) 根据parent抽象路径名和child路径名字符串创建一个新File实例
路径问题:
绝对路径:该文件在硬盘上的完整路径,绝对路径一般都是以盘符开头的。
相对路径: 相对路径就是资源文件相对于当前程序所在的路径。
. 当前路径
.. 上一级路径
注意: 如果程序当前所在的路径与资源文件不是在同一个盘下面,是没法写相对路径的。
File类的常用方法:
创建
createNewFile()——在指定位置创建一个空文件,成功就返回true,如果已存在就不创建然后返回false;
mkdir()——创建一个单级文件夹;
mkdirs()——创建多级文件夹;
dir = new File("F:\\aa\\bb");
System.out.println("创建多级文件夹:"+ dir.mkdirs());
renameTo(File dest)——如果目标文件与源文件是在同一个路径下,那么renameTo的作用是重命名,如果目标文件与源文件不是在同一个路径下,那么renameTo的作用就是剪切,而且还不能操作文件夹;
File file = new File("F:\\aa");
File destFile = new File("F:\\bb");
System.out.println("重命名成功吗?"+file.renameTo(destFile)) ;
删除
delete()——删除文件或一个空文件夹,成功返回true,失败返回false;
deleteOnExit() ——JVM退出的时候删除文件;
判断
exists()——文件或文件夹是否存在;
isFile()——是否是一个文件,如果不存在,则始终为false;
isDirectory()——是否是一个目录,如果不存在,则始终为false;
isHidden()——是否是一个隐藏的文件或是否是隐藏的目录;
isAbsolute()——测试此抽象路径名是否为绝对路径名;
获取
getName()——获取文件或文件夹的名称;
getPath()——返回绝对路径;
getAbsolutePath()——获取文件的绝对路径,与文件是否存在没关系;
length()——获取文件的大小(字节数),如果文件不存在则返回0L,如果是文件夹也返回0L;
getParent()——获取文件的父路径;
lastModified() ——获取最后一次被修改的时间;
文件夹相关
static File[ ] listRoots()——列出所有的根目录(Window中就是所有系统的盘符);
list()——把当前文件夹下面的所有子文件名与子文件夹名存储到一个String类型的数组中返回;
listFiles()——把当前文件夹下面的所有子文件与子文件夹都使用了一个FIle对象描述,然后把这些File对象存储到一个FIle数组中返回;
list(FilenameFilter filter)——返回指定当前目录中符合过滤条件的子文件或子目录。
listFiles(FilenameFilter filter)——返回指定当前目录中符合过滤条件的子文件或子目录。
// 自定义一个文件名过滤器
class MyFilter implements FilenameFilter{
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".java");
}
}
IO流分类
如果是按照数据的流向划分
输入流
输出流
如果按照处理的单位划分
字节流: 字节流读取得都是文件中二进制数据,读取到二进制数据不会经过任何的处理。
字符流: 字符流读取的数据是以字符为单位的。字符流也是读取文件中的二进制数据,不过会把这些二进制数据转换成我们能识别的字符。
字符流 = 字节流 + 解码
输入字节流
--------| InputStream 所有输入字节流的基类抽象类
--------------| FileInputStream 读取文件数据的输入字节流
--------------| BufferedInputStream 缓冲输入字节流,缓冲输入字节流的出现主要是为了提高读取文件数据的效率。其实该类内部只不过是维护了一个8kb的字节数组而已
使用FileInputStream读取文件数据的步骤
1. 找到目标文件
2. 建立数据的输入通道
3. 读取文件中的数据
4. 关闭资源
使用BufferedInputStream的步骤
1. 找到目标文件
2. 建立数据的输入通道
3. 建立缓冲输入字节流流
4. 关闭资源
注意: 凡是缓冲流都不具备读写文件的能力
输出字节流
--------| OutputStream 是所有输出字节流的父类,抽象类
-------------| FileOutStream 向文件输出数据的输出字节流
-------------| Bufferedoutputstream 缓冲输出字节流,BufferedOutputStream出现的目的是为了提高写数据的效率,内部也是维护了一个8kb的字节数组而已
FileOutputStream如何使用呢
1. 找到目标文件
2. 建立数据的输出通道
3. 把数据转换成字节数组写出
4. 关闭资源
FileOutputStream要注意的细节
1. 使用FileOutputStream 的时候,如果目标文件不存在,那么会自动创建目标文件对象
2. 使用FileOutputStream写数据的时候,如果目标文件已经存在,那么会先清空目标文件中的数据,然后再写入数据
3.使用FileOutputStream写数据的时候,,如果目标文件已经存在,需要在原来数据基础上追加数据的时候,应该使用new FileOutputStream(file,true)构造函数,第二参数为true
4.使用FileOutputStream的write方法写数据的时候,虽然接收的是一个int类型的数据,但是真正写出的只是一个字节的数据,只是把低八位的二进制数据写出,其他二十四位数据全部丢弃。
使用BufferedOutputStream的步骤
1. 找到目标文件
2. 建立数据的输出通道
3. 把数据写出
4. 关闭资源
BufferedOutputStream 要注意的细节
使用BufferedOutStream写数据的时候,它的write方法是是先把数据写到它内部维护的字节数组中,如果需要把数据真正的写到硬盘上面,需要调用flush方法或者是close方法、 或者是内部维护的字节数组已经填满数据
回忆
字符流: 字符流会把读取到的二进制的数据进行对应的编码与解码工作。 字符流 = 字节流 + 编码(解码)
输入字符流
----- | Reader 输入字符流的基类,抽象类
-------------| FileReader 读取文件的输入字符流
-------------| BufferedReader 缓冲输入字符流,出现的目的是为了提高读取文件的效率和拓展了FileReader的功能,其实该类内部也是维护了一个字符数组;
FileReader的用法
1. 找到目标文件
2. 建立数据的输入通道
3. 读取数据
4. 关闭资源
输出字符流
------| Writer 输出字符流的基类,抽象类
-----------| FileWriter 向文件数据数据的输出字符流
-----------|BufferedWriter 缓冲输出字符流,提高FileWriter的写数据效率与拓展FileWriter的功能。BufferedWriter内部只不过是提供了一个8192长度的字符数组作为缓冲区而已,拓展了FileWriter的功能。
FileWriter的使用步骤
1. 找到目标文件
2. 建立数据输出通道
3. 写出数据
4. 关闭资源
FileWriter要注意的事项
1. 使用FileWriter写数据的时候,FileWriter内部是维护了一个1024个字符的数组,写数据的时候会先写入到它内部维护的字符数组中,如果需要把数据真正写到硬盘上,需要调用flush或者是close方法或者是填满了内部的字符数组;
2. 使用FileWriter的时候,如果目标文件不存在,那么会自动创建目标文件;
3.使用FileWriter的时候, 如果目标文件已经存在了,那么默认情况会先清空文件中的数据,然后再写入数据,如果需要在原来的基础上追加数据需要使用“new FileWriter(File , boolean)”的构造方法,第二参数为true。
对象的输入输出流
对象的输入输出流的主要作用是用于写对象的信息与读取对象的信息,对象信息一旦写到文件上那么对象的信息就可以做到持久化了。
对象的输出流:ObjectOutputStream
对象的输入流: ObjectInputStream
对象输入输出流要注意的细节
1. 如果对象需要被写出到文件上,那么对象所属的类必须要实现Serializable接口。 Serializable接口没有任何的方法,是一个标识接口而已;
2. 对象的反序列化创建对象的时候并不会调用到构造方法;
3. serialVersionUID 是用于记录class文件的版本信息的,serialVersionUID这个数字是通过一个类的类名、成员、包名、工程名算出的一个数字。使用ObjectInputStream反序列化的时候,ObjectInputStream会先读取文件中的serialVersionUID,然后与本地的class文件的serialVersionUID进行对比,如果这两个id不一致,那么反序列化就失败了。
4. 如果序列化与反序列化的时候可能会修改类的成员,那么最好一开始就给这个类指定一个serialVersionUID,如果一类已经指定的serialVersionUID,然后在序列化与反序列化的时候,jvm都不会再自己算这个class的serialVersionUID了。
5. 如果一个对象某个数据不想被序列化到硬盘上,可以使用关键字transient修饰。
7. 如果一个类维护了另外一个类的引用,那么另外一个类也需要实现Serializable接口。
转换流
输入字节流的转换流:InputStreamReader
输出字节流的转换流:OutputStreamWriter
转换流的作用
1. 如果目前所获取到的是一个字节流需要转换字符流使用,这时候就可以使用转换流。
字节流----> 字符流
2. 使用转换流可以指定编码表进行读写文件。