IO专题

作者: 攻城老狮 | 来源:发表于2021-05-27 08:09 被阅读0次

1 文件

1.1 文件流的相关概念

流:数据在数据源(文件)和程序(内存)之间经历的路径

输入流:数据从数据源(文件)到程序(内存)的路径

输出流:数据从程序(内存)到数据源(文件)的路径

1.2 常用的文件操作

1.2.1 创建文件对象

public class File_ {
    public static void main(String[] args) throws IOException {
        //1.根据路径构建一个File对象
        String pathname = "d:/fileTest1.txt";
        File file1 = new File(pathname);
        file1.createNewFile();
        //2.根据父目录文件和子路径构建
        File parent = new File("d:/");
        File file2 = new File(parent, "fileTest2.txt");
        file2.createNewFile();
        //3.根据父目录和子路径构建
        File file3 = new File("d:/", "fileTest3.txt");
        file3.createNewFile();
    }
}

1.2.2 获取文件的相关信息

public class File_ {
    public static void main(String[] args) throws IOException {
        String pathname = "d:/fileTest1.txt";
        File file = new File(pathname);
        //1.getName 获取文件名
        System.out.println(file.getName());
        //2.getAbsolutePath 获取文件绝对路径
        System.out.println(file.getAbsolutePath());
        //3.getParent 获取文件父级目录
        System.out.println(file.getParent());
        //4.length 文件大小(字节)
        System.out.println(file.length());
        //5.exists 文件是否存在
        System.out.println(file.exists());
        //6.isFile 判断是不是一个文件
        System.out.println(file.isFile());
        //7.isDirectory 判断是不是一个目录
        System.out.println(file.isDirectory());
    }
}
  • result
fileTest1.txt
d:\fileTest1.txt
d:\
0
true
true
false

2 IO 流原理及流的分类

2.1 IO 流的分类

  • 按操作数据单位不同分为:字节流(8 bit)二进制文件,字符流(按字符)文本文件
  • 按数据流的流向不同分为:输入流,输出流
  • 按流的角色的不同分为:节点流,处理流(包装流)

2.2 IO 流的体系图

image-20210518150008681.png

3 FileInputStream和FileOutputStream

说明:使用这两个类可以实现对二进制文件的读入和写出,节点流

