Java SE-07-IO流

1. File

  1. 文件和目录是可以通过File封装成对象的

  2. 对于File而言,其封装的并不是一个真正存在的文件,仅仅是一个路径名而已。它可以是存在的,也可以是不存在的。将来是要通过具体的操作把这个路径的内容转换为具体存在的

  3. File常用方法:

    win系统的路径分隔符\要用转义为\\
    
    常用字段:
    // 路径结束的标志
    static String pathSeparator
    // 目录与目录之间的分隔符
    static String separator
    
    常用构造:
    // 通过将给定的路径名字符串转换为抽象路径名来创建新的File实例
    File(String pathname)
    
    // 从父路径名字符串和子路径名字符串创建新的File实例
    File(String parent, String child)
    
    // 从父抽象路径名和子路径名字符串创建新的File实例
    File(File parent, String child)
    
    常用方法:
    // 当且仅当具有该名称的文件尚不存在时,原子地创建一个由该抽象路径名命名的新的空文件
    boolean createNewFile()
    
    // 创建由此抽象路径名命名的目录
    boolean mkdir()
    
    // 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录
    boolean mkdirs()
    
    // 删除由此抽象路径名表示的文件或目录
    // 如果一个目录中有内容,需要先删除目录中的内容,最后才能删除目录
    boolean delete()
    
    // 测试此抽象路径名表示的文件或目录是否存在
    boolean exists()
    
    // 测试此抽象路径名表示的文件是否为目录
    boolean isDirectory()
    
    // 测试此抽象路径名表示的文件是否为普通文件
    boolean isFile()
    
    // 返回文件的长度(单位B)
    long length()
    
    // 返回此抽象路径名的绝对路径名形式
    File getAbsoluteFile()
    
    // 返回此抽象路径名的绝对路径名字符串
    String getAbsolutePath()
    
    // 将此抽象路径名转换为路径名字符串
    String getPath()
    
    // 获取此文件或目录名称
    String getName()
    
    // 返回上一级目录;没有则返回null
    File getParentFile()
    
    // 返回一个字符串数组,命名由此抽象路径名表示的目录中的文件和目录
    String[] list()
    
    // 返回一个抽象路径名数组,表示由该抽象路径名表示的目录中的文件
    File[] listFiles()
    
    // 返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录
    File[] listFiles(FileFilter filter)
    
  4. 递归遍历目录:

    // 递归遍历目录
    public static void tree(File dir) {
        // 获取给定的File目录下所有的文件或目录的File数组
        File[] files = dir.listFiles();
        // 遍历该File数组,得到每一个File对象
        if (files != null) {
            for (File file : files) {
                // 判断该File对象是否是目录
                if (file.isDirectory()) {
                    // 是目录:递归调用
                    System.out.println(file.getAbsolutePath() + ":");
                    tree(file);
                } else {
                    // 不是目录:获取绝对路径输出在控制台
                    System.out.println(file.getAbsolutePath());
                }
            }
        }
    }
    

