Java-IO流知识整理

Java-IO流知识整理

一、文件

1.1 概念

  • 保存数据的地方;

1.2 文件流

  • 文件在程序中是以流的形式来操作的;

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

    • 输入流: 数据源(文件) ==> 程序(内存)
    • 输出流: 数据源(文件) <== 程序(内存)

    IOStream_1

1.3 常用的文件操作

  • (1)文件创建

    • 三种方式
    static void createFile_1(){//1.根据文件路径创建
            String  filePath = "D:\\JavaCode\\projects\\JavaDemo\\hsp_ch19\\testfile\\news01.txt";
            File file = new File(filePath);//在内存中,创建了File文件对象;
    
            try {
                file.createNewFile();//此时才会在磁盘对应位置创建文件并写入;
                System.out.println("文件" + file.getName() + "已创建");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    
        static void createFile_2(){//2.根据父目录文件 + 文件名创建
            File parent = new File("D:\\JavaCode\\projects\\JavaDemo\\hsp_ch19\\testfile");
            String fileName = "news02.txt";
    
            File file = new File(parent, fileName);
    
            try {
                file.createNewFile();
                System.out.println("文件" + file.getName() + "已创建");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    
        static void createFile_3(){//3.根据父目录文件路径 + 文件名创建
            String parentPath = "D:\\JavaCode\\projects\\JavaDemo\\hsp_ch19\\testfile";
            String fileName = "news03.txt";
    
            File file = new File(parentPath, fileName);
    
            try {
                file.createNewFile();
                System.out.println("文件" + file.getName() + "已创建");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    
  • (2)获取文件信息

    • 常用的几个:
    static void getInfo(){
        File file = new File("D:\\JavaCode\\projects\\JavaDemo\\hsp_ch19\\testfile\\news01.txt");
    
        System.out.println(" 文件名 ===== " + file.getName());
    
        System.out.println(" 绝对路径 ===== " + file.getAbsolutePath());
    
        System.out.println(" 父级目录 ===== " + file.getParent());
    
        System.out.println(" 文件大小(byte) ===== " + file.length());
    
        System.out.println(" 文件是否存在 ===== " + file.exists());
    
        System.out.println(" 是不是一个文件 ===== " + file.isFile());
    
        System.out.println(" 文件是不是一个目录 ===== " + file.isDirectory());
    }
    
  • (3)目录操作和文件删除

    • 删除文件
    @Test
    public void m1() {
        //1.判断 指定路径的文件是否存在,存在则删除;
        String filePath = "D:\\JavaCode\\projects\\JavaDemo\\hsp_ch19\\testfile\\news01.txt";
        File file = new File(filePath);
        if (file.exists()) {
            if (file.delete()) {
                System.out.println("文件删除成功!");
            } else {
                System.out.println("文件删除失败!");
            }
        } else {
            System.out.println("文件不存在!");
        }
    }
    
    • 删除(目录)文件
    @Test
    public void m2() {
        //2.判断 指定目录 是否存在,存在则删除;
        //  目录也是一种文件!!
        String filePath = "D:\\JavaCode\\projects\\JavaDemo\\hsp_ch19\\testfile02";
        File file = new File(filePath);
        if (file.exists()) {
            if (file.delete()) {
                System.out.println("目录删除成功!");
            } else {
                System.out.println("目录删除失败!");
            }
        } else {
            System.out.println("该目录不存在!");
        }
    }
    
    • 创建目录
    @Test
    public void m3() {
        //3.判断 指定目录 是否存在,存在则提示存在,否则创建该目录;
        String filePath = "D:\\JavaCode\\projects\\JavaDemo\\hsp_ch19\\testfile\\a";
        File file = new File(filePath);
        if (file.exists()) {
            System.out.println("该目录已存在!");
        } else {
            if(file.mkdirs()){//创建多级目录mkdirs(),即在当前已存在的目录下,创建多级目录文件(...\\a\\b\\c\\d)
                // if(file.mkdir()){//创建一级目录mkdir(),即在当前已存在的目录下,创建一级目录文件(...\\a)
                System.out.println("该目录创建成功!");
            }
            else {
                System.out.println("该目录创建失败!");
            }
        }
    }
    

二、IO流原理及流的分类

2.1 I/O原理

  • I/O技术:用于处理数据传输,如文件读/写,网络通讯等;
  • Java程序中,对于数据输入/输出操作以“流(stream)”的方式进行;
    • 输入流(input):读取外部数据(可以是磁盘、光盘、另一个程序等等)到程序(内存)中;
    • 输出流(output):将程序(内存)数据输出到外部存储设备或另一个程序
  • java.io包中提供了各种“流”类和接口,用以获取不同种类的数据,并通过方法进行数据的输入或输出;

2.2 流的分类

  • 按操作数据单位不同:
    • 字节流(8 bit)
      • InputStream 和 OutputStream
      • 如:操作二进制文件(如视频,音频)时,使用字节流操作不会产生损失
    • 字符流(字符,大小与文件编码有关)
      • Reader 和 Writer
      • 如:操作文本文件(文本文件里面都是字符)时,使用字符流操作比较好
  • 按数据流的流向不同:
    • 输入流
    • 输出流
  • 按流的角色不同
    • 节点流
    • 处理流/包装流
(抽象基类)字节流字符流
输入流InputStreamReader
输出流OutputStreamWriter

上述四个类都是抽象类,可以通过实现子类来创建相应的对象,I/O流的子类都是以抽象父类作为后缀的

2.3 输入流

2.3.1 InputStream
  • 抽象类 ==> 输入流 ==> 字节流
  • 以字节为单位进行I/O操作
FileInputStream
  • 文件输入流(字节流)

  • new FileInputStream(File/String)

    • 一个字节一个字节读取
    @Test
    public void read_FileInputStream_byte() throws IOException {
        String filePath = "D:\\JavaCode\\projects\\JavaDemo\\hsp_ch19\\testfile\\hello1.txt";
        int read_index = 0;
        FileInputStream fi = null;
        try {
            fi = new FileInputStream(filePath);
            read_index = fi.read();
            while(read_index != -1){//read_index == -1时,文件到达末尾,读取结束!
                System.out.print((char)read_index);
                read_index = fi.read();
            }
            System.out.println();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        finally {
            //这里不能直接访问trycatch子句中定义的流对象
            if(fi != null)
                fi.close();
        }
    }
    
    • 通过byte数组,指定每次最多读取的字节数
    @Test
    public void read_FileInputStream_byteArray() throws IOException {
        String filePath = "D:\\JavaCode\\projects\\JavaDemo\\hsp_ch19\\testfile\\hello1.txt";
        int read_len = 0;
        byte[] buf = new byte[8];//让字节流一次最多读取8个字节
        FileInputStream fi = null;
        try {
            fi = new FileInputStream(filePath);
    
            while ((read_len = fi.read(buf)) != -1){//read(byte[])返回读取到的字节数
                System.out.print(new String(buf, 0, read_len));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        finally {
            //这里不能直接访问trycatch子句中定义的流对象
            if(fi != null)
                fi.close();
        }
    }
    
BufferedInputStream
  • 继承关系:BufferedInputStream 继承 FliterInputStream 继承 InputStream

  • 带缓冲字节输入流(包装流,可以包装任意InputStream字节输入流及其实现子类)

ObjectInputStream
  • 对象字节输入流(节点-处理-输入流)
  • new ObjectInputStream(InpuSteam)
2.3.2 Reader
  • 抽象类 ==> 输入流 ==> 字符流
  • 以字符为单位进行I/O操作
FileReader
  • 继承关系:FileReader 继承 InputStreamReader 继承 Reader

  • 文件输入流(字符流)

  • new FileReader(File/String)

    • 一个字符一个字符读取
    @Test
    public void read_FileReader_char() throws IOException {
        String filePath = "D:\\JavaCode\\projects\\JavaDemo\\hsp_ch19\\testfile\\news04.txt";
        int read_index = 0;
        FileReader fr = null;
    
        try {
            fr = new FileReader(filePath);
            while((read_index = fr.read()) != -1){
                System.out.print((char)read_index);
            }
            System.out.println();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        finally {//记得关闭流!!
            if(fr != null)
                fr.close();
        }
    }
    
    • 通过char数组读取
    @Test
    public void read_FileReader_charArr() throws IOException {
        String filePath = "D:\\JavaCode\\projects\\JavaDemo\\hsp_ch19\\testfile\\news04.txt";
        int read_len = 0;
        char[] buf = new char[8];
        FileReader fr = null;
    
        try {
            fr = new FileReader(filePath);
            while((read_len = fr.read(buf)) != -1){
                //                System.out.print(new String(buf));
                System.out.print(new String(buf, 0, read_len));
            }
            System.out.println();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        finally {//记得关闭流!!
            if(fr != null)
                fr.close();
        }
    }
    
BufferedReader
  • 带缓冲字符输入流(包装流,可以包装不同的节点流)

  • new BufferedReader(new xxxReader)

    • 读取文件
    import java.io.*;
    
    /**
     * @author: sea-365
     * @date: 2023/4/21 15:06
     */
    public class FileIO_BufferedReader01 {
        public static void main(String[] args) throws IOException {
            String filePath = "./hsp_ch19/FileIO_create/FileIO_create01.java";
            //创建BufferedReader
            BufferedReader bufferedReader = new BufferedReader(new FileReader(new File(filePath)));
            //读取文件
            String line = bufferedReader.readLine();
            while(line != null){
                System.out.println(line);
                line = bufferedReader.readLine();
            }
    
            //关闭流
            bufferedReader.close();
    
        }
    }
    
InputStreamReader
  • 转换流

2.4 输出流

2.4.1 OutputStream
  • 抽象类 ==> 输出流 ==> 字节流
  • 以字节为单位进行I/O操作
FileOutputStream
  • 文件输出流(字节流)

    • 指定的文件不存在但所在目录存在,则会先创建该文件然后写入数据;
    @Test
    public void write_FileOutputStream() throws IOException {
        String filePath = "D:\\JavaCode\\projects\\JavaDemo\\hsp_ch19\\testfile\\hello2.txt";
        FileOutputStream fo = null;
    
        try {
            fo = new FileOutputStream(filePath, true);//true表示追加模式,默认为false覆盖模式;
    
            fo.write('a');//写入单个字节;
    
            fo.write("\nhello,北京\n".getBytes());//通过字节数组写入
    
            fo.write("\n1234567890\n".getBytes(), 3, 9);//写入字节数组指定范围内的数据
    
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        finally {
            if(fo != null)
                fo.close();
        }
    }
    
BufferedOutputStream
  • 继承关系:BufferedOutputStream 继承 FliterOutputStream 继承 OutputStream
  • 带缓冲字节输出流(包装流,可以包装任意OutputStream字节输入流及其实现子类)
ObjectOutputStream
  • 对象字节输出流(节点-处理-输出流)
  • new ObjectOutputStream(OutputStream)
2.4.2 Writer
  • 抽象类 ==> 输入流 ==> 字符流

  • 以字符为单位进行I/O操作

FileWriter
  • 继承关系:FileWriter 继承 OutputStreamWriter 继承 Writer

  • 文件输出流(字符流)

  • FileWriter在使用结束后,必须使用close()关闭方法或flush()刷新方法,否则写入不到指定文件(还在内存中!!!)

    • 顺序:先flush(),后close()!

    • 两个方法的实现中都会将流里面的内容写入文件;

  • new FileWriter(File/String, true);//true表示追加内容,默认是false,覆盖模式;

    • 一个字符一个字符写入
    @Test
    public void writer_FileWriter_char() throws IOException {
        String filePath = "D:\\JavaCode\\projects\\JavaDemo\\hsp_ch19\\testfile\\news05.txt";
        FileWriter fw = null;
    
        try {
            //fw = new FileWriter(filePath);//覆盖模式
            fw = new FileWriter(filePath, true);//追加模式
            fw.write('a');
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        finally {//记得关闭或刷新流!!
            if(fw != null)
                fw.close();
        }
    }  
    
    • 指定char数组写入
    @Test
    public void writer_FileWriter_charArr() throws IOException {
        String filePath = "D:\\JavaCode\\projects\\JavaDemo\\hsp_ch19\\testfile\\news05.txt";
        FileWriter fw = null;
        try {
            //fw = new FileWriter(filePath);//覆盖模式
            fw = new FileWriter(filePath, true);//追加模式
            fw.write("abcdefg\n".toCharArray());
            fw.write("abcdefgh\n".toCharArray(), 0, 3);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        finally {//记得关闭或刷新流!!
            if(fw != null)
                fw.close();
        }
    }    
    
    • 字符串写入
    @Test
    public void writer_FileWriter_String() throws IOException {
        String filePath = "D:\\JavaCode\\projects\\JavaDemo\\hsp_ch19\\testfile\\news05.txt";
        FileWriter fw = null;
        try {
            //fw = new FileWriter(filePath);//覆盖模式
            fw = new FileWriter(filePath, true);//追加模式
            fw.write("abcdefg\n");
            fw.write("abcdefgh\n", 0, 3);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        finally {//记得关闭或刷新流!!
            if(fw != null)
                fw.close();
        }
    }
    
BufferedWriter
  • 带缓冲字符输出流

  • new BufferedWriter(new xxxWriter)

    • 字符串写入文件
    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    
    /**
     * @author: sea-365
     * @date: 2023/4/21 16:52
     */
    public class FileIO_BufferedWriter01 {
        public static void main(String[] args) throws IOException {
            String filePath = "./hsp_ch19/testfile/bufferedwriter01.txt";
            BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(new File(filePath)));
    
            bufferedWriter.write("我现在在学Java IO流,感觉不是很有意思啊。。。。");
            bufferedWriter.newLine();//插入一个和系统相关的换行符
            bufferedWriter.write("还是得学习!!!");
    
            bufferedWriter.close();
        }
    }
    
OutputStreamWriter
  • 转换流

2.5 节点流和处理流

分类字节输入流字节输出流字符输入流字符输出流分类
抽象基类InputStreamOutputStreamReaderWriter
访问文件FileInputStreamFileOutputStreamFileReaderFileWriter节点流
访问数组ByteArrayInputStream节点流
访问管道PipedInputStream节点流
访问字符串节点流
缓冲流BufferedInputStream处理(包装)流
转换流处理(包装)流
对象流ObjectInputStream处理(包装)流
抽象基类
(继承自第二行的基类)
FilterInputStreamFilterOutputStreamFilterReaderFilterWriter
打印流PrintStreamPrintWriter处理(包装)流
推回输入流PushbackInputStreamPushbackReader处理(包装)流
特殊流DataInputStreamDataOutputStream处理(包装)流
2.5.1 节点流
  • 节点流可以从一个**特定的数据源(存放数据的地方)**读写数据;
    • 如FileReader、FileWriter是从某个文件中读写数据;
2.5.2 处理流
  • 处理流也叫包装流,是“连接”在已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能;
    • 如BufferedReader、BufferedWriter;
  • 优点:
    • 1.性能的提升:主要以增加缓冲的方式来提高输入输出的效率;
    • 2.操作的便捷:处理流 可能提供一系列便捷的方法来一次性输入输出大批量数据,使用更加灵活;
2.5.3 区别和联系
  • 1.节点流是底层(低级)流,直接跟数据源相接
  • 2.处理流(包装流)包装节点流,既可以消除不同节点流的实现差异,也可以提供更加方便的输入输出方法;
  • 3.处理流对节点流进行包装,使用了修饰器设计模式不与数据源直接相连
2.5.4 标准输入输出流
类型默认设备描述编译类型运行类型
System.inInputStream键盘标准输入InputStreamBufferedInputStream
System.outOutputStream显示器标准输出PrintStreamPrintStream
/**
 * @author: sea-365
 * @date: 2023/4/26 20:35
 */
public class FileIO_System01 {
    public static void main(String[] args) {
        System.out.println(System.in.getClass());
        System.out.println(System.out.getClass());
    }
}
  • 输出:

在这里插入图片描述

2.5.5 转换流
  • InputStreamReader

    • new InputStreamReader(InputStream)
    • new InputStreamReader(InputStream, Charset);//可以指定字符集将字节流转换为字符流;
  • OutputStreamWriter

    • new OutputStreamWriter(OutputStream)
    • new OutputStreamWriter(OutputStream, Charset)
  • 是Reader/Writer的子类,是字符流;

  • 处理纯文本数据时,使用字符流效率较高,可以有效解决中文乱码问题;

2.5.6 打印流
  • PrintStream/PrintWriter
  • 继承关系:
    • PrintStream 继承 FilterOutputStream 继承 OutputStream;
    • PrintWriter 继承 Wirter;
  • 字节流,只有输出流,没有输入流;

2.6 Properties

  • 例子:读取配置文件中的值
  • 配置文件如下:
ip=192.168.0.1
user=root;
password=123456
  • 不使用Properties类时
/**
 * @author: sea-365
 * @date: 2023/4/26 21:40
 */
public class FileIO_Properties01 {
    public static void main(String[] args) throws IOException {
        
        //不使用Properties类
        String filePath = "./hsp_ch19/testfile/mysql.properties";
        BufferedReader br = new BufferedReader(new FileReader(filePath));

        String line = "";

        while((line = br.readLine()) != null){
            String[] split = line.split("=");
            System.out.println(split[0] + "=" + split[1]);
        }
    }
}
  • Properties类介绍

    • 专门用于读写配置文件的集合类;
      • 格式:键=值
    • 注意:键值对中不需要空格,值不需要用引号,默认类型是String;
  • 使用Properties类

/**
 * @author: SEA
 * @date: 2023/4/27
 */
public class FileIO_Properties02{
    public static void main(String[] args) throws IOException {
        String filePath_1 = "./hsp_ch19/testfile/mysql.properties";
        String filePath_2 = "./hsp_ch19/testfile/mysql2.properties";
        //new一个Propertes对象
        Properties properties = new Properties();
        //加载指定的配置文件
        properties.load(new FileReader(filePath_1));
        //将指定配置文件中的配置信息打印到标准输出(显示器)
        properties.list(new PrintStream(System.out));


        Properties properties1 = new Properties();
        properties1.setProperty("email", "123456@163.com");
        properties1.setProperty("call", "123456789");
        properties1.setProperty("name", "张三");//出现中文,将会转换成Unicode编码进行保存
        properties1.store(new FileOutputStream(filePath_2), "");

        properties1.list(new PrintStream(System.out));

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SEA-365

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值