IO流之字符流
创始人
2025-05-29 18:54:00

文章目录

    • 1. 字符流概述
    • 2. 编码表
    • 3. 编码和解码
    • 4. 写数据的方式
    • 5. 读数据的方式
    • 6. 转换流的子类
    • 7. 字符缓冲流
      • 7.1 特有功能
      • 7.2 复制文件
      • 7.3 点名器
      • 7.4 总分排名
    • 8. 复制文件夹
      • 8.1 复制单级文件夹
      • 8.2 复制多级文件夹

1. 字符流概述

由于字节流操作中文不是特别的方便,所以 Java 就提供了字符流。

字符流 = 字节流 + 编码表

用字节流复制文本文件时,文本文件也会有中文,但是不会出现问题,原因是最终底层操作会自动将复制到的内容进行字节拼接成中文,那么如何识别它是中文呢?
汉字在存储的时候,无论选择哪种编码存储,第一个字节都是负数。

2. 编码表

基础知识:
① 计算机中存储的信息都是用二进制数表示的,我们在屏幕上看到的英文、汉字等字符都是二进制数转换之后的结果;
② 按照某种规则,将字符存储到计算机中,称为编码。反之,将存储在计算机中的二进制数按照某种规则解析显示出来,称为解码。按照 A 编码存储,就必须按照 A 编码解析,这样才能显示正确的文本符号,否则就会导致乱码;
③ 字符编码就是一套自然语言的字符与二进制数之间的对应规则(A,65);
④ 常见的字符集有 ASCLL 字符集、GBXXX字符集、Unicode 字符集等,其中 GBK 是最常用的中文码表,Unicode 字符集是为表达任意语言的任意字符而设计的,被称为统一码、标准万国码,最为常用的是 UTF-8 编码,互联网工程工作小组要求所有互联网协议都必须支持 UTF-8 编码

采用何种规则编码,就要采用对应的规则解码,否则就会出现乱码!

3. 编码和解码

① 编码:
byte[] getBytes():使用平台默认的字符集将该 String 编码为一系列字节,将结果存储到新的字节数组中;
byte[] getBytes(String charsetName):使用指定的字符集将该 String 编码为一系列字节,将结果存储到新的字节数组中。

② 解码:
String(byte[] bytes):通过使用平台的默认字符集解码指定的字节数组来构造新的 String;
String(byte[] bytes, String charsetName):通过指定的字符集解码指定的字节数组来构造新的 String。

//Test.javapackage com.zxe;import java.io.*;public class Test {public static void main(String[] args) throws IOException {String s = "中国伟大";byte[] bys = s.getBytes("GBK");String ss = new String(bys, "GBK");System.out.println(ss);}
}

在这里插入图片描述

以上是字符串中的编码和解码问题,接下来我们看一下字符流中的编码解码问题。

① InputStreamRead:是从字节流到字符流的桥梁,它读取字节,并使用指定的编码将其解码为字符,它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集;
② OutputStreamWriter:是从字符流到字节流的桥梁,使用指定的编码将写入的字符编码为字节,它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。


OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("idea_test\\myCharStream.txt"), "GBK");
osw.write("我爱你中国!");
osw.close();
InputStreamReader isr = new InputStreamReader(new FileInputStream("idea_test\\myCharStream.txt"), "GBK");
int ch;
while ((ch = isr.read()) != -1) {System.out.print((char) ch);
}
isr.close();

4. 写数据的方式

在这里插入图片描述
在这里插入图片描述

用字符流写数据是有缓冲的,写入的内容在文件中一下显示不出来,需要用刷新流方法 flush() 实现刷新!

//Test.javapackage com.zxe;import java.io.*;public class Test {public static void main(String[] args) throws IOException {OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("idea_test\\myCharStream.txt"));osw.write(97);char[] chs = {'a', 'b', 'c', 'd'};osw.write(chs);osw.write(chs, 0, chs.length);osw.write("qweqq");osw.write("qweqq", 2, 3);osw.flush();osw.close();}
}

在这里插入图片描述

从 off 索引开始切入,取 len 长度,注意 len 代表的是所取字符的个数,并不是索引!

5. 读数据的方式

在这里插入图片描述


InputStreamReader isr = new InputStreamReader(new FileInputStream("idea_test\\myCharStream.txt"));
//一次读一个字符数据
int ch;
while ((ch = isr.read()) != -1) {System.out.print((char) ch);
}
//一次读一个字符数组数据
char[] chs = new char[1024];
int len;
while ((len = isr.read(chs)) != -1) {System.out.println(new String(chs, 0, len));
}
isr.close();

