Java文件IO

import org.junit.jupiter.api.Test;
import java.io.*;
import java.util.Arrays;

//@SpringBootTest
class SpringbootClangApplicationTests {


    /** # FileOutputStream(字节输出流)
     * 输出到文件
     * 一.创建字符流对象
     *
     * 二.写出数据
     *
     * 三.释放资源
     *  1.void write(int b) 一次写一个字节
     *  2.void write(byte[] b) 一次写一个字节数组数据
     *  3.void write(byte[] b, int off, int len) 一次写入部分数据
     * ## 注意事项
     * 默认覆盖之前的内容
     * public FileOutputStream(File file, boolean append)
     * 通过FileOutputStream(filePath, true) 追加写入
     */

    // 1.void write(int b)
    @Test
    void testIntB() throws IOException {

        //1.创建输出流
        FileOutputStream fos = new FileOutputStream("a.txt");

        //2.写入数据
        fos.write('a');

        //3.关闭资源
        fos.close();

    }


    // 2.void write(byte[] b)
    @Test
    void testByteB() throws IOException {
        //1.创建对象
        FileOutputStream fos = new FileOutputStream("a.txt");

        //2.创建字节数组
        byte[] bytes = {97, 98, 99, 100, 101};

        //3. 写入数据
        fos.write(bytes);

        //4.关闭资源
        fos.close();
    }

    //3.void write(byte[] b, int off, int len)

    /**
     * 参数一、数组
     * 参数二、起始位置
     * 参数三、个数
     * @throws IOException
     */
    @Test
    void testStringB() throws IOException {

        //1.创建对象
        FileOutputStream fos = new FileOutputStream("a.txt");
        //               0   1   2   3    4
        //2.创建数组      a   b   c   d    e
        byte[] bytes = {97, 98, 99, 100, 101};
        fos.write(bytes, 1, 2);

        //3.关闭资源
        fos.close();
    }

    //案例
    @Test
    public void demo() throws IOException {
        //1.创建对象
        FileOutputStream fos = new FileOutputStream("a.txt");

        //2.写出数据
        String str = "abc";
        byte[] bytes = str.getBytes();
        fos.write(bytes);
//        fos.write('\n');
//        fos.write('\r');
        String str2 = "def";
        byte[] bytes2 = str2.getBytes();
        fos.write(bytes2);

        //3.释放资源
        fos.close();


    }


    /** # FielInputStream(字节输入流)
     * 读取文件的数据
     * ## 实现步骤
     * 1.创建对象
     * 2.读取数据
     * 3.释放资源
     * ## 注意事项
     * 1.如果文件不存在,会直接报错
     * 2.如果读到文件末尾,值为-1
     */
    @Test
    public void fileInputDemo() throws IOException {
        //1.创建对象
        FileInputStream fis = new FileInputStream("a.txt");

        //2.读取数据
        int b1 = fis.read();
        System.out.println(b1);

        int b2 = fis.read();
        System.out.println(b2);


        int b3 = fis.read();
        System.out.println(b3);

        int b4 = fis.read();
        System.out.println(b4);

        int b5 = fis.read();
        System.out.println(b5);
    }

    /**
     * 循环读取字节输入流
     * read读取一次数据,就移动一次指针
     */
    @Test
    public void fileInputDemo02() throws IOException {

        //1.创建对象
        FileInputStream fis = new FileInputStream("a.txt");

        //2.循环读取
        int b=0;
        while ((fis.read()) !=-1){
            System.out.println((char)b);
        }

        //3.释放资源
        fis.close();
    }
    /**
     * FileInputStream
     * public int read() 一次读一个字节
     * public int read(byte[] buffer) 一次读一个字节数组(尽可能把数组填满)
     */

    /**
     * # 实战一
     * 小文件拷贝
     *
     */

    @Test
    public void fileInputDemo03() throws IOException {
        //1.创建对象
        FileInputStream fis = new FileInputStream("grim.png");
        FileOutputStream fos = new FileOutputStream("copy.png");
        //2.拷贝
        //核心思想,边读边写
        int b;
        while ((b = fis.read()) !=-1){
            fos.write(b);
        }

        //3.释放资源
        //规则,先开的后关闭
        fos.close();
        fis.close();


    }

