java详解 --- IO流

先创建一个SD类,全篇都能用到:

public class SD{
    // 定义文件分隔符
    public static String s_f = System.getProperty("file.separator");
    // 定义路径分隔符
    public static String s_p = System.getProperty("path.separator");
    // 定义行分隔符
    public static String s_l = System.getProperty("line.separator");
    // 定义项目路径
    public static String d_w = System.getProperty("user.dir");
    // 定义系统路径
    public static String d_d = System.getProperty("user.home");
    // 定义桌面路径
    public static String d_h = d_h + s_f + "Desktop";
    // 定义项目文件路径
    public static String d_s = d_w + s_f + "src";

    // 封装一个函数 用来获取文件的路径
    public static String getPath(String ... args){
        if(args.length == 0){
            return d_d;
        }
        if(args.length == 1){
            return args[0]; 
        }
        // 使用可变字符串用来拼接路径
        StringBuffer sb = new StringBuffer();
        // 多处使用 用于变量值的保存
        int len = args.length;
        for(int i= 0 ; i < len - 1 , i++){
            sb.append(args[i]);
            sb.append(s_f);
        }
        // 外部拼接最后一位
        sb.append(args[i - 1]);
        return new String(sb);
    }
}

一.IO流

1.流的定义:程序操作数据类似于”管道输送水源” , 从源头到目标的一个不间断的持续过程 , 将此过程功能封装抽象定义出来的类称之为流(stream)

2.输入流与输出流:
输入流:将文件中的数据输入到程序中 , 形成程序数据
输出流:将程序中已有数据输出到文件中 , 形成持久化的数据
注意:
输入流 : Input < == > 读 : reader
输出流 : Output < == > 写 : writer

3.字节流与字符流:
字节流 : 以字节作为流的操作对象
字符流 : 以字符作为流的操作对象
注意:
1 ). 字符流可以高效的处理文本相关的数据 , 字节流可以处理任意文本数据.
2 ). 字符流有默认缓冲区 , 字节流不具有默认缓冲区(buffer).

二.文件字节输出流 - FileOutputStream

1.功能:将数据以字节的方式写入文件
字节:byte[] / int(ASCII码值)
2.书写步骤:
①.指定写入的文件存放的路径
②.指定写入的文件名
③.获取写入的信息(可以是字节数组:byte[] / int(ASCII码))
④.创建操作该文件的FileOutputStream类的对象
⑤.写入数据
⑥.关闭流(重点:必须关闭流)
3.代码举例:
首先在你的工作目录下创建io/io01/1.txt文件.

    // 获取目标文件夹
    String pathname = SD.getPath(SD.d_w , "io", "io01");
    File path = new File(pathname);

    // 写入时判断文件夹如果存在就创建它
    if (!path.exists()) {
        path.mkdirs();
    }

    // 获取目标文件
    File file = new File(path, "1.txt");

    // 需要写入的数据
    String info = "①②③④⑤" + SD.s_l;
    // 放入byte数组中
    byte[] bs = info.getBytes();

    // 创建FileOutputstream类以及相关操作
    FileOutputStream output = null;
    try {
        // 第二个参数是代表可否续写而不是覆盖
        output = new FileOutputStream(file , true);
        // 写入方法
        output.write(bs);
    } catch (FileNotFoundException e) {
        System.out.println("异常 - FileNotFoundException");
    } catch (IOException e) {
        System.out.println("异常 - IOException");
    } finally {
        try {
            // 关闭流
            if (output != null) {
                output.close();
            }
        } catch (IOException e) {
            System.out.println("异常 - IOException");
        }
    }
    // 提示执行完毕
    System.out.println("执行完毕!!");

三.文本字节输出流 - FileInputStream

1.功能:以字节来操作单位 读取文本中的数据
2.书写步骤:
①.获取对应的目标文件
②.创建文件对应的FileInputStream类的对象
③.通过流对象读取文件内容
④.使用读取到的内容(打印 / 展示 / 再次写入)
⑤.关闭流
3.代码举例:
1).读取数字/英文
首先在你的工作目录下创建io/io02/100.txt文件.

    // 获取目标文件
    String child = SD.getPath("io" , "io02" , "100.txt");
    File file = new File(SD.d_w , child);

    // 创建文件对应的FileInputStream类
    FileInputStream input = null;
    try {
        // 创建流的对象的时候可能会出现FileNotFoundException
        input = new FileInputStream(file);
        // 使用流读取文件时可能会出现IOException
        int res = 0;
        /*
             * 使用read() 读取文件
             * 1).一次只会读取一个文件
             * 2).返回的是读取到的字节对应的ASCII码值
             * 3).读取的文件 最后没有数据时会返回-1
         */
        // input.read() 既是判断条件 又是运算结果
        // 所以将此操作上移到循环作为判断条件 操作用()嵌套在循环条件
        // 使用这种方法可以一个字节读取 同时将一个字节输出到控制台上
        while ((res = input.read()) != -1) {
            // 直接输出汉字的话会出现乱码
            System.out.printf("%c" , res);
        }
    } catch (FileNotFoundException e) {
        System.out.println("异常 - FileNotFoundException");
    } catch (IOException e) {
        System.out.println("异常 - IOException");
    } finally {
        try {
            // 为了避免出现空指针异常(流创建失败 流就不会存在)
            if (input != null) {
                input.close();
            }
        } catch (IOException e) {
            System.out.println("异常 - IOException");
        }
    }
    // 提示程序执行完毕
    System.out.println("执行完毕!!");

