1 File类

java.io.File 类,是文件和目录路径名的抽象表示形式,java把电脑中的文件和文件夹(目录)封装成为一个File类,可以使用File类的方法对文件/文件夹进行操作
一些静态变量

  • String pathSeparatorchar pathSeparatorChar :与系统有关的的路径分隔符,Windows是分号,Linux是冒号
  • String separatorchar separatorChar :与系统有关的下级目录表示符,Windows是\,Linux是/

    注意:路径是不区分大小写的

1.1 构造方法

File(String pathName) 通过将给定路径字符串转换为抽象路径名来创建一个新File类实例

  • 路径可以是以文件结尾,也可以是以文件夹结尾
  • 路径可以是相对路径,也可以是绝对路径
  • 路径可以存在,也可以不存在
  • 创建File对象,只是把字符串路径封装为File对象,不考虑路径的存在性

File(String parent, String child) 根据 parentchild 路径名字符串创建一个新File类实例
File(File parent, String child) 根据父路径和子路径字符串创建一个新File类实例

1.2 功能方法

获取

  • public String getAbsolutePath()
  • public String getPath() 返回路径字符串表示形式(原封不动,既非绝对 ,也非相对)
  • public String getName() 返回此File表示的文件或目录的名称(构造方法中的结尾部分)
  • public long length() 返回此File表示的文件的大小

    • 文件长度以字节为单位
    • 文件夹没有大小属性,所以不可对文件夹使用此方法
    • 若文件不存在,则返回0

      判断

  • public boolean exists() 判断文件或目录是否存在

  • public boolean isDirectory() 判断是否为目录
  • public boolean isFile() 判断是否为文件

    创建删除

  • public boolean createNewFile() 当且仅当具有该文件的名称尚不存在时,创建一个新的空文件

    • 文件不存在,创建文件,返回true
    • 文件存在,不会创建,返回false
  • public boolean delete() 删除此File表示的文件或目录
  • public boolean mkdir() 创建由此File表示的目录(只能创建单级目录)
    • 文件夹不存在,创建文件夹,返回true
    • 文件夹存在,则不会创建,返回false;构造方法中给出的路径若不存在,返回false
  • public boolean mkdirs() 创建由此File表示的目录,包括任何必须但不存在的父目录

    遍历

  • public String[] list() 返回一个表示该File目录中所有子目录或文件的字符串数组

  • public File[] listFiles() 返回一个表示该File目录中所有子目录或文件的File数组

    如果构造方法中给出的目录的路径不存在,或者构造方法给出的路径不是一个目录,都会抛出空指针异常

1.3 Filter

File类中有两个与 listFiles() 重载的方法

FileFilter

public File[] listFiles(FileFilter filter)
java.io.FileFilter 接口,用于过滤File对象
其中的抽象方法

  • boolean accept(File pathname) 测试指定抽象路径名是否包含在某个路径列表中中,如果返回true,则将文件对象保存在文件数组中 ```java //需求:找到文件目录下所有java文件 import java.io.File; import java.io.FileFilter;

public class Demo03 { public static void main(String[] args) { File file = new File(“src”); getAllFiles(file); } public static void getAllFiles(File dir){ File[] files = dir.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { return pathname.isDirectory() || pathname.getName().toLowerCase().endsWith(“.java”); } }); for (File file : files) { if(file.isDirectory()){ getAllFiles(file); }else{ System.out.println(file); } } } }

  1. <a name="2ImoT"></a>
  2. ### FilenameFilter
  3. `public File[] listFiles(FilenameFilter filter)`<br />`java.io.FilenameFilter` 接口,用于过滤文件名<br />**其中的抽象方法**
  4. - `boolean accept(File dir, String name)` 测试指定文件是否应该包含在某一文件列表中
  5. ```java
  6. //需求:找到文件目录下所有的java文件
  7. package File;
  8. import java.io.File;
  9. public class Demo04 {
  10. public static void main(String[] args) {
  11. File file = new File("src");
  12. getAllFiles(file);
  13. }
  14. private static void getAllFiles(File dir) {
  15. File[] files = dir.listFiles((File d, String pathname) -> {
  16. return new File(d, pathname).isDirectory() || pathname.toLowerCase().endsWith(".java");
  17. });
  18. for (File file : files) {
  19. if (file.isDirectory()) {
  20. getAllFiles(file);
  21. } else {
  22. System.out.println(file);
  23. }
  24. }
  25. }
  26. }

2 IO

2.1 概述

  • 输入 :把硬盘中的数据, 读取 到内存中使用
  • 输出 :把内存中的数据, 写入 到硬盘中保存