字符流读数据和字节流读数据的格式是一样的!

6. 转换流的子类

需求:把模块目录下的某文件内容复制到模块目录下的另一文件中。

分析:
① 我们可以使用上面的 InputStreamReader 和 OutputStreamWriter 转换流进行操作,但转换流的名字太长,而我们常见的操作都是按照本地默认编码实现的,所以,为了简化书写,转换流为我们提供了对应的子类;
② FileReader(String fileName),用于读取字符文件的便捷类;
③ FileWriter(String fileName),用于写入字符文件的便捷类。

//Test.javapackage com.zxe;import java.io.*;public class Test {public static void main(String[] args) throws IOException {FileReader fr = new FileReader("idea_test\\myCharStream.txt");FileWriter fw = new FileWriter("idea_test\\copy.txt");char[] chs = new char[1024];int len;while ((len = fr.read(chs)) != -1) {fw.write(chs, 0, len);}fr.close();fw.close();}
}

在这里插入图片描述

如果不指定编码类型,我们完全可以使用其子类,简化代码!

7. 字符缓冲流

字符缓冲流:
① BufferedWriter:将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可以指定缓冲区大小,或者可以接受默认大小,默认值足够大,可用于大多数用途;
② BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符、数组和行的高效读取,可以指定缓冲区大小,或者可以使用默认大小,默认值足够大,可用于大多数用途。


BufferedWriter bw = new BufferedWriter(new FileWriter("idea_test\\myCharStream.txt"));
String s = "我爱你中国!";
bw.write(s, 0, s.length());
bw.close();

7.1 特有功能

① newLine():写一行行分隔符。行分隔符字符串由系统属性定义,该换行适用于任何系统;
② readLine():读一行文字。结果包含行的内容的字符串,不包括任何行终止字符,如果流的结尾已经到达,则为 null。

//Test.javapackage com.zxe;import java.io.*;public class Test {public static void main(String[] args) throws IOException {BufferedWriter bw = new BufferedWriter(new FileWriter("idea_test\\myCharStream.txt"));BufferedReader br = new BufferedReader(new FileReader("idea_test\\myCharStream.txt"));for (int i = 0; i < 10; i++) {bw.write("hello" + i);bw.newLine();bw.flush();}String line;while ((line = br.readLine()) != null) {System.out.println(line);}br.close();bw.close();}
}

在这里插入图片描述

在这里插入图片描述

注意一次读取一行的时候,这里是只读内容不读换行符号,所以要想换行得用 println!

7.2 复制文件

//Test.javapackage com.zxe;import java.io.*;public class Test {public static void main(String[] args) throws IOException {BufferedWriter bw = new BufferedWriter(new FileWriter("idea_test\\copy.txt"));BufferedReader br = new BufferedReader(new FileReader("idea_test\\myCharStream.txt"));String line;while ((line = br.readLine()) != null) {bw.write(line);bw.newLine();bw.flush();}br.close();bw.close();}
}

用字符缓冲流的特有功能复制文件,是我们最常用的一种方法!

7.3 点名器

需求:给出一个文件里面存储了班级同学的姓名,每一个姓名占一行,要求通过程序实现随机点名器。

思路:
① 创建字符缓冲输入流对象;
② 创建 ArrayList 集合对象;
③ 调用字符缓冲输入流对象的方法读数据;
④ 把读取到的字符串数据存储到集合中;
⑤ 释放资源;
⑥ 使用 Random 产生一个随机数,随机数的范围在 [0,集合的长度];
⑦ 把第 6 步产生的随机数作为索引到 ArrayList 集合中获取值;
⑧ 把第 7 步得到的数据输出在控制台。

package com.zxe;import java.io.*;
import java.util.ArrayList;
import java.util.Random;public class Test {public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new FileReader("idea_test\\student.txt"));ArrayList array = new ArrayList<>();String line;while ((line = br.readLine()) != null) {array.add(line);}Random r = new Random();int index = r.nextInt(array.size());System.out.println(array.get(index));}
}

在这里插入图片描述

在这里插入图片描述

7.4 总分排名

需求:键盘录入 5 个学生信息(学号,姓名,语文成绩,数学成绩,英语成绩)。要求按照成绩总分从高到低写入文本文件。

思路:
① 定义学生类;
② 创建 TreeSet 集合,通过比较器排序进行排序;
③ 键盘录入学生数据;
④ 创建学生对象,把键盘录入的数据对应赋值给学生的成员变量;
⑤ 把学生对象添加到 TreeSet 集合;
⑥ 创建字符缓冲输出流对象;
⑦ 遍历集合,得到每一个学生对象;
⑧ 把学生对象的数据拼接成指定格式的字符串;
⑨ 调用字符缓冲输出流对象的方法写数据。