    /**
     * # 实战
     * 大文件拷贝
     * 主要事项
     * 尽可能装满数组
     * 读不到数据就返回-1
     */
    @Test
    public void fileInputDemo04() throws IOException {
        //1.创建对象
        FileInputStream fis = new FileInputStream("a.txt");
        //2.读取数据
        byte[] bytes = new byte[2];
        //一次读取多少字节数据,由数组长度决定
        //返回值,本次读到多少个字节数据
        //第一次读
        int len1 = fis.read(bytes);
        System.out.println(len1);
        String str = new String(bytes,0,len1);
        System.out.println(str); //ab

        //第二次读
        int len2 = fis.read(bytes);
        String str2 = new String(bytes,0,len2);
        System.out.println(str2); //cd

        //第三次读
        int len3 = fis.read(bytes);
//        String str3 = new String(bytes,0,len3);
        String str3 = new String(bytes); //e->c->(ed)
        System.out.println(str3);

//        //第四次读
//        int len4 = fis.read(bytes);
//        String str4 = new String(bytes,0,len4);
//        System.out.println(str4);

        //3.释放资源
        fis.close();


    }

    /**
     * 文件拷贝改写
     *
     */
    @Test
    public void fileCopy() throws IOException {

        /**
         * 异常处理
         * try {
         *     1.创建对象
         *     2.处理数据
         * } catch() {
         *      异常处理代码
         * } finally {
         *     3.关闭资源
         * }
         */



        /**
         * 简化后
         */
        //1.创建对象
        try(FileInputStream fis = new FileInputStream("grim.png");
            FileOutputStream fos = new FileOutputStream("copy.png")) {
            //2.读取数据
            int len = 0;
            byte[] bytes = new byte[1024];
            while ((len = fis.read(bytes)) != -1) {
                fos.write(bytes, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } //3.释放资源。自动执行了finay 关闭了资源
    }


    /**
     * 字符集
     * 一、ASCII
     * 一字节,前面补0,补齐8位
     * a->97->0110 0001
     *
     * 二、GBK(GB扩展)
     * 存储英文:兼容ASCII
     * 存储中文:二字节(高位和低位),以1开头
     *
     * 三、Unicode
     * 一个英文占1字节,第一位是0,转成数字是一个正数
     * 一个汉字占3字节,第一个字节的第一位是1,转成数字是一个负数
     * UTF-8一种编码方式(不是字符集)
     * 0xxxxxxx(ASCII)
     * 110xxxxx 10xxxxxx
     * 1110xxxx 10xxxxxx 10xxxxxx(使用Unicode 填补)
     * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
     *
     * 四、为什么有乱码?
     * 1.字节流读取未读完整个汉字
     * 2.使用不同方式编码和解码
     *
     * 五、为什么字节流读取时会产生乱码,而拷贝时不会?
     * 拷贝到目的地数据没有丢失,使用对应编码方式读不会产生乱码。
     *
     */

    /**
     * Java中编码的方法
     *      public byte[] getBytes() 使用默认方式进行编码
     *      public byte[] getBytes(String charsetName) 使用指定方式进行编码
     *
     * Java中解码的方法
     *      String(byte[] bytes) 使用默认方式进行解码
     *      String(byte[] bytes, String charsetName) 使用指定方式进行解码
     */
    @Test
    public void charsetNameDemo() throws UnsupportedEncodingException {
        //1.编码
        String str = "ai你哟";
        byte[] bytes1 = str.getBytes("GBK");
        byte[] bytes2 = str.getBytes("UTF-8");
        System.out.println(Arrays.toString(bytes1));
        System.out.println(Arrays.toString(bytes2));

        //2.解码
        String str1 = new String(bytes1);
        System.out.println("GBK:"+str1);
        String str2 = new String(bytes2);
        System.out.println("UTF-8:"+str2);

    }


    /**
     * 字符流读取
     * 本质上就是字节流+字符集
     * 1.创建字符流对象
     * 2.读取数据读到末尾返回-1
     * 3.释放资源
     */

    //一、字符流默认一次读一个字节
    @Test
    public void fileReaderDemo() throws IOException {
        //1.创建对象并关联本地文件
        FileReader fr = new FileReader("a.txt");

        //2.读取数据 read()
        //字符流的底层就是字节流,默认按照一个字节一个字节读取的
        //如果遇到中文1就会异常读取多个,GBK一次读2字节,UTF-8一次读3字节
        //最终返回一个10进制
        int ch;
        while ((ch = fr.read()) != -1) {
            System.out.println(ch);
        }

        //3.释放资源
        fr.close();
    }

    //二、字符流默认一次读多个字节
    @Test
    public void fileReaderBytes() throws IOException {
        //1.创建对象
        FileReader fr = new FileReader("a.txt");

        //2.读取数据,一次默认读两个字符
        char[] chars = new char[2];

        int len;
        //read(char) 把读取数据、解码、强转 三步合并了,放到字符数字中
        while ((len = fr.read(chars)) != -1) {
            //可能读不满
            System.out.println(new String(chars, 0, len));
        }

        //3.释放资源
        fr.close();
    }

    /**
     * TODO 字符输出流
     * 1.创建字符流对象
     *      public FileWriter(File file)
     *      public FileWriter(String pathname)
     *      public FileWriter(File file, boolean append) 续写
     *      public FileWriter(String pathname, boolean append) 续写
     * 2.读取数据
     *      void write(int c) 写一个字符
     *      void write(String str) 写出一个字符串(主要)
     *      void write(char[] cbuf) 写出一个字符数组
     *      void write(char[] cbuf, int off, int len) 写出字符数组的一部分
     *
     * 3.关闭资源
     * @throws IOException
     */
    //TODO 字符输出流 写一个字符
    @Test
    public void fileWriterDemo() throws IOException {
        //1.创建对象,关联本地文件
        FileWriter fw = new FileWriter("a.txt");

        //2.写入数据
        fw.write(25105); //根据字符集进行编码,把编码后的数据写入到文件中

        //3.关闭字符输出流
        fw.close();
    }
    // TODO 字符输出流 写一个字符串
    @Test
    public void fileWriterStrDemo() throws IOException {
        //1.创建对象
        FileWriter fw = new FileWriter("a.txt");

        //2.写入数据
        fw.write("我是你爹");

        //3.关闭资源
        fw.close();
    }

    /**
     * 字符流原理
     * FileReader
     * 会创建一个8192字节的缓冲区
     * 把数据放到缓冲区中读,尽可能填满缓冲区
     * 每次read() 都会判断缓冲区是否有内容
     *           如果缓冲区用完了
     *           就会继续从文件中取到缓冲区
     *           如果文件也没有内容,就会返回-1
     *           如果缓冲区满了,就会
     * FileWriter
     * 创建一个缓冲区
     * 每次write()会写到缓冲区
     *  当
     *    1.缓冲区满了会自动保存
     *    2.flush后
     *    3.关闭资源前,会检查缓冲区中是否有数据
     *    时,会把缓冲区的数据写出到文件中
     */

    /**
     * 实战一
     * 拷贝文件夹
     * 判断是否是文件
     *  是: 进行拷贝
     *  不是:继续遍历
     */
    @Test
    public void StreamDemo() throws IOException {
        //拷贝一个文件夹,考虑子文件夹

        //1.创建对象表示数据源
        File src = new File("/home/ime/Documents/hello");
//        File[] files = src.listFiles("demo/a.txt");
        //2.创建对象表示目的地
        File dest = new File("demo/hello");

        //3.调用方法进行拷贝
        copydir(src, dest);
    }

    public void copydir(File src, File dest) throws IOException {

        //递归
        //1.进入数据源
        File[] files = src.listFiles();
        if(files==null) return;

        //2.便利数组
        for(File file : files){
            //判断文件
            if(file.isFile()) {
                //3.开始拷贝
                FileInputStream fis = new FileInputStream(file);//要拷贝的文件
                FileOutputStream fos = new FileOutputStream(dest + "/" + file.getName());//拷贝的目的地

                byte[] b = new byte[1024];
                int len;
                while ((len = fis.read(b)) != -1) {
                    fos.write(b, 0, len);
                }
                fos.close();
                fis.close();

            } else {
                //4.如果是文件夹.递归
                copydir(file, new File(dest, file.getName()));
            }
        }
    }

    /**
     * 实战二
     * 文件加密
     */
    @Test
    public void StreamDemo02() throws IOException {
        //1.创建对象关联原始文件
        FileInputStream fis = new FileInputStream("a.txt");
        //2.创建对象关联加密文件
        FileOutputStream fos = new FileOutputStream("ency.txt");

        //3.加密处理
        int b;
        while ((b = fis.read())!= -1) {
            fos.write(b^2);
        }

        //4.释放资源
        fos.close();
        fis.close();
    }

    @Test
    public void StreamDemo03() throws IOException {
        FileReader fis = new FileReader("a.txt");
        FileWriter fos = new FileWriter("demo/ency.txt");
        char[] chars = new char[2];
        int len;
        while ((len = fis.read(chars)) != -1) {
            fos.write(chars, 0, len);
        }

    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值