//使用FileInputStream 和 FileOutputStream 实现对照片的拷贝
public class FileCopy {
    public static void main(String[] args) {
        String srcPathName = "d:/testPicture.png";
        String destPathName = "d:/testPicture_new.png";
        FileInputStream fis = null;
        FileOutputStream fos = null;
        int readLen = 0;
        byte[] buf = new byte[1024];
        try {
            fis = new FileInputStream(srcPathName);
            fos = new FileOutputStream(destPathName);
            //每次读入1024字节内容至缓冲区,返回实际存储至缓冲区的字节数
            while ((readLen = fis.read(buf)) != -1) {
                fos.write(buf, 0, readLen);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

4 FileReader 和 FileWriter

说明:使用这两个类可以实现对字符的输入输出,FileWriter使用后,必须关闭或刷新,否则写入不到指定的文件

public class FileReaderWriter {
    public static void main(String[] args) {
        String srcFilePath = "d:/testFile.txt";
        String destFilePath = "d:/testFile_new.txt";
        FileReader fr = null;
        FileWriter fw = null;
        int readLen = 0;
        char[] buf = new char[8];
        try {
            fr = new FileReader(srcFilePath);
            fw = new FileWriter(destFilePath);
            //每次读入8字符内容至缓冲区,返回实际存储至缓冲区的字符数
            while ((readLen = fr.read(buf)) != -1) {
                fw.write(buf, 0, readLen);
                //打印字符到屏幕
                System.out.println(new String(buf,0,readLen));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fr != null) {
                    fr.close();
                }
                if (fw != null) {
                    fw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

5 节点流和处理流

5.1 基本说明

  • 节点流:可以从一个特定的数据源读写数据,如 FileReader,FileWriter
  • 处理流/包装流:连接在已存在的流之上,为程序提供更强大的读写功能,更灵活,如 BufferedReader,BufferedWriter

5.2 节点流和处理流的区别

  • 节点流是底层流/低级流,直接跟数据源相接
  • 处理流包装节点流,既可以消除不同节点流的实现差异,也可以提供方便的方法实现输入输出。
  • 处理流采用修饰器模式,不会直接于数据源连接

6 BufferedReader 和 BufferedWriter

6.1 基本说明

  • Buffer额度Reader 和 BufferedWriter 属于字符流,是按照字符来读取数据的
  • 关闭时只需要关闭最外层流即可
  • 不能操作二进制文件,由于其是以字符的形式流动,故会造成二进制文件的损坏

6.2 示例

说明:使用这两个类可以实现对文本文件的读入和写出,包装流

public class BufferedReaderWriter {
    public static void main(String[] args) {
        //获取resources目录下的文件方法(target目录下)
        String srcFilePath = Thread.currentThread().getContextClassLoader().getResource("testFile.txt").getPath();
        String destFilePath = Thread.currentThread().getContextClassLoader().getResource("testFile_new.txt").getPath();
        BufferedReader br = null;
        BufferedWriter bw = null;
        String line;
        try {
            br = new BufferedReader(new FileReader(srcFilePath));
            bw = new BufferedWriter(new FileWriter(destFilePath));
            while ((line = br.readLine()) != null) {
                bw.write(line);
                bw.newLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
                if (bw != null) {
                    bw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

7 BufferedInputStream 和 BufferedOutputStream

说明:使用这两个类可以实现对二进制文件的读入和写出,包装流

public class BufferedInputStreamOutputStream {
    public static void main(String[] args) {
        String srcFilePath = Thread.currentThread().getContextClassLoader().getResource("testFile.txt").getPath();
        String destFilePath = Thread.currentThread().getContextClassLoader().getResource("testFile_new.txt").getPath();
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        byte[] buf = new byte[64];
        int len = 0;
        try {
            bis = new BufferedInputStream(new FileInputStream(srcFilePath));
            //true 表示追加
            bos = new BufferedOutputStream(new FileOutputStream(destFilePath,true));
            while ((len = bis.read(buf)) != -1) {
                bos.write(buf, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (bis != null) {
                    bis.close();
                }
                if (bos != null) {
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

8 对象流 ObjectInputStream 和 ObjectOutputStream

8.1 对象流说明

  • 将Java对象保存至文件中称为序列化,将文件中的数据(值和类型)恢复为Java对象称为反序列化

  • 序列化和普通的保存不同之处在于,普通的保存只存储值,而序列化会保存值和数据类型

  • 对象流提供了对基本类型和对象类型的序列化和反序列化

8.2 序列化说明

  • 读写顺序要相同,按什么顺序序列化就需要按什么顺序反序列化
  • 要求序列化或反序列化对象,实现Serializable接口
  • 序列化的类中建议添加SerialVersionUID,为了提高版本的兼容性
  • 序列化对象时,默认将所有属性序列化,除了static和transient修饰的成员
  • 序列化对象时,要求属性的类型需要实现序列化接口
  • 序列化具备可继承性,如果某个类已经实现序列化,则它的所有子类也默认实现序列化

8.3 示例

  • 序列化

说明:使用 ObjectOutputStream 序列化基本数据类型和自定义对象,包装流

  • 反序列化

说明:使用 ObjectInputStream 反序列化上述内容,包装流

public class ObjectInputStreamOutputStream {
    public static void main(String[] args) {
        serialFunc();
        deserialFunc();
    }

    //反序列化
    public static void deserialFunc(){
        String objectPath = Thread.currentThread().getContextClassLoader().getResource("objectFile.txt").getPath();
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream(objectPath));
            //反序列化基本类型
            System.out.println(ois.readInt());
            System.out.println(ois.readBoolean());
            System.out.println(ois.readUTF());
            //反序列化自定义对象
            System.out.println(ois.readObject());
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                if (ois !=null){
                    ois.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //序列化
    public static void serialFunc(){
        String objectPath = Thread.currentThread().getContextClassLoader().getResource("objectFile.txt").getPath();
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream(objectPath));
            //序列化基本类型
            oos.writeInt(233);
            oos.writeBoolean(false);
            oos.writeUTF("hello world");
            //序列化自定义对象
            oos.writeObject(new Person("yorick",24));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (oos !=null){
                    oos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

9 标准输入输出流

9.1 基本说明

  • System.in 标准输入,类型是InputStream(BufferedInputStream),默认设备为键盘
  • System.out 标准输出,类型是PrintStream,默认设备为显示器

10 转换流 InputStreamReader 和 OutputStreamWriter

10.1 基本说明

  • 若本地文件采用gbk编码,则使用字符输入流读入默认采用的为utf-8编码,会导致出现乱码。可以借助 字节输入流转换编码,再使用字符输入流读入,故需要借助转换流转换
  • InputStreamReader 是 Reader 的子类,可以将 InputStream 包装为 Reader
  • OutputStreamWriter 是 Writer 的子类,可以将 OutputStream 包装为 Writer

10.2 示例

说明:将gbk编码的文件,读入不产生乱码

public class InputStreamReaderOutputStreamWriter {
    public static void main(String[] args) {
        String srcFilePath = Thread.currentThread().getContextClassLoader().getResource("testFile.txt").getPath();
        BufferedReader br = null;
        String line;
        try {
            //将其进行层层包装
            br = new BufferedReader(new InputStreamReader(new FileInputStream(srcFilePath),"gbk"));
            while ((line = br.readLine())!=null){
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (br !=null){
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

11 打印流 PrintStream 和 PrintWriter

11.1 基本说明

  • 打印流只有输出流,没有输入流

  • PrintStream 间接继承 OutputStream,PrintWriter 继承 Writer

相关文章

网友评论

      本文标题:IO专题

      本文链接:https://www.haomeiwen.com/subject/asdlsltx.html