File对象
File对象本质是一个文件或文件夹,用于写入和读取文件内容
注意:对于相对路径而言,在单元测试方法中的File是相对于Module,在main中的File是相对于Project
构造器
File(String pathname)
File file1 = new File("D:\\workspace"); // 对应一个文件夹 File file2 = new File("D:\\workspace\test.txt"); // 对应一个文件
File(String parent, String child)
File file = new File("D:\\workspace", "test.txt"); // 第一个参数是文件夹,第二个参数可以是文件/文件夹
File(File parent, String child)
File 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)
:重命名(文件移动)
前提:源文件必须存在,目标文件必须不存在,且目标文件所在文件夹必须存在File 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()
:创建文件,若文件存在,则返回falseFile file = new File("workspace/hello.txt"); try {System.out.println(file.createNewFile()); // 不存在返回true,文件已存在返回false } catch(IOException e) {e.printStackTrace(); }
delete()
:删除文件或目录,若文件/目录不存在,返回false
说明:
① 对于目录而言,只能删除空目录
② 删除不走回收站mkdir()
:创建一个目录,如果当前目录的上层目录不存在,则创建失败// 前提:只有workspace目录存在 File file = new File("workspace/test.txt"); file.mkdir(); // 创建成功 File file = new File("workspace/a/test.txt"); // a目录和test.txt不存在 file.mkdir(); // 创建失败
mkdirs()
:创建多级目录,如果当前目录的上层目录也不存在,一并创建// 前提:只有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)
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)
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:复制某个文本文件中的内容到新文件中(使用节点流)
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文件(使用字节流)
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文件(使用字节缓冲流)
说明:关闭处理流会自动关闭内层流
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()
方法,可以一次性读取一行数据,但是换行不能读出来
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类型的文件(使用转换流)
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(属于类,跟对象无关)
修饰,则这些属性不会被序列化,会以默认值保存到文件中public 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对象存储在本地文件中(序列化过程)
ObjectOutputStream 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对象读取到内存中(反序列化过程)
ObjectInputStream 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
案例:从键盘输入,并转成大写输出
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文件中
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();}
}