顶级父类

输入流 输出流
字节流 InputStream OutputStream
字符流 Reader Writer

2.2 字节流

字节输出流OutputStream

1.常用方法

  • void close() 关闭此输出流并释放与此流有关的所有系统资源
  • void flush() 刷新此输出流并强制写出所有缓冲的输出字节
  • void write(byte[] b) 将byte数组写入此输出流
    • 如果第一个字节是正数(0-127),则查询ASCII表
    • 如果第一个字节是负数,则将其与之后相邻的字节组成一个中文显示,查询系统默认码表(GBK)
  • void write(byte[] b, int off, int len) 将b中从off开始的len个字节写入此输出流
  • void write(int b) 将指定的字节写入此输出流
    • 如果写入数字在0-127之间,则查询ASCII表将其转化为字符
    • 否则,查询系统默认码表(中文系统,GBK)

2.FileOutputStream
构造方法

  • FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的输出文件流
  • FileOutputStream(File file) 同上
  • FileOutputStream(String name, boolean append) 是否追加写
  • FileOutputStream(File file, boolean append)是否追加写

    字节输入流InputStream

    1.常用方法

  • void close()

  • int available() 返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的字节数
  • int read() 读取一个字节,每读取一个则将游标向后移一位,读取到文件末尾则返回-1
  • int read(byte[] b) 将读取的字节存在缓冲数组b中
  • int read(byte[] b, int off, int len)

2.FileInputStream
构造方法

  • FileInputStream(String name)
  • FileInputStream(File file)

    2.3 字符流

    使用字节流读取中文字符时可能会产生显示不完全(乱码)问题 ,这是因为按照GBK编码两个字节组成一个中文字符,但是按照UTF-8编码是三个字节组成一个中文字符。

    字符输入流Reader

    1.常用方法

  • public void close()

  • public int read() 从输入流读取一个字符
  • public int read(char[] cbuf) 从输入流中读取一些字符,并将其存储在cbuf数组中

2.FileReader类
构造方法

  • FileReader(File file)
  • FileReader(String fileName)
  • FileReader(FileDescriptor fd)

    字符输出流Writer

    1.常用方法

  • void write(int c) 写入单个字符(写入的是内存缓冲区,是一个字符转换为字节的过程,必须flush才能写入文件)

  • void write(char[] cbuf) 写入字符数组
  • abstract void write(char[] int off, int len) 写入字符数组的某一部分
  • void write(String str) 写入字符串
  • void write(String str, int off, int len) 写入字符串的某一部分
  • void flush() 刷新该流的缓冲,将字节写入文件
  • void close() 关闭此流,但要先刷新它

2.FileWriter类
构造方法

  • FileWriter(File file)
  • FileWriter(String fileName)

3. flush()close()的区别

  • flush 刷新缓冲区,流对象可以继续使用
  • close 先刷新缓冲区,然后释放资源,流对象不可再被使用

    2.4 流对象的异常处理

  • JDK1.7以前,非常麻烦

  • 从JDK1.7开始,在try后面增加一个(),将流对象在其中定义,当try中代码执行完毕后,会自动把流对象释放,而不用再写fianlly ```java package Stream;

import java.io.FileReader; import java.io.IOException;

public class Demo06 { public static void main(String[] args) { try (FileReader fw = new FileReader(“src/Stream/Hello.txt”);) { int c = fw.read(); } catch (IOException e) { e.printStackTrace(); } System.out.println(“Test done.”); } }

  1. <a name="SEY37"></a>
  2. # 2.5 Properties
  3. > 唯一一个与IO流相结合的集合,该类表示了一个持久的属性流,可保存在流中或从流中加载
  4. Properties集合是一个双列集合(继承自Hashtable),key和value默认都是字符串,常用方法有
  5. - `Object setProperty(String key, String value)`
  6. - `String getProperty(String key)`
  7. - `Set<String> stringPropertyNames()`
  8. - `void store(OutputStream out, String comments)` 把集合中的数据持久化写入到硬盘中存储
  9. - `void store(Writer writer, String comments)` 注释 `comments` 不能使用中文
  10. - `void load(InputStream inStream)` 把硬盘中保存的数据读取到内存中使用
  11. - `void load(Reader reader)`
  12. <a name="pj6Hp"></a>
  13. # 2.6 缓冲流
  14. 给基本的输入输出流增加一个缓冲区,提高读写效率
  15. <a name="kILHZ"></a>
  16. ### BufferedOutputStream
  17. 构造方法
  18. - `BufferedOutputStream(OutputStream out)`
  19. - `BufferedOutputStream(OutputStream out, int size)`
  20. ```java
  21. import java.io.BufferedOutputStream;
  22. import java.io.FileOutputStream;
  23. import java.io.IOException;
  24. import java.nio.charset.StandardCharsets;
  25. public class Demo09 {
  26. public static void main(String[] args) throws IOException {
  27. FileOutputStream fos = new FileOutputStream("src/Stream/buffered.txt");
  28. BufferedOutputStream bos = new BufferedOutputStream(fos);
  29. bos.write("我是写入缓冲区的字符串".getBytes(StandardCharsets.UTF_8));
  30. bos.flush();
  31. bos.close();
  32. }
  33. }