package com.zxe;import java.util.Objects;public class Student {private int Sno;private String Sname;private int chinese;private int math;private int english;public Student() {}public Student(int sno, String sname, int chinese, int math, int english) {Sno = sno;Sname = sname;this.chinese = chinese;this.math = math;this.english = english;}public int getSno() {return Sno;}public void setSno(int sno) {Sno = sno;}public String getSname() {return Sname;}public void setSname(String sname) {Sname = sname;}public int getChinese() {return chinese;}public void setChinese(int chinese) {this.chinese = chinese;}public int getMath() {return math;}public void setMath(int math) {this.math = math;}public int getEnglish() {return english;}public void setEnglish(int english) {this.english = english;}public int getSum() {int sum = chinese + math + english;return sum;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;return Sno == student.Sno && chinese == student.chinese && math == student.math && english == student.english && Objects.equals(Sname, student.Sname);}@Overridepublic int hashCode() {return Objects.hash(Sno, Sname, chinese, math, english);}
}
package com.zxe;import java.io.*;
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;public class Test {public static void main(String[] args) throws IOException {//创建TreeSet集合,通过比较器排序法进行排序TreeSet ts = new TreeSet<>(new Comparator() {@Overridepublic int compare(Student o1, Student o2) {int num1 = o2.getSum() - o1.getSum();int num2 = num1 == 0 ? o2.getSno() - o1.getSno() : num1;return num2;}});//键盘录入学生对象并添加到TreeSet集合Scanner sc = new Scanner(System.in);for (int i = 0; i < 5; i++) {System.out.println("请录入第" + (i + 1) + "个同学的信息:");System.out.print("学号:");int sno = sc.nextInt();System.out.print("姓名:");String sname = sc.next();System.out.print("语文成绩:");int chinese = sc.nextInt();System.out.print("数学成绩:");int math = sc.nextInt();System.out.print("英语成绩:");int english = sc.nextInt();Student s = new Student(sno, sname, chinese, math, english);ts.add(s);}//遍历TreeSet集合将学生信息有序写入文本文件BufferedWriter bw = new BufferedWriter(new FileWriter("idea_test\\grades.txt"));bw.write("学号  姓名  语文  数学  英语  总分");bw.newLine();for (Student s : ts) {StringBuilder sb = new StringBuilder();sb.append(s.getSno()).append("  ").append(s.getSname()).append("  ").append(s.getChinese()).append("  ").append(s.getMath()).append("  ").append(s.getEnglish()).append("  ").append(s.getSum());bw.write(sb.toString());bw.newLine();bw.flush();}bw.close();}
}

在这里插入图片描述
在这里插入图片描述

8. 复制文件夹

8.1 复制单级文件夹

package com.zxe;import java.io.*;public class Test {public static void main(String[] args) throws IOException {File srcFolder = new File("F:\\tyut");String srcFolderName = srcFolder.getName();File destFolder = new File("idea_test", srcFolderName);if (!destFolder.exists()) {destFolder.mkdir();}File[] files = srcFolder.listFiles();for (File srcFile : files) {String srcFileName = srcFile.getName();File destFile = new File(destFolder, srcFileName);copyFile(srcFile, destFile);}}public static void copyFile(File srcFile, File destFile) throws IOException {BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));byte[] bys = new byte[1024];int len;while ((len = bis.read(bys)) != -1) {bos.write(bys, 0, len);}bis.close();bos.close();}
}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

8.2 复制多级文件夹

package com.zxe;import java.io.*;public class Test {public static void main(String[] args) throws IOException {File srcFolder = new File("F:\\tyut");File destFolder = new File("idea_test");copyFolder(srcFolder, destFolder);}public static void copyFolder(File srcFolder, File destFolder) throws IOException {if (srcFolder.isDirectory()) {String srcFileName = srcFolder.getName();File newFolder = new File(destFolder, srcFileName);if (!newFolder.exists()) {newFolder.mkdir();}File[] srcFiles = srcFolder.listFiles();for (File srcFile : srcFiles) {copyFolder(srcFile, newFolder);}} else {File newFile = new File(destFolder, srcFolder.getName());copyFile(srcFolder, newFile);}}public static void copyFile(File srcFile, File destFile) throws IOException {BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));byte[] bys = new byte[1024];int len;while ((len = bis.read(bys)) != -1) {bos.write(bys, 0, len);}bis.close();bos.close();}
}

