File对象
File对象本质是一个文件或文件夹,用于写入和读取文件内容
注意:对于相对路径而言,在单元测试方法中的File是相对于Module,在main中的File是相对于Project
构造器
-
File(String pathname)
javaFile file1 = new File("D:\\workspace"); // 对应一个文件夹 File file2 = new File("D:\\workspace\test.txt"); // 对应一个文件
-
File(String parent, String child)
javaFile file = new File("D:\\workspace", "test.txt"); // 第一个参数是文件夹,第二个参数可以是文件/文件夹
-
File(File parent, String child)
javaFile file1 = new File("D:\\workspace"); File file2 = new File(file1, "test.txt"); // 第一个参数传入一个File对象,且这个对象必须是个文件夹
常用方法
获取文件信息
getName()
:获取文件名称gePath()
:获取相对路径getAbsolutePath()
:获取文件绝对路径File getAbsoluteFile()
:获取绝对路径表示的文件getParent()
:获取上层目录路径length()
:获取文件所占的字节lastModified()
:获取文件最后修改的时间(毫秒数)exists()
:判断文件或目录是否存在isDirectory()
:是否是一个目录isFile()
:是否是一个文件canRead()
:是否可读canWrite()
:是否可写isHidden()
:是否隐藏
遍历文件内部
String[] list()
:返回目录中最外层的所有子目录及子文件File[] listFiles()
:返回目录中最外层的所有子目录及子文件
操作文件
-
renameTo(File)
:重命名(文件移动)
前提:源文件必须存在,目标文件必须不存在,且目标文件所在文件夹必须存在javaFile file1 = new File("hello.txt"); // 假设hello.txt存在 File file2 = new File("workspace", "world.txt"); // 假设workspace存在,world.txt不存在 Boolean isSuccess = file1.renameTo(file2); // 是否移动成功 System.out.println(isSuccess); // 是否成功
-
createNewFile()
:创建文件,若文件存在,则返回falsejavaFile file = new File("workspace/hello.txt"); try { System.out.println(file.createNewFile()); // 不存在返回true,文件已存在返回false } catch(IOException e) { e.printStackTrace(); }
-
delete()
:删除文件或目录,若文件/目录不存在,返回false
说明:
① 对于目录而言,只能删除空目录
② 删除不走回收站 -
mkdir()
:创建一个目录,如果当前目录的上层目录不存在,则创建失败java// 前提:只有workspace目录存在 File file = new File("workspace/test.txt"); file.mkdir(); // 创建成功 File file = new File("workspace/a/test.txt"); // a目录和test.txt不存在 file.mkdir(); // 创建失败
-
mkdirs()
:创建多级目录,如果当前目录的上层目录也不存在,一并创建java// 前提:只有workspace目录存在 File file = new File("workspace/a/test.txt"); // a目录和test.txt不存在 file.mkdirs(); // 创建成功(a目录和test.txt都被创建)
IO流
- 按流向划分:输入流、输出流
- 按操作数据单位划分:字节流、字符流
- 按IO流的角色划分 :节点流、处理流
IO流的基础类
抽象基类 | 文件流(节点流) | 缓冲流(处理流) | 转换流(处理流) | 数据流(处理流) | 对象流(处理流) |
---|---|---|---|---|---|
InputStream(字节流输入流) | FileInputStream | BufferedInputStream | InputStreamReader | DataInputStream | ObjectInputStream |
ouputStream(字节输出流) | FileOutputStream | BufferedOutputStream | OutputStreamWriter | DataOutputStream | ObjectOutputStream |
Reader(字符输入流) | FileReader | BufferedReader | |||
Writer(字符输出流) | FileWriter | BufferedWriter | |||
PrintStream(打印流) |
说明
① 字符流一般用于读取txt文件,字节流一般用于读取mp3、mp4、jpg等文件
② 字节流 可以用于txt文件的复制,但是用于读取txt文件可能会出现乱码(如果遇到汉字,一个汉字占3个字节,可能读不完整)
③ 缓冲流 可以提高文件的读写效率(相当于在文件和内存中间架了一层8kb的缓存区,先从文件中读取到缓存中,最后再一并读入到内存中)
④ 输出流中的flush()
方法,可以手动将数据立即写入到磁盘中
⑤ 转换流 可以将字节流转换为字符流,或者将字符流转换为字节流
⑥ 数据流 只可以读写基本数据类型、String类型数据
⑦ 对象流既可以读写基本数据类型、String类型数据,又可以读写引用类型数据
案例1:将磁盘中的文本文件读入内存中,并打印文件内容(使用字符输入流 FileReader)
java
File file = new File("hello.txt");
FileReader fr = null;
try {
fr = new FileReader(file);
char[] cBuffer = new char[5]; // 用于存储批量读出来的字符
int len; // 用于存储本次读取出的长度
// 开始读入
while((len = fr.read(cBuffer)) != -1) {
// 遍历本次所有读出的字符
for(int i = 0; i < len; i++) {
System.out.println(cBuffer[i]);
}
}
} catch(IOException e) {
e.printStackTrace();
} finally {
// 关闭字符输入流
try {
if (fr != null) {
fr.close();
}
} catch(IOException e) {
e.printStackTrace();
}
}
案例2:将内存中的文本数据写入到磁盘文件中(使用字符输出流FileWriter)
java
FileWriter fw = null;
try {
File file = new File("world.txt"); // 与目标文件做映射
fw = new FileWriter(file); // 覆盖原有文件内容
// fw = new FileWriter(file, true); // 在原有文件基础上,追加内容
// 开始写入
fw.write("这是写入的第一行内容...\n");
fw.write("这是写入的第二行内容...\n");
fw.write("这是写入的第三行内容...\n");
System.out.println("写入成功");
} catch(IOException e) {
e.printStackTrace();
} finally {
// 关闭字符输出流
try {
if (fw != null) {
fw.close();
}
} catch(IOException e) {
e.printStackTrace();
}
}
案例3:复制某个文本文件中的内容到新文件中(使用节点流)
java
FileReader fr = null;
FileWriter fw = null;
try {
File srcFile = new File("test.txt"); // 映射源文件
File destFile = new File("test_copy.txt"); // 映射目标文件
fr = new FileReader(srcFile);
fw = new FileWriter(destFile);
char[] cBuffer = new char[5]; // 存储每次读取出来的字符
int len; // 记录每次读取出的字符长度
// 开始读取
while((len = fr.read(cBuffer)) != -1) {
// 开始写入
fw.write(cBuffer, 0, len); // 写入cBuffer中从下标0开始的len长度数据
}
System.out.println("复制成功");
} catch(IOException e) {
e.printStackTrace();
} finally {
// 关闭输入流、输出流
try {
if (fr != null) fr.close();
} catch(IOException e) {
e.printStackTrace();
}
try {
if (fw != null) fw.close();
} catch(IOException e) {
e.printStackTrace();
}
}
案例4:复制jpg文件(使用字节流)
java
FileInputStream fis = null;
FileOutputStream fos = null;
try {
File srcFile = new File("workspace", "screen.jpg");
File destFile = new File("workspace", "screen_copy.jpg");
fis = new FileInputStream(srcFile);
fos = new FileOutputStream(destFile);
byte[] bBuffer = new byte[1024]; // 存储每次读取出来的字节
int len; // 记录每次读取出来字节的长度
// 开始读取
while((len = fis.read(bBuffer)) != -1) {
// 开始写入
fos.write(bBuffer, 0, len);
}
System.out.println("复制成功");
} catch(IOException e) {
e.printStackTrace();
} finally {
// 关闭流
try {
if (fis != null) fis.close();
} catch(IOException e) {
e.printStackTrace();
}
try {
if (fos != null) fos.close();
} catch(IOException e) {
e.printStackTrace();
}
}
案例5:复制jpg文件(使用字节缓冲流)
说明:关闭处理流会自动关闭内层流
java
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
File srcFile = new File("workspace", "screen.jpg");
File destFile = new File("workspace", "screen_copy.jpg");
FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
bis = new BufferedInputStream(fis); // 将输入流用处理流包裹
bos = new BufferedOutputStream(fos); // 将输出流用处理流包裹
byte[] bBuffer = new byte[1024];
int len;
// 使用输入的处理流读取
while((len = bis.read(bBuffer)) != -1) {
// 使用输出的处理流写入
bos.write(bBuffer, 0, len);
}
System.out.println("复制成功");
} catch(IOException e) {
e.printStackTrace();
} finally {
// 关闭处理流
try {
if (bis != null) bis.close();
} catch(IOException e) {
e.printStackTrace();
}
try {
if (bos != null) bos.close();
} catch(IOException e) {
e.printStackTrace();
}
}
案例6:复制文本文件(使用字符缓冲流)
说明:BufferReader
增加了readLine()
方法,可以一次性读取一行数据,但是换行不能读出来
java
BufferedReader br = null;
BufferedWriter bw = null;
try {
br = new BufferedReader(new FileReader(new File("workspace", "hello.txt"))); // 包裹字符输入流
bw = new BufferedWriter(new FileWriter(new File("workspace", "hello_copy.txt"))); // 包裹字符输出流
String data = null; // 存储本次读取出的一行数据
while((data = br.readLine()) != null) {
bw.write(data);
bw.newLine(); // 换行
}
System.out.println("复制成功");
} catch(IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null) br.close();
} catch(IOException e) {
e.printStackTrace();
}
try {
if (bw != null) bw.close();
} catch(IOException e) {
e.printStackTrace();
}
}
案例7:将GBK类型的文件转为UTF-8类型的文件(使用转换流)
java
InputStreamReader isr = null;
OutputStreamWriter osw = null;
try {
File srcFile = new File("workspace", "hello_GBK.txt");
File destFile = new File("workspace", "hello_UTF8.txt");
isr = new InputStreamReader(new FileInputStream(srcFile), "GBK");
osw = new OutputStreamWriter(new FileOutputStream(destFile), "UTF-8");
char[] cBuffer = new char[5];
int len;
while((len = isr.read(cBuffer)) != -1) {
String s = new String(cBuffer, 0, len);
osw.write(s);
}
System.out.println("转换成功");
} catch(IOException e) {
e.printStackTrace();
} finally {
try {
if (isr != null) isr.close();
} catch(IOException e) {
e.printStackTrace();
}
try {
if (osw!= null) osw.close();
} catch(IOException e) {
e.printStackTrace();
}
}
案例8:将Java对象存储在本地文件中,并从本地文件中把Java对象读取到内存中(使用对象流)
对象的序列化机制 :允许把内存中的Java对象转换成二进制流,从而允许把这种二进制流永久的保存在磁盘上,或者通过网络将这种二进制流传输到另一个网络节点,当其他程序获取到了这种二进制流,就可以恢复成原来的Java对象
序列化 :将Java对象转成二进制流的过程(ObjectOutputStream)
反序列化:将二进制流恢复成Java对象的过程(ObjectInputStream)
-
声明Person类和Account类
注意:
① 自定义的类必须实现Serializable接口才能被序列化,并且需要声明static final long serialVersionUID
(serialVersionUID是用于标识类的,如果不声明serialVersionUID,则当类改变时,serialVersionUID会自动改变)
② 自定义类中的各个属性也必须是可序列化的,比如本例中的Account
③ 类中的属性如果加上transient(瞬时的)
或者static(属于类,跟对象无关)
修饰,则这些属性不会被序列化,会以默认值保存到文件中javapublic class Person implements Serializable{ private static final long serialVersionUID = 1L; private String name; private int age; private Account account; public Person() {} public Person(String name, int age, Account account) { this.name = name; this.age = age; this.account = account; } // ... setter、getter、toString等方法省略 } class Account implements Serializable{ private static final long serialVersionUID = 2L; private double balance; public Account() {} public Account(double balance) { this.balance = balance; } // ... setter、getter、toString等方法省略 }
-
将Java对象存储在本地文件中(序列化过程)
javaObjectOutputStream oos = null; try { // 创建文件对象和对象流 File file = new File("object.dat"); oos = new ObjectOutputStream(new FileOutputStream(file)); // 开始序列化写入 oos.writeObject(new Person("a", 18, new Account(1000))); oos.writeUTF("这是一段字符串"); System.out.println("写入完成"); } catch(IOException e) { e.printStackTrace(); } finally { // 关闭对象流 try { if (oos != null) { oos.close(); } } catch(IOException e) { e.printStackTrace(); } }
-
从本地文件中把Java对象读取到内存中(反序列化过程)
javaObjectInputStream ois = null; try { // 创建文件对象和对象流 File file = new File("object.dat"); ois = new ObjectInputStream(new FileInputStream(file)); // 开始反序列化读入 Person p = (Person)ois.readObject(); System.out.println(p); String s = (String)ois.readUTF(); System.out.println(s); System.out.println("读取完成"); } catch(IOException | ClassNotFoundException e) { e.printStackTrace(); } finally { // 关闭对象流 try { if (ois != null) { ois.close(); } } catch(IOException e) { e.printStackTrace(); } }
标准输入流:System.in
案例:从键盘输入,并转成大写输出
java
BufferedReader br = null;
System.out.print("请输入(输入exit退出程序):");
try {
// 这里使用BufferedReader,可以调用readLine()来读取输入的一整行数据。
// 因为System.in是字节数据,所以需要使用转换流把字节流转换为字符流
br = new BufferedReader(new InputStreamReader(System.in));
String line;
while((line = br.readLine()) != null) {
if (line.equalsIgnoreCase("exit")) {
break;
}
System.out.println(line.toUpperCase());
System.out.print("请输入(输入exit退出程序):");
}
} catch(IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null) {
br.close();
}
} catch(IOException e) {
e.printStackTrace();
}
}
标准输出流:System.out
说明:System.out
默认将内容打印到控制台中
案例:修改System.out默认行为,使用System.out输出到某个txt文件中
java
PrintStream ps = null;
try {
ps = new PrintStream(new FileOutputStream(new File(""test.txt")));
ps.println("这是写入的第一行数据");
ps.println("这是写入的第二行数据");
// 修改System.out的默认输出方式:输出到test.txt中
System.setOut(ps);
System.out.println("这是写入的第三行数据");
} catch(FileNotFoundException e) {
e.printStackTrace();
} finally {
if (ps != null){
ps.close();
}
}