BufferedInputStream

构造方法

  • BufferedIutputStream(InputStream in)
  • BufferedIutputStream(InputStream in, int size) ```java import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException;

public class Demo10 { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream(“src/Stream/buffered01.txt”); BufferedInputStream bis = new BufferedInputStream(fis, 2); int len = 0; while((len=bis.read())!=-1){ System.out.print((char)len);; } bis.close(); } }

  1. <a name="UQLRN"></a>
  2. ### BufferedWriter
  3. 构造方法
  4. - `BufferedWriter(Writer out)`
  5. - `BufferedWriter(Writer out, int size)`
  6. 特有方法
  7. - `void newline()` 写入换行符
  8. <a name="sZSqy"></a>
  9. ### BufferedReader
  10. 构造方法
  11. - `BufferedReader(Reader reader)`
  12. - `BufferedReader(Reader reader, int size)`
  13. 特有方法
  14. - `String readLine()` 读取一行文本内容,若读到文本结尾,则返回null
  15. <a name="BX2U8"></a>
  16. # 3 转换流
  17. <a name="IuvAH"></a>
  18. ## 3.1 常见的编码方式
  19. - ASCII
  20. - GBxxx
  21. - GB2312
  22. - GBK
  23. - GB18030
  24. - Unicode
  25. - UTF-8
  26. - UTF-16
  27. - UTF-32
  28. <a name="BmA5b"></a>
  29. ## 3.2 转换流的方式
  30. <a name="LtB8a"></a>
  31. ### InputStreamReader
  32. 是字节流通向字符流的桥梁,可以指定charset对字节流进行解码
  33. - `InputStreamReader(InputStream in)`
  34. - `InputStreamReader(InputStream in, String charSetName)`
  35. ```java
  36. import java.io.FileInputStream;
  37. import java.io.IOException;
  38. import java.io.InputStreamReader;
  39. public class Demo12 {
  40. public static void main(String[] args) throws IOException {
  41. InputStreamReader isr = new InputStreamReader(new FileInputStream("src/Stream/gbk.txt"),"gbk");
  42. int len = 0;
  43. while((len=isr.read())!=-1){
  44. System.out.print((char)len);
  45. }
  46. isr.close();
  47. }
  48. }

OutputStreamWriter

FileWriter 只能使用IDE默认码表写入,而 OutputStreamWriter 则可以使用指定charset进行写入

  • OutputStreamWriter(OutputStream out) 创建使用默认编码的输出流
  • OutputStreamWriter(OutputStream out, String charSetName) 创建使用指定编码的输出流 ```java import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter;

public class Demo11 { public static void main(String[] args) throws IOException { write_gbk(); }

  1. private static void write_gbk() throws IOException {
  2. OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("src/Stream/gbk.txt"),"gbk");
  3. osw.write("你好,世界");
  4. osw.flush();
  5. }

}

  1. <a name="shi"></a>
  2. ### 练习:实现文件转码
  3. ```java
  4. package Stream;
  5. import java.io.*;
  6. public class Demo13 {
  7. public static void main(String[] args) throws IOException {
  8. String fileName = "src/Stream/gbk.txt";
  9. convert_to_utf8(fileName);
  10. }
  11. private static void convert_to_utf8(String fileName) throws IOException {
  12. InputStreamReader isr = new InputStreamReader(new FileInputStream(fileName), "gbk");
  13. OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(fileName.replace("gbk", "utf8")), "utf8");
  14. int len = 0;
  15. while ((len = isr.read()) != -1) {
  16. osw.write(len);
  17. }
  18. isr.close();
  19. osw.close();
  20. }
  21. }

3.3 序列化与反序列化

先定义一个Perosn类

  1. package Stream;
  2. import java.io.Serializable;
  3. public class Person implements Serializable {
  4. private String name;
  5. private int age;
  6. @Override
  7. public String toString() {
  8. return "Person{" +
  9. "name='" + name + '\'' +
  10. ", age=" + age +
  11. '}';
  12. }
  13. public String getName() {
  14. return name;
  15. }
  16. public void setName(String name) {
  17. this.name = name;
  18. }
  19. public int getAge() {
  20. return age;
  21. }
  22. public void setAge(int age) {
  23. this.age = age;
  24. }
  25. public Person(String name, int age) {
  26. this.name = name;
  27. this.age = age;
  28. }
  29. }