2. 字节流

  1. 字节流抽象基类:

    1. InputStream:字节输入流所有类的超类
    2. OutputStream:字节输出流所有类的超类
    3. 子类名称都是以其父类名作为子类名的后缀(如FileOutputStream)
  2. InputStream常用方法:

    // 关闭此输入流并释放与流相关联的任何系统资源
    void close()
    
    // 从输入流读取数据的下一个字节
    // 返回的是读取到的内容
    abstract int read()
    
    // 从输入流中读取一些字节数,并将它们存储到缓冲器阵列b
    // 返回读入缓冲区的总字节数,也就是实际的读取字节个数
    int read(byte[] b)
    
    // 从输入流读取最多len个字节的数据到字节数组
    // 返回读入缓冲区的总字节数,也就是实际的读取字节个数
    int read(byte[] b, int off, int len)
    
  3. OutputStream常用方法:

    // 关闭此输出流并释放与此流相关联的任何系统资源
    void close()
    
    // 刷新此输出流并强制任何缓冲的输出字节被写出
    void flush()
    
    // 将指定的字节写入此输出流
    // 一次写一个字节数据
    abstract void write(int b)
    
    // 将b.length字节从指定的字节数组写入此输出流
    // 一次写一个字节数组数据
    void write(byte[] b)
    
    // 从指定的字节数组写入len字节,从偏移量off开始输出到此输出流
    // 一次写一个字节数组的部分数据
    void write(byte[] b, int off, int len)
    
    换行符:
        windows:\r\n
        linux:\n
        mac:\r
    
  4. FileOutputStream常用构造:

    // 创建文件输出流以指定的名称覆盖写入文件
    FileOutputStream(String name)
    
    // 创建文件输出流以指定的名称写入文件
    FileOutputStream(String name, boolean append)
    
    // 创建文件输出流以覆盖写入由指定的File对象表示的文件
    FileOutputStream(File file)
    
    // 创建文件输出流以写入由指定的File对象表示的文件
    FileOutputStream(File file, boolean append)
    
  5. 使用字节输出流写数据的步骤:

    1. 创建字节输出流对象(调用系统功能创建了文件,创建字节输出流对象,让字节输出流对象指向文件)
    2. 调用字节输出流对象的写数据方法
    3. 释放资源(关闭此文件输出流并释放与此流相关联的任何系统资源)
  6. 使用字节输入流读数据的步骤:

    1. 创建字节输入流对象
    2. 调用字节输入流对象的读数据方法
    3. 释放资源
  7. 字节缓冲流:字节缓冲流仅仅提供缓冲区,而真正的读写数据还得依靠基本的字节流对象进行操作

    BufferedInputStream(InputStream in)
    BufferedInputStream(InputStream in, int size)
    
    BufferedOutputStream(OutputStream out)
    BufferedOutputStream(OutputStream out, int size)
    
  8. 复制多级目录:

    // 复制多级目录
    public static void cpa(File src, File dest) throws IOException {
        // 目标文件或路径
        File destFile = new File(dest, src.getName());
        // 判断数据源File是否为目录
        if (src.isDirectory()) {
            // 在目的地下创建和数据源File名称一样的目录
            if (!destFile.exists()) {
                destFile.mkdirs();
            }
            // 遍历获取src目录下的所有文件的File数组,复制每一个File对象
            File[] srcFiles = src.listFiles();
            for (File srcFile : srcFiles) {
                cpa(srcFile, destFile);
            }
        } else {
            // 是文件就复制
            cp(src, destFile);
        }
    }
    
    // 字节流复制文件
    public static void cp(File src, File dest) throws IOException {
        // 根据数据源创建字节输入流对象
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(src));
        // 根据目的地创建字节输出流对象
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dest));
        // 读写数据,复制文件
        byte[] buffer = new byte[1024];
        int len;
        while ((len = bis.read(buffer)) != -1) {
            bos.write(buffer, 0, len);
        }
        // 释放资源
        bos.close();
        bis.close();
    }
    

3. 字符流

  1. 字符流抽象基类:

    1. Reader:字符输入流的抽象类
    2. Writer:字符输出流的抽象类
  2. 字符流写数据时,先写到内存,然后通过flush或close从内存刷新到目标文件中。

  3. 字符流中和编码解码相关的两个类:

    InputStreamReader构造:
    // 创建一个使用默认字符集的InputStreamReader
    InputStreamReader(InputStream in)
    // 创建一个使用指定字符集的InputStreamReader
    InputStreamReader(InputStream in, String charsetName)
    
    InputStreamReader方法:
    // 返回此流使用的字符编码的名称
    String getEncoding()
    
    
    OutputStreamWriter构造:
    // 创建一个使用默认字符编码的OutputStreamWriter
    OutputStreamWriter(OutputStream out)
    // 创建一个使用命名字符集的OutputStreamWriter
    OutputStreamWriter(OutputStream out, String charsetName)
    
    OutputStreamWriter方法:
    // 返回此流使用的字符编码的名称
    String getEncoding()
    
  4. Reader常用方法:

    // 关闭流并释放与之相关联的任何系统资源
    abstract void close()
    
    // 读一个字符
    int read()
    
    // 将字符读入数组
    int read(char[] cbuf)
    
    // 将字符读入数组的一部分
    abstract int read(char[] cbuf, int off, int len)
    
  5. Writer常用方法:

    // 关闭流,先刷新
    abstract void close()
    
    // 刷新流
    abstract void flush()
    
    // 写一个字符
    void write(int c)
    
    // 写入一个字符数组
    void write(char[] cbuf)
    
    // 写入字符数组的一部分
    abstract void write(char[] cbuf, int off, int len)
    
    // 写一个字符串
    void write(String str)
    
    // 写一个字符串的一部分
    void write(String str, int off, int len)
    
  6. 字符缓冲流:

    BufferedReader(Reader in)
    BufferedReader(Reader in, int sz)
    // 读一行文字,不包括换行符,如果流的结尾已经到达,则为null
    String readLine()
    
    
    BufferedWriter(Writer out)
    BufferedWriter(Writer out, int sz)
    // 写一行行分隔符
    void newLine()
    
  7. 字符流复制文本文件(可以复制,但用法错误,复制就用字节流):

    public static void cp(String src, String dest) throws IOException {
        // 根据数据源创建字节输入流对象
        BufferedReader br = new BufferedReader(new FileReader(src));
        // 根据目的地创建字节输出流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter(dest));
        // 读写数据,复制文件
        String line;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        // 释放资源
        bw.close();
        br.close();
    }
    

4. IO流的异常处理

常规手动释放资源:
try{
    可能出现异常的代码;
}catch(异常类名 变量名){
    异常的处理代码;
}finally{
    执行所有清除操作;
}

