【JAVA入门】Day40 - 字符流

【JAVA入门】Day40 - 字符流


文章目录

  • [【JAVA入门】Day40 - 字符流](#【JAVA入门】Day40 - 字符流)

字符流的底层就是字符流+字符集,它能实现在读取时,碰到英文字母,还按 1 个字节读取,碰到汉字时,则按多个字节读取(UTF-8 是 3 个字节,GBK 是 2 个字节)。因此,字符流用于纯文本场景的数据输入和输出。

一、Reader ------ 字符输入流

Reader 是字符输入流的抽象总类,它不能直接创建对象。但是有 FileReader 继承 Reader,它可以实现对本地文件的字符输入。

FileReader 的使用步骤如下:

代码实现。

① read() 空参读取:

java 复制代码
package IOCharStream;

import java.io.FileReader;
import java.io.IOException;

public class CharStreamDemo1 {
    public static void main(String[] args) throws IOException {
        /*
            字符输入流的使用
         */

        //1.创建对象
        FileReader fr = new FileReader("D:\\IdeaProjects\\HelloWord\\src\\IOCharStream\\hhh.txt");

        //2.读取数据 read() 空参
        int ch;
        while((ch = fr.read()) != -1){
            System.out.print((char)ch);
        }

        //read() 细节:
        //1.默认一个字节一个字节读取,但是遇到中文会一次读 3 个字节(默认UTF-8)
        //2.该方法读取的字符会将二进制转成十进制,这个十进制也表示在字符集上的数字
        //3.如果想看中文汉字,直接将这些十进制数据强转即可

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

② 带参 read() 方法详解:

java 复制代码
package IOCharStream;

import java.io.FileReader;
import java.io.IOException;

public class CharStreamDemo2 {
    public static void main(String[] args) throws IOException {
        /*
            public int read(char[]  buffer)     //一次读取多个数据,参数为char类型数组,返回值为读取到的字符个数
         */

        //1.创建对象
        FileReader fr = new FileReader("D:\\IdeaProjects\\HelloWord\\src\\IOCharStream\\hhh.txt");

        //2.读取数据
        char[] chars = new char[2];         //一次读两个字符
        int len;
        //read(chars):读取数据,解码,强制类型转换,三合一,将强转之后的字符放入数组中
        //带参read = 空参read + 强转
        while((len = fr.read(chars)) != -1){
            //把数组中的数据变成字符串再打印
            System.out.print(new String(chars, 0 , len));           //转字符串细节:从0索引到len索引转
        }

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

二、Writer ------ 字符输出流

Writer 是字符输出流的抽象总类,它不能直接创建对象。但有 FileWriter 继承自它,可以实现对本地文件数据的输出。

FileWriter 的使用方法如下:

① 利用构造方法生成对象。

细节1:参数是字符串表示的路径或者 File 对象表示的路径都可以。

细节2:如果文件不存在,会自动创建一个新的文件,但要保证父级路径是存在的。

细节3:如果文件已存在,默认覆写文件,如果不想清空可以打开续写开关。

② 调用成员方法写出。

细节:如果 write 方法的参数是一个整数,实际上写到本地文件中的是这个整数在字符集上对应的 char 字符。

③ 释放资源。

方法用例:

java 复制代码
package IOCharStream;

import java.io.FileWriter;
import java.io.IOException;

public class CharStreamDemo3 {
    public static void main(String[] args) throws IOException {
        /*
            文件写出
         */

        FileWriter fw = new FileWriter("D:\\IdeaProjects\\HelloWord\\src\\IOCharStream\\heyhey.txt");

        //1.一次写一个字符

        fw.write(25105);            //根据字符集编码方式(UTF-8)进行编码,把编码之后的数据写到文件中去

        fw.close();

        //2.一次写一个字符串
        FileWriter fw2 = new FileWriter("D:\\IdeaProjects\\HelloWord\\src\\IOCharStream\\heyhey.txt");

        fw2.write("嘿嘿嘿");

        fw2.close();

        //3.用字符数组写出
        char[] chars = {'我','喜','欢','你'};

        FileWriter fw3 = new FileWriter("D:\\IdeaProjects\\HelloWord\\src\\IOCharStream\\heyhey.txt",true);

        fw3.write(chars);

        fw3.close();

        //4.写出字符串的一部分
        FileWriter fw4 = new FileWriter("D:\\IdeaProjects\\HelloWord\\src\\IOCharStream\\heyhey.txt");

        fw4.write("嘿嘿嘿",0,2);           //写出0索引起始的2个字符

        fw4.close();

        //5.写出字符数组的一部分
        FileWriter fw5 = new FileWriter("D:\\IdeaProjects\\HelloWord\\src\\IOCharStream\\heyhey.txt",true);

        fw5.write(chars,1,3);               //写出1索引起始的3个字符

        fw5.close();
    }
}

三、字节流和字符流的使用场景

字节流可以拷贝任意类型的文件,而字符流可以读取纯文本文件 中的数据,也可以往纯文本文件 写出数据。

【练习1】递归拷贝文件夹(拷贝文件都用字节流)。

java 复制代码
package IOCharStream;

import java.io.*;

public class CharStreamTest1 {
    public static void main(String[] args) throws IOException {
            /*
        拷贝一个文件夹 D:\IdeaProjects\HelloWord\src\IOCharStream\MyFiles
        to
        D:\IdeaProjects\HelloWord\src\IOCharStream\CopiedFiles
     */

        //1.创建对象表示数据源
        File src = new File("D:\\IdeaProjects\\HelloWord\\src\\IOCharStream\\MyFiles");

        //2.创建对象表示目的地
        File dest = new File("D:\\IdeaProjects\\HelloWord\\src\\IOCharStream\\CopiedFiles");

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

    /*
        作用:拷贝文件夹
     */
    private static void copydir(File src, File dest) throws IOException {
        //先创建dest文件夹,防止它不存在
        dest.mkdirs();
        //递归
        //1.进入数据源
        File[] files = src.listFiles();

        //2.遍历数组
        for (File file : files) {
            //3.判断是文件,直接拷贝,判断是文件夹,递归
            if(file.isFile()){
                //细节:拷贝时一定是从文件开始,到文件结束,因此目的地路径要写成文件
                // 新建一个对象,父级路径是目的地文件夹,子级路径(文件名)可以用getName方法获取
                FileInputStream fis = new FileInputStream(file);
                FileOutputStream fos = new FileOutputStream(new File(dest, file.getName()));
                byte[] bytes = new byte[1024 * 1024 * 5];
                int len;
                while((len = fis.read(bytes)) != -1){
                    fos.write(bytes,0,len);
                }
                fos.close();
                fis.close();
            }else{
                //如果是文件夹,递归
                copydir(file,new File(dest, file.getName()));

            }
        }

    }

}

【练习2】文件加密。

为了保证文件的安全性,就需要对原始文件进行加密存储,再使用的时候再对其进行解密处理。

加密原理:

对原始文件中的每一个字节数据进行更改,然后将更改以后的数据存储到新的文件中。

解密原理:

读取加密之后的文件,按照加密的规则反向操作,变成原始文件。

java 复制代码
package IOCharStream;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CharStreamTest2 {
    public static void main(String[] args) throws IOException {
        /*
            为了保证文件的安全性,就需要对原始文件进行加密存储,再使用的时候再对其进行解密处理。
            加密原理:
            对原始文件中的每一个字节数据进行更改,然后将更改以后的数据存储到新的文件中。
            解密原理:
            读取加密之后的文件,按照加密的规则反向操作,变成原始文件。

            ^:异或
                两边相同:false
                两边不同:true

            被加密的图片:D:\IdeaProjects\HelloWord\src\IOCharStream\舞动新春.png

         */

        //1.创建对象关联原始文件
        FileInputStream fis = new FileInputStream("D:\\IdeaProjects\\HelloWord\\src\\IOCharStream\\舞动新春.png");

        //2.创建加密后的文件对象
        FileOutputStream fos = new FileOutputStream("D:\\IdeaProjects\\HelloWord\\src\\IOCharStream\\ency.png");

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

        fos.close();

        //解密时互换路径即可

    }
}

【练习3】排序。修改文件中的数据,让他们排序:

2-1-9-4-7-8

to

1-2-4-7-8-9

【解法1】使用ArrayList和Collections排序。

java 复制代码
package IOCharStream;

import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

public class CharStreamTest3 {
    public static void main(String[] args) throws IOException {
        /*
            修改文件中的数据,让他们排序
            2-1-9-4-7-8
            to
            1-2-4-7-8-9
         */

        //1.读入源文件
        FileReader fr = new FileReader("D:\\IdeaProjects\\HelloWord\\src\\IOCharStream\\File.txt");
        StringBuilder sb = new StringBuilder();

        //2.将数据存入sb
        int ch;
        while((ch = fr.read()) != -1){
            sb.append((char)ch);
        }

        //sb转字符串
        String str = sb.toString();

        //切割字符串
        String[] arrStr = str.split("-");

        //变成整数列表
        ArrayList<Integer> arr = new ArrayList<>();
        for (String s : arrStr) {
            arr.add(Integer.parseInt(s));
        }

        //调用Collections工具类排序
        Collections.sort(arr);

        System.out.println(arr);

        //转回字符且拼接-写出文件
        FileWriter fw = new FileWriter("D:\\IdeaProjects\\HelloWord\\src\\IOCharStream\\File.txt");
        for(int i = 0; i < arr.size(); i++){
            //是最后一个元素,不附 - ,不是最后一个元素,附上 -
            if(i == arr.size() - 1){
                //把每一位Integer数字转字符串原样写出
                fw.write(arr.get(i) + "");
            }else{
                fw.write(arr.get(i) + "-");
            }
        }

        fw.close();
    }
}

【解法2】使用流处理。

java 复制代码
package IOCharStream;

import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

public class CharStreamTest4 {
    public static void main(String[] args) throws IOException {
        /*
            修改文件中的数据,让他们排序
            2-1-9-4-7-8
            to
            1-2-4-7-8-9
         */

        //1.读入源文件
        FileReader fr = new FileReader("D:\\IdeaProjects\\HelloWord\\src\\IOCharStream\\File.txt");
        StringBuilder sb = new StringBuilder();

        //2.将数据存入sb
        int ch;
        while((ch = fr.read()) != -1){
            sb.append((char)ch);
        }

        fr.close();

        //使用ArrayList的流处理
        Integer[] arr = Arrays.stream(sb.toString()
                        .split("-"))
                .map(Integer::parseInt)
                .sorted()
                .toArray(Integer[]::new);

        //转回字符且拼接-写出文件
        //把原字符串的分隔符修改为-
        String str = Arrays.toString(arr).replaceAll(", ","-");      //[1, 2, 4, 7, 8, 9]
        System.out.println(str);        //[1-2-4-7-8-9]
        //截取中间的数字
        String result = str.substring(1, str.length() - 1);

        //写出数据
        FileWriter fw = new FileWriter("D:\\IdeaProjects\\HelloWord\\src\\IOCharStream\\File.txt");

        fw.write(result);

        fw.close();
    }
}
相关推荐
blammmp9 分钟前
Java:数据结构-枚举
java·开发语言·数据结构
何曾参静谧21 分钟前
「C/C++」C/C++ 指针篇 之 指针运算
c语言·开发语言·c++
暗黑起源喵27 分钟前
设计模式-工厂设计模式
java·开发语言·设计模式
WaaTong32 分钟前
Java反射
java·开发语言·反射
Troc_wangpeng33 分钟前
R language 关于二维平面直角坐标系的制作
开发语言·机器学习
努力的家伙是不讨厌的35 分钟前
解析json导出csv或者直接入库
开发语言·python·json
Envyᥫᩣ1 小时前
C#语言:从入门到精通
开发语言·c#
云空1 小时前
《Python 与 SQLite:强大的数据库组合》
数据库·python·sqlite
九圣残炎1 小时前
【从零开始的LeetCode-算法】1456. 定长子串中元音的最大数目
java·算法·leetcode
wclass-zhengge1 小时前
Netty篇(入门编程)
java·linux·服务器