ObjectOutputStream

对象的序列化流 , 类通过实现 java.io.Serializable 接口以启用其序列化功能,可序列化类的所有子类都是可序列化的,序列化接口没有方法或字段,仅用于标识可序列化的语义
构造方法
ObjectOutputStream(OutputStream out)
特有的成员方法
void writeObject(Object obj)

  1. import java.io.FileOutputStream;
  2. import java.io.IOException;
  3. import java.io.ObjectOutputStream;
  4. public class Demo14 {
  5. private static java.io.OutputStream OutputStream;
  6. public static void main(String[] args) throws IOException {
  7. ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("src/Stream/persons.txt"));
  8. Person p1 = new Person("小石头", 18);
  9. oos.writeObject(p1);
  10. }
  11. }

ObjectInputStream

对象的反序列化流
构造方法
ObjectInputStream(InputStream in)
特有的成员方法
Object readObject()

  1. package Stream;
  2. import java.io.FileInputStream;
  3. import java.io.IOException;
  4. import java.io.ObjectInputStream;
  5. public class Demo15 {
  6. public static void main(String[] args) throws IOException, ClassNotFoundException {
  7. ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src/Stream/persons.txt"));
  8. Object obj = ois.readObject();
  9. System.out.println(obj);
  10. }
  11. }

transient(瞬态)关键字

  • static关键字所修饰的内容优先于对象加载到内存中,所以不能被序列化
  • transient关键字所修饰的内容也不可被序列化,但并不包含static的含义

    InvalidClassException

  • 编译器(javac)会把Person.java文件编译生成Person.class,由于Person类实现了 Serializable 接口,因此会根据类的定义给Person.class添加一个序列号

  • 反序列化时,会使用Person.class文件中的序列号和persons.txt中的序列号做比较,如果一致,则反序列化成功,若不一致,则抛出 InvalidClassException异常

问题产生的原因:每一次给类修改定义,都会重新给类生成一个序列号
解决问题的办法:为类手动指定序列号,使用以下格式
private static final long serialVersionUID = 1L;

序列化集合

当想要序列化多个对象时,可以将对象保存到集合中,对集合进行序列化和反序列化
序列化

  1. import java.io.FileOutputStream;
  2. import java.io.IOException;
  3. import java.io.ObjectOutputStream;
  4. import java.util.ArrayList;
  5. public class Demo16 {
  6. public static void main(String[] args) throws IOException {
  7. ArrayList<Person> list = new ArrayList<>();
  8. ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("src/Stream/persons.txt"));
  9. list.add(new Person("张三", 18));
  10. list.add(new Person("李四", 28));
  11. list.add(new Person("王五", 38));
  12. list.add(new Person("赵六", 48));
  13. oos.writeObject(list);
  14. oos.close();
  15. }
  16. }

反序列化

  1. import java.io.FileInputStream;
  2. import java.io.IOException;
  3. import java.io.ObjectInputStream;
  4. public class Demo17 {
  5. public static void main(String[] args) throws IOException, ClassNotFoundException {
  6. ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src/Stream/persons.txt"));
  7. Object obj = ois.readObject();
  8. System.out.println(obj);
  9. }
  10. }

3.4 打印流PrintStream

1.PrintStream的特点

  • 只能输出数据,不能读取数据
  • 永远不会抛出IO异常
  • 有特有的方法 print println

2.构造方法

  • PrintStream(File file) 输出的目的地是一个文件
  • PrintStream(OutputStream out) 输出目的地是一个字节输出流
  • PrintStream(String fileName) 输出目的地是一个文件路径

3.注意事项

  • 如果使用继承自父类的 write 方法写数据,那么查看数据的时候会查询码表 97->a
  • 如果使用自己特有的方法print/println写数据,则会写入原始数据 97->97
  • 使用 System.setOut(PrintStream out) 方法改变输出语句的目的地为参数传递的打印流的目的地
    1. import java.io.FileNotFoundException;
    2. import java.io.PrintStream;
    3. import java.io.File;
    4. public class Demo18 {
    5. public static void main(String[] args) throws FileNotFoundException {
    6. PrintStream ps = new PrintStream(new File("src/Stream/printstream.txt"));
    7. ps.println("我是爱南开的。");
    8. ps.close();
    9. }
    10. }