自动释放资源:
JDK7改进方案*:
try(定义输入流对象;定义输出流对象;){
    可能出现异常的代码;
}catch(异常类名 变量名){
    异常的处理代码;
}

JDK9改进方案:
定义输入流对象;
定义输出流对象;
try(输入流对象名;输出流对象名){
    可能出现异常的代码;
}catch(异常类名 变量名){
    异常的处理代码;
}

5. 标准输入输出流

System类中有两个静态最终成员变量:
// “标准”输入流,BufferedInputStream类型
public static final InputStream in
// “标准”输出流,PrintStream类型
public static final PrintStream out

自己实现键盘录入数据:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
写起来太麻烦,Java就提供了一个类实现键盘录入
Scanner sc = new Scanner(System.in);

输出语句的本质:是一个标准的输出流
PrintStream ps = System.out;
PrintStream类有的方法,System.out都可以使用

6. 打印流

  1. 打印流的特点:

    1. 只负责输出数据,不负责读取数据
    2. 永远不会抛出IOException,但是有可能抛出其他异常
    3. 可以启用自动刷新
      1. PrintStream自动刷新
      2. PrintWriter调用println、printf、format方法可以自动刷新
  2. 字节打印流:PrintStream

    1. PrintStream(String fileName) 使用指定的文件名创建新的打印流,无需自动换行
    2. 使用继承父类的方法写数据:查看的时候会转码
    3. 使用自己的特有方法写数据:查看的数据原样输出
  3. 字符打印流:PrintWriter

    常用构造:
    // 使用指定的文件名创建一个新的PrintWriter,而不需要自动执行行刷新
    PrintWriter(String fileName)
    
    // 创建一个新的PrintWriter
    PrintWriter(Writer out, boolean autoFlush)
        out:字符输出流
        autoFlush:如果为真,则println、printf、format方法将刷新输出缓冲区
    

7. 对象序列化流

  1. 对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象;这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息,字节序列写到文件之后,相当于文件中持久保存了一个对象的信息;反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化

  2. 静态属于类,不属于对象,因此静态不能对象序列化

  3. 序列化时,只对对象的状态进行保存,而不管对象的方法

  4. 当一个对象的成员变量引用其他对象,序列化该对象时也把引用对象进行序列化

  5. 对于JVM可以反序列化对象,它必须是能够找到class文件的类

  6. 一个对象要想被序列化,该对象所属的类必须实现标记接口Serializable,不需要重写任何方法

  7. 如果子类实现Serializable接口而父类未实现时,父类不会被序列化;如果父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口。

  8. 如果一个对象中的某个成员变量的值不想被序列化,可以给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程

  9. 为了保证不同Java编译器实现之间的一致的serialVersionUID值,一个可序列化的类必须声明一个显式的serialVersionUID值

  10. 用对象序列化流序列化了一个对象后,若修改了对象所属的类文件,读取数据时抛出了InvalidClassException异常。其解决方案:

    1. 重新序列化
    2. 在类中添加属性private static final long serialVersionUID
  11. 对象序列化流:ObjectOutputStream

    常用构造:
    // 创建一个写入指定的OutputStream的ObjectOutputStream
    ObjectOutputStream(OutputStream out)
    
    序列化对象的方法:
    // 将指定的对象写入ObjectOutputStream
    void writeObject(Object obj)
    
  12. 对象反序列化流:ObjectInputStream

    JVM可以反序列化的对象必须是能够找到class文件的类
    常用构造:
    // 创建从指定的InputStream读取的ObjectInputStream
    ObjectInputStream(InputStream in)
    
    反序列化对象的方法:
    // 从ObjectInputStream读取一个对象
    Object readObject()
    

8. Commons IO

  • Apache软件基金会开发的Commons IO是个简化了IO的工具类

  • 官网:http://commons.apache.org/proper/commons-io/

  • 使用Commons IO需要添加jar包(如:commons-io-2.8.0.jar)

    IOUtils类常用方法:
    // 把input输入流中的内容拷贝到output输出流中,返回拷贝的字节个数(适合文件大小为2GB以下)
    static int copy(InputStream input, OutputStream output)
    // 把input输入流中的内容拷贝到output输出流中,返回拷贝的字节个数(适合文件大小为2GB以上)
    static long copyLarge(InputStream input, OutputStream output)
    // 悄悄的释放资源,自动处理close()方法抛出的异常
    static void closeQuietly(任意流对象)
    
    FileUtils类常用方法:
    // 复制文件到另外一个目录下
    static void copyFileToDirectory(File srcFile, File destDir)
    // 传递File类型的目录,进行整个目录的复制,自动进行递归遍历
    static void copyDirectoryToDirectory(File sourceDir, File destinationDir)
    // 写字符串到文本文件中
    static void writeStringToFile(File file, String data)
    // 读取文本文件,返回字符串
    static String readFileToString(File file)
    

若有错误或补充,欢迎私信

你可能感兴趣的:(Java SE-07-IO流)