相对路径和绝对路径
1. 文件路径的分类
相对路径和绝对路径
2. 绝对路径概述
以盘符开始,在系统中具有唯一性:比如:c:/aaa/a.txt
3. 相对路径概述
相对某个位置而言的,不具有唯一性
如果代码中给定的路径没有以盘符开始,则默认相对于当前项目的根目录
比如:d:/bbb/ aaa.txt
比如:e:/bbb/ aaa.txt
如果在代码中使用相对路径:a.png 默认相对于当前项目的根目录
会在当前项目根目录下查找a.png
aaa/b.txt:会在当前项目根目录下查找aaa文件夹,然后在aaa文件夹下找b.txt
"/aaa.txt"则默认相对于当前项目的根目录的盘符里
"aaa.txt"则默认相对于当前项目的根目录
小结:
如何判断文件路径是相对路径还是绝对路径?
判断路径是否以盘符开始,如果是则绝对路径,否则是相对路径
掌握File类常用的构造方法
1. File类的作用
* 文件和目录路径名的抽象表示形式。
* 用来操作硬盘上的文件或文件夹,比如获得文件大小,删除文件,删除文件夹...
2. File类常用构造方法
public File(String pathname)
* 根据路径字符串创建文件对象
public File(String parent,String child)
* 根据父路径字符串和子路径字符串创建文件对象
public File(File parent,String child)
* 根据父路径文件对象和子路径字符串创建文件对象
File的常用方法
1. File类与获取文件信息相关的方法
public String getAbsolutePath() :获得文件或文件夹的绝对路径字符串
public String getPath() :获得创建文件对象时指定文件路径字符串
public String getName() :获得文件或文件夹名称
public long length() :
获得文件大小,单位:字节
如果文件不存在,则返回0
只能获得普通文件的大小,不能获得文件夹的大小
File getParentFile() :获得父路径文件对象
2. File类与判断相关的方法
boolean exists();
判断文件或文件夹是否存在,存在返回true,否则false
boolean isDirectory();
判断是否是文件夹,是返回true,否则false
如果文件夹不存在,则返回false
boolean isFile();
判断是否是普通文件,是返回true,否则false
如果文件夹存在,则返回false
3. File类与创建文件和文件夹相关的方法
boolean createNewFile();
创建文件,只能创建普通文件,不能创建文件夹
创建成功返回true,失败返回false
如果文件已经存在,则什么也不发生,返回false
boolean mkdir(); ==> make directory
创建单级文件夹,只能创建文件夹,不能创建普通文件
创建成功返回true,否则false
如果文件夹已经存在,则什么也不发生,返回false
boolean mkdirs();
创建多级文件夹,只能创建文件夹,不能创建普通文件
创建成功返回true,否则false
如果文件夹已经存在,则什么也不发生,返回false
4. File类与删除文件和文件夹相关的方法
boolean delete();
删除文件,删除成功返回true,否则false
如果是文件夹,只能删除空文件夹。
5. 能够掌握File目录的遍历
File类与目录遍历相关的方法
* String[] list();
* File[] listFiles();
* 获得当前文件夹下所有文件(子文件夹和子文件)
File类两个常见的静态成员变量
static String pathSeparator
* 与系统有关的路径分隔符,为了方便,它被表示为一个字符串。
* 不同的操作系统,路径分隔符不一样。
* mac系统: :
* windows系统: ;
static String separator
* 与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串。
* 不同的操作系统,名称分隔符不一样。
* mac和linux系统: /
* windows系统: \
IO流的作用
1. 为什么要学习IO流
目前数据使用集合和数组,集合或数组保存在内存中的,内存是临时性存储,
一旦电脑断电或程序重新启动,数据就没有了。
如果需要保证数据永久存储,就希望将数据存储到硬盘的文件中。
通过IO流我们就可以将数据保存到文件中,也可以从文件中读取数据到程序中。
2. IO流的作用
1. 将内存中的数据保存到文件中
2. 将文件中数据读取到内存中
3. 什么是IO
Input:输入:数据从文件到内存中
Output:输出:数据从内存到文件中
4. 学习IO流的目的:实现数据持久化操作。
IO流的分类
按数据类型分
字节流:以字节为单位进行读写数据
字符流:以字符为单位进行读写数据
按数据流向分
输入流
输出流
字节输出流:以字节为单位输出数据到文件中
字节输入流:以字节为单位从文件中读取数据到内存中
字符输入流:以字符为单位从文件中读取数据到内存中
字符输出流:以字符为单位输出数据到文件中
掌握OutputStream类的作用和方法
1. OutputStream类概述
Output:输出
Stream:字节流
字节输出流,该类是一个抽象类,是所有字节输出流的父类
作用:以字节为单位输出数据到文件中
2. OutputStream类常用方法
void close():关闭流释放资源
void write(byte[] b)
输出一个字节数组到文件中
void write(byte[] b, int off, int len)
输出字节数组的一部分内容到文件中
off:数组起始索引
len:要输出的字节个数
void write(int b) 输出一个字节到文件中
3. OutputStream类常用子类
FileOutputStream(重点)
BufferedOutputStream
ObjectOutputStream
PrintStream
FileOutputStream类向文件输出字节
1. FileOutputStream类概述
继承OutputStream,以字节为单位输出数据。
2. FileOutputStream类常用构造方法
FileOutputStream(String pathname);
根据文件路径字符串创建字节输出流对象
如果文件不存在,则会自动创建文件
FileOutputStream(File file);
根据文件对象创建字节输出流对象
如果文件不存在,则会自动创建文件
3. FileOutputStream类使用步骤
创建输出流对象
输出文本
关闭流对象
使用FileOutputStream类向文件输出字节数组
OutputStream类与写出字节数组相关的方法
void write(byte[] b)
输出一个字节数组到文件中
void write(byte[] b, int off, int len)
输出字节数组的一部分内容到文件中
off:数组起始索引
len:要输出的字节个数
使用FileOutputStream实现追加写出数据
1. FileOutputStream类与追加写出数据相关的构造方法
FileOutputStream(File file, boolean append)
FileOutputStream(String path, boolean append)
根据文件路径字符串或文件对象创建字节输出流对象
append:true 代表追加输出数据
2. 如何实现换行输出
需要输出一个换行符
\r mac和linux
\n unix
\r\n windows 以后使用该换行符即可
理解IO流使用的注意事项
1. java.io.FileNotFoundException: /Users/pkxing/Documents/aa (Is a directory)
* 创建流关联目标文件时不能关联文件夹,必须是普通文件
2. 创建文件或清空文件内容发生在构造方法中,不是write方法中
3. java.io.IOException: Stream Closed
流一旦关闭就不能再读写数据
理解缓冲流的原理
1. 缓冲流的分类
字节缓冲流
字节缓冲输出流:BufferedOutputStream 继承 OutputStream
字节缓冲输入流:BufferedInputStream 继承 InputStream
字符缓冲流
字符缓冲输入流:BufferedReader 继承 Reader
字符缓冲输出流:BufferedWriter 继承 Writer
2. 缓冲流的原理
内部使用数组临时存储多个数据,当缓冲区数组满了或调用了close或调用了flush方法,
才会一次性调用底层资源将缓冲区数组的数据输出目标文件中。
目的为了减少底层资源的调用次数,从而提高读写速度。
使用字节缓冲输出流BufferedOutputStream输出数据
1. BufferedOutputStream和FileOutputStream使用的区别
BufferedOutputStream继承OutputStream
BufferedOutputStream和FileOutputStream使用的区别在于构造方法不一样,其他完全一致。
2. BufferedOutputStream类常用构造方法
FileOutputStream(String pathname)
FileOutputStream(File file)
BufferedOutputStream(OutputStream out)
* 根据字节输出流对象创建字节缓冲输出流
* 目前可以传递的子类对象:FileOutputStream
3. BufferedOutputStream常用方法
write:输出一个字节,字节数组,字节数组的一部分
public static void main(String[] args)throws Exception{
// 1. 创建字节输出流对象:非缓冲流(FileOutputStream)
FileOutputStream fos = new FileOutputStream("b.txt");
// 2. 创建字节缓冲输出流对象:传递fos
BufferedOutputStream bos = new BufferedOutputStream(fos);
// 3. 输出一个字节
bos.write(97);
// 输出一个字节数组
bos.write("你好".getBytes());
// 4. 关闭流释放资源
bos.close();
}
使用字节输入缓冲流BufferedInputStream读取数据
1. BufferedInputStream和FileInputStream使用的区别
BufferedInputStream继承InputStream
BufferedInputStream和FileInputStream使用的区别在于构造方法不一致。
2. BufferedInputStream类常用构造方法
BufferedInputStream(InputStream in)
* 根据字节输入流创建字节缓冲输入流对象
* 目前可以传递的子类对象:FileInputStream
3. BufferedInputStream类常用方法
* read:读一个字节,一个字节数组
小结:
BufferedInputStream流使用步骤
1. 创建字节输入流关联目标文件:FileInputStream
2. 根据字节输入流创建字节输入缓冲流:BufferedInputStream
3. 调用字节缓冲输入流的read方法读取数据
4. 调用字节缓冲输入流的close方法关闭流释放资源
public static void readByteArray()throws Exception{
// 1. 创建字节缓冲输入流对象
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("b.txt"));
// byte[] buf = new byte[8192];
// 2. 定义变量接收实际读取到的字节个数
int len = -1;
// 3. 定义字节数组:用来存储读取到的字节数
byte[] buf = new byte[1024];
// 4. 循环读取数据
while((len = bis.read(buf)) != -1){
System.out.println(new String(buf,0,len));
}
// 5. 关闭流释放资源
bis.close();
}
掌握字符缓冲输出流BufferedWriter类特有的方法
1. FileWriter和BufferedWriter使用的区别
构造方法不一样,其他完全相同
2. BufferedWriter类构造方法
继承Writer,字符缓冲输出流:以字符为单位输出数据
BufferedWriter(Writer writer)
* 目前可以传递的子类对象:FileWriter
3. BufferedWriter特有方法
* void newLine():输出一个换行符
public static void main(String[] args) throws Exception {
// 创建字符缓冲输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("c.txt",true));
bw.write("你好");// 输出数据
bw.newLine();// 输出换行符
bw.close();// 关闭流释放资源
}
掌握字符缓冲输入流BufferedReader类特有的方法
1. FileReader和BufferedReader使用的区别
构造方法不同,其他都一样
2. BufferedReader类构造方法
BufferedReader继承Reader 字符缓冲输入流,以字符为单位读取数据
BufferedReader(Reader reader)
* 目前可以传递的子类对象:FileReader
3. BufferedReader特有方法
String readLine(); 读取一行数据,读到文件末尾返回null
能够说出FileReader和BufferedReader读取字符乱码的原因
1. 字符流读取字符乱码的原因?
* 因为文本在存储时使用的码表和读取时使用的码表不一致造成的。
* 编码和解码使用的码表不一致
2. 如何解决乱码问题?
* 编码和解码使用相同的码表
使用转换流:InputStreamReader读取字符数据保证不乱码
1. InputStreamReader概述
继承Reader,本质字符流,以字符为单位读取数据
InputStreamReader 是字节流通向字符流的桥梁:字节转换字符
2. InputStreamReader类的构造方法
InputStreamReader(InputStream in)
* 根据字节输入流创建字符转换输入流,默认码表:utf-8
* 目前可以字节输入流有: FileInputStream和BufferedInputStream
InputStreamReader(InputStream in, String charsetName)
* 根据字节输入流创建字符转换输入流
* 目前可以字节输入流有: FileInputStream和BufferedInputStream
* charsetName:字符集名称(编码表名称) 常用的编码表名:gbk和utf8
小结:
InputStreamReader流读取数据的过程
1. 先字节输入流FileInputStream从目标文件中读取数据,读到的是一堆二进制数据
2. 将读取到的二进制数据交给字符转换流InputStreamReader查询指定的码表:将二进制数字转换为字符
字节流不会查询码表,只能字符流才会查询码表。
使用转换流:OutputStreamWriter输出字符数据
1. OutputStreamWriter概述
继承Writer 本质字符输出流,以字符为单位输出数据
OutputStreamWriter 是字符流通向字节流的桥梁:字符转字节
OutputStreamWriter和FileWriter,BufferedWriter的区别在于可以使用指定的码表输出数据。
2. OutputStreamWriter类的构造方法
OutputStreamWriter(OutputStream out,String charsetName)
* 根据字节输出流创建字符转换输出流
* charsetName:指定编码表名称:gbk或utf8
小结:
OutputStreamWriter流输出数据的过程:
1. 先由字符转换输出流OutputStreamWriter将字符查询指定的码表得到二进制数据
2. 然后将二进制数字交给字节输出流FileOutputStream,由字节输出流将二进制数据输出到目标文件中
掌握对象序列化和反序列化的概念
1. 对象序列化和反序列化的概念
对象序列化:将自定义对象以流的形式保存到文件中的过程
对象反序列化:将文件中的对象数据以流的形式读取出来的过程
2. 实现对象序列化和反序列化相关的类
ObjectOutputStream:实现对象序列化操作:保存对象到文件中
ObjectInputStream:实现对象反序列化操作:读取对象到内存中
使用对象输出流将对象保存到文件中:实现对象序列化操作
1. ObjectOutputStream构造方法
ObjectOutputStream(OutputStream out)
* 根据字节输出流创建对象输出流
* 目前可以传递的字节输出流:FileOutputStream和BufferedOutputStream
2. ObjectOutputStream类常用方法
void writeObject(Object obj)
* 将对象保存到流关联的目标文件中
3. ObjectOutputStream流的使用步骤
1. 创建字节输出流关联目标文件:FileOutputStream
2. 根据字节输出流创建对象输出流:ObjectOutputStream
3. 创建自定义对象
4. 调用对象输出流的writeObject方法传递自定义对象:保存对象
5. 关闭流释放资源
4. java.io.NotSerializableException:
com.itheima._09对象序列化流.Student
原因:对象没有序列化的能力,需要实现了Serializable接口的对象才能实现序列化操作。
5. Serializable接口概述
* 该接口称为标记性接口,标记类的对象具有序列化的资格。
使用对象输入流从文件中读取对象:实现对象反序列化操作
1. ObjectInputStream构造方法
作用:实现对象反序列化操作
ObjectInputStream(InputStream in)
根据字节输入流创建对象输入流
可以传递的子类对象:FileInputStream或BufferedOutputStream
2. ObjectInputStream类常用方法
Object readObject();
从流关联的目标文件中读取一个自定义对象
3. ObjectInputStream流的使用步骤
1. 创建字节输入流关联目标文件:FileInputStream
2. 根据字节输入流创建对象输入流:ObjectInputStream
3. 调用对象输入流的readObject方法读取对象
4. 关闭流释放资源
掌握transient关键字的作用
1. transient关键字的作用
transient:短暂,瞬时 反义词:持久化
作用:用来修饰成员变量,能够保证该成员变量的值不会被序列化到文件中。
2. transient使用格式
修饰符 transient 数据类型 变量名;
3. 须知
对象序列化只会序列化对象自己的数据,属于类的数据不会被序列化到文件中,比如静态成员变量
理解序列号冲突的原因以及解决方案
1. 序列号冲突的原因:
保存对象时使用的序列号和读取对象时使用的序列号不一致导致的
2. 如何解决序列号冲突:
自定义序列号,让序列号的值为一个固定值,不能随机产生。
定义序列号的格式: private static final long serialVersionUID = 1L;
一旦类实现了Serializable接口,每次类重新编译都会随机产生一个长整型数字(称为序列号),记录在class文件中
可以将序列号理解为类的唯一标识
能够将集合序列化到文件中
1. 将存有多个自定义对象的集合序列化操作,保存到list.txt文件中。
2. 反序列化list.txt ,并遍历集合,打印对象信息。
小结:
集合序列化到文件中的注意事项:集合中对象也需要实现Serializable接口
能够使用打印流打印数据
1. 打印流分类
字节打印流:PrintStream
字符打印流:PrintWriter
2. 打印流的特点
没有输入,只有输出
能够方便直接原样输出各种数据类型的值
3. PrintStream类使用
PrintStream(String fileName)
根据目标文件创建字节打印流
常用方法
print(数据类型 变量名)
println(数据类型 变量名)
改变打印流流向
PrintStream ps = new PrintStream("ps.txt");
// 先获得与控制台关联的打印流对象
// name = jack
PrintStream consolePs = System.out;
// 将与控制台关联的打印流流向改变到文件中
// name = rose
System.setOut(ps);
System.setOut(consolePs);// 设置回来