2).读取中英文共存
首先在工作目录下创建目标文件 然后再编写代码:

    // 获取目标文件
    String child = SD.getPath("io" , "io02" , "100.txt");
    File file = new File(SD.d_w , child);

    // 创建文件对应的FileInputStream类
    FileInputStream input = null;
    try {
        // 创建流的对象的时候可能会出现FileNotFoundException
        input = new FileInputStream(file);
        // 使用流读取文件时可能会出现IOException
        int len = 0;
        // input.read() 既是判断条件 又是运算结果
        // 后面的[]是每次读取的字节
        // 这次给的是文件的长度 如果文件过大可能会崩
        // 所以[]中的长度应该给适当的距离 
        byte[] res = new byte[(int)file.length()];
        while ((len = input.read()) != -1) {
            // 直接输出汉字的话会出现乱码
            System.out.println(new String(res));
        }
    } catch (FileNotFoundException e) {
        System.out.println("异常 - FileNotFoundException");
    } catch (IOException e) {
        System.out.println("异常 - IOException");
    } finally {
        try {
            // 为了避免出现空指针异常(流创建失败 流就不会存在)
            if (input != null) {
                input.close();
            }
        } catch (IOException e) {
            System.out.println("异常 - IOException");
        }
    }
    // 提示程序执行完毕
    System.out.println("执行完毕!!");

四.字节流的边读边写(复制文本)

1.书写步骤:
①.获取读取的目标文件(要复制的文本)
②.确定要写入的目标文件(复制到的目标文本)
③.创建对应文件对应的输入流 和 输出流
④.读取内容 并 写入内容
⑤.关闭流
2.代码举例:
1).文本文件的复制
首先在工作目录下创建目标文件 然后再编写代码:

    // 获取要读取目标文件
    String sPath= SD.getPath(SD.d_w , "io" , "io02" , "100.txt");
    File source = new File(sPath);

    // 获取要写入的目标文件
    String tPath = SD.getPath(SD.d_w , "io" , "io02" , "101.txt");
    File target = new File(tPath);

    // 获取目标文件对应的输入 和 输出流
    FileOutputStream out = null;
    FileInputStream in = null;
    try {
        // 读取目标文件
        in = new FileInputStream(source);
        // 写入目标文件
        out = new FileOutputStream(target);
        // 复制文件
        int res = 0;
        while ((res = in.read()) != -1) {
            // 写入文件的方法write()
            out.write(res);
        }
    } catch (FileNotFoundException e) {
        System.out.println("异常 - FileNotFoundException");
    } catch (IOException e) {
        System.out.println("异常 - IOException");
    } finally {
        try {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        } catch (IOException e) {
            System.out.println("异常 - IOException");
        }
    }
    // 提示程序执行完毕
    System.out.println("执行完毕!!");

2).非文本文件的复制
首先在工作目录下创建目标文件 然后再编写代码:

    File source = new File(SD.d_d , "001.png");
    File target = new File(SD.d_d , "002.png");

    // 将所有的异常上抛给main函数处理    
    FileInputStream in = new FileInputStream(source);
    FileOutputStream out = new FileOutputStream(target);

    // 读写操作 -- 复制操作
    int len = 0;
    byte[] res = new byte[1];
    while ((len = in.read(res)) != -1) {
        // 按byte[]数组进行数据写入 从0开始 写入了len长度
        out.write(res , 0 , len);   
    }

    in.close();
    out.close();

    // 删除源文件
    source.delete();

六.文件字符流 - 读(Reader) / 写(Writer)

1.定义:以字符为单位操作文本文件.
2.字符的好处(相比于字节):
①.文本文件专属操作流 可以更高效率的操作文本
②.拥有默认缓冲区 所以字符流不操作文件本身 操作的是缓冲区
③.以字符为操作单位 无需考虑不同字符所占字节数
3.对应的流的方法:
Reader <==> FileReader
Writer <==> FileWriter
4.代码举例:

public static void main(String[] args) {
    //writeSomething();
    readSomething();
}

// 写入文本文件
private static void writeSomething() {
    String path = SD.getPath(SD.d_w , "io" , "io03");
    File file = new File(path , "a.txt");
    FileWriter writer = null;
    try {
        // 续写
        writer = new FileWriter(file , true);
        char[] info = {'1' , 'A' , '一' , '①'};  
        // 从info数组的索引1开始 截取3长度写入到文件中
        writer.write(info , 1 , 2);
        // 书写一次 清一次缓冲区
        writer.flush();
        writer.write("��"); // 这里写的是4个字节 网页读取不了
        writer.flush();
        writer.write("��");
        writer.flush();
        writer.write(SD.s_l);
        // 最后一次清缓冲区操作可以交给close()
    } catch (IOException e) {
        System.out.println("异常 - IOException");
    } finally {
        try {
            if (writer != null) {
                writer.close();
            }
        } catch (IOException e) {
            System.out.println("异常 - IOException");
        }
    }
    System.out.println("写入完成!!");
}

// 读取文本文件
private static void readSomething() {
    String path = SD.getPath(SD.d_w , "io" , "io03");
    File file = new File(path , "a.txt");

    FileReader reader = null;
    try {
        reader = new FileReader(file);
        int len = 0;
        char[] info = new char[1];
        while ((len = reader.read(info)) != -1) {
            // 延时打印
            long time = System.currentTimeMillis();
            while (System.currentTimeMillis() - time < 60) {}
            // 告诉打印时可能解析错误
            // 原因: "��""��"占4个字节 char占两个字节 需两次读取 才可以解析为完整字符
            // 且系统对应字符流已经被处理(char一次读取不完的字符会被增加标识)
            System.out.print(new String(info , 0 , len));
        }
    } catch (FileNotFoundException e) {
        System.out.println("异常 - FileNotFoundException");
    } catch (IOException e) {
        System.out.println("异常 - IOException");
    } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                System.out.println("异常 - IOException");
        }
    }
    System.out.println("读取完成!!");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值