在这里插入图片描述

在这里插入图片描述

判断数据源 File 是否是目录?
① 不是,说明是文件,直接复制,用字节流;
② 是,在目的地下创建和数据源 File 名称一样的目录,获取数据源 File 下所有文件或者目录的 File 数组,遍历该 File 数组,得到每一个 File 对象,最后把该 File 作为数据源 File 对象,递归调用复制文件夹的方法。

相关内容

热门资讯

Opentss代码测试 这是个多方门限签名库,使用rust实现。 代码包含两个功能,秘密共享密钥...
【id:14】【20分】C. ... 题目描述 编写一个函数比较两个字符串,参数是两个字符指针(要求显式定义...
无需公网IP,远程连接SQL ... 文章目录1.前言2.本地安装和设置SQL Server2.1 SQL Server下载2.2 SQL...
WuThreat身份安全云-T... 漏洞名称:CairoSVG 文件服务器端请求伪造 漏洞级别:严重 漏洞编号:CVE-2023-275...
Postgresql源码(10... 1 子事务控制语句分析 1.1 执行savepoint 执行函数: 【立即执行】→De...
python@日期和时间@da... 文章目录python datetimerelativedeltademo`timedelta...
数据库--进阶版-11--SQ... 1.插入数据 ·insert优化: 例如要插入下面这些 insert into tb_...
C语言—文件操作 为什么使用文件使用文件可以直接将数据存放到电脑硬盘上,做到数据的持久化什么是文件硬盘上...
【Zabbix_6.x 第三章... 文章目录👹 关于作者Zabbix 系列文章目录第三章 监控任意主机一、解决第二章登录...
python爬虫可以爬什么 Python爬虫可以爬取的东西有很多,Python爬虫怎么学?简单的分析...
组态王与200SMART之间无... 在实际的工业场合应用中,人机界面跟PLC配套使用是比较常见的现场“CP组合”ÿ...
KaiwuDB 荣获第三届 I... 3月17日,由中国某部电子化标准研究院、苏州金融科技协会、中国计算机用户协会指导&#x...
上海人工智能企业CIMCAI智... 上海人工智能企业CIMCAI智能港口自动化港口数字化码头智慧港航,成熟终端智慧港航人工...
红米note10 pro机型解... 前言。操作解除锁类案例只限于自己的机型, 因手机号长期不用或者忘记密码导致账号锁出现的...
9、Cascaded Diff... 简介 主页:https://cascaded-diffusion.github.io/...
异核通信框架(1)——SMP和... 0.前言         我是菜鸡,很久没有发表文章了。老样子,今天推荐...
Leetcode.2048 下... 题目链接 Leetcode.2048 下一个更大的数值平衡数 Rating : 17...
GBASE南大通用第二届校园大... 第二届校园大使在本周正式集结完毕啦! 全国一共有27所高校近50余名学生报名参加。 各...
Blender Apps?20... 2023 年对 Blender 来说将会是很有趣的一年,除了努力保持核心功能稳定和不断...
Python数据结构与算法(p... 学习材料清华大学博士讲解Python数据结构与算法 B站:https://www.bi...
Docker安装使用Nacos Docker安装使用Nacos1 参考2 Nacos版本2.1 访问地址3 Docker部署Naco...
Spring Boot 接口统... 需求 需求如题,想给一个 spring boot 项目的所有请求路径添加统一前缀&#x...
Boeing MQ-28 Gh... Boeing MQ-28 Ghost Bat作为五代机忠诚僚机的开山之作,今天我们来一...
线性动态规划问题 文章目录1. 三角形中最小路径之和2. 最长递增子序列3. 最长公共子序列 1. 三角形中最小路径之...
携手共赢!菊风荣获三基同创“2... 近年来智能手表市场发展势头迅猛,为满足用户多样化的应用场景,对于音视频能...
CentOS8提高篇3:Cen... 1. 准备工作(需要配置epel, rpmfusion源); 配置e...
计算机组成原理(7)--哈工大 程序中断方式中断的概念I/O中断的产生CPU和打印机部分并行工作程序中断方式的接口电路配置中断请求触...
Amazon S3 客户端:T... TntDrive 是适用于 Windows 的新 Amazon S3 客户端。使用 TntDrive...
java8 jdk1.8在wi... 一、软件下载 1、从网盘获取 java8安装包 2、或者从官网获取(需要提前注册ora...
【 Deep-Shallow ... A Deep-Shallow Fusion Network with Multi-Detail Ex...