JAVA-编程基础-11-04-java IO 字符流

news2024/12/24 8:14:59

Lison <dreamlison@163.com>, v1.0.0, 2023.05.07

JAVA-编程基础-11-04-java IO 字符流

文章目录

  • JAVA-编程基础-11-04-java IO 字符流
    • 字符流Reader 和 Writer
    • 字符输入流(Reader)
      • **FileReader构造方法**
      • **FileReader读取字符数据**
    • 字符输出流(Writer)
      • FileWriter 构造方法
      • FileWriter写入数据

字符流Reader 和 Writer

字符流 Reader 和 Writer 的故事要从它们的类关系图开始,来看图。

在这里插入图片描述

字符流是一种用于读取和写入字符数据的输入输出流。与字节流不同,字符流以字符为单位读取和写入数据,而不是以字节为单位。常用来处理文本信息。

如果用字节流直接读取中文,可能会遇到乱码问题,见下例:

//FileInputStream为操作文件的字符输入流
FileInputStream inputStream = new FileInputStream("files/a.txt");//内容为“Lison 勤学苦练 !!”

int len;
while ((len=inputStream.read())!=-1){
    System.out.print((char)len);
}

运行结果:

运行结果:Lison 勤学苦ç»

在这里插入图片描述

之所以出现乱码是因为在字节流中,一个字符通常由多个字节组成,而不同的字符编码使用的字节数不同。如果我们使用了错误的字符编码,或者在读取和写入数据时没有正确处理字符编码的转换,就会导致读取出来的中文字符出现乱码。

例如,当我们使用默认的字符编码(见上例)读取一个包含中文字符的文本文件时,就会出现乱码。因为默认的字符编码通常是 ASCII 编码,它只能表示英文字符,而不能正确地解析中文字符。

那使用字节流该如何正确地读出中文呢?见下例。


        //FileInputStream为操作文件的字符输入流//内容为“Lison 勤学苦练 !!”
        try (FileInputStream inputStream = new FileInputStream("files/a.txt");){

            byte[] bytes = new byte[1024];
            int len;
            while ((len = inputStream.read(bytes)) != -1) {
                System.out.print(new String(bytes, 0, len));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

运行结果: Lison 勤学苦练

为什么这种方式就可以呢?

因为我们拿 String 类进行了解码,查看new String(byte bytes[], int offset, int length)的源码就可以发现,该构造方法有解码功能

    public String(byte bytes[], int offset, int length) {
        checkBounds(bytes, offset, length);
        this.value = StringCoding.decode(bytes, offset, length);
    }

继续追看 StringCoding.decode() 方法调用的 defaultCharset() 方法,会发现默认编码是UTF-8,代码如下

  static char[] decode(byte[] ba, int off, int len) {
        String csn = Charset.defaultCharset().name();
        try {
            // use charset name decode() variant which provides caching.
            return decode(csn, ba, off, len);
        } catch (UnsupportedEncodingException x) {
            warnUnsupportedCharset(csn);
        }
  }
    public static Charset defaultCharset() {
        if (defaultCharset == null) {
            synchronized (Charset.class) {
                String csn = AccessController.doPrivileged(
                    new GetPropertyAction("file.encoding"));
                Charset cs = lookup(csn);
                if (cs != null)
                    defaultCharset = cs;
                else
                    defaultCharset = forName("UTF-8");
            }
        }
        return defaultCharset;
    }

在 Java 中,常用的字符编码有 ASCII、ISO-8859-1、UTF-8、UTF-16 等。其中,ASCII 和 ISO-8859-1 只能表示部分字符,而 UTF-8 和 UTF-16 可以表示所有的 Unicode 字符,包括中文字符。

当我们使用 new String(byte bytes[], int offset, int length) 将字节流转换为字符串时,Java 会根据 UTF-8 的规则将每 3 个字节解码为一个中文字符,从而正确地解码出中文。

尽管字节流也有办法解决乱码问题,但不够直接,于是就有了字符流,专门用于处理文本文件(音频、图片、视频等为非文本文件)。

从另一角度来说:字符流 = 字节流 + 编码表

字符输入流(Reader)

java.io.Reader字符输入流超类(父类),它定义了字符输入流的一些共性方法:

  • 1、close():关闭此流并释放与此流相关的系统资源。
  • 2、read():从输入流读取一个字符。
  • 3、read(char[] cbuf):从输入流中读取一些字符,并将它们存储到字符数组 cbuf

FileReader 是 Reader 的子类,用于从文件中读取字符数据。它的主要特点如下:

  • 可以通过构造方法指定要读取的文件路径。
  • 每次可以读取一个或多个字符。
  • 可以读取 Unicode 字符集中的字符,通过指定字符编码来实现字符集的转换。

FileReader构造方法

  • 1、FileReader(File file):创建一个新的 FileReader,参数为File对象
  • 2、FileReader(String fileName):创建一个新的 FileReader,参数为文件名。

代码示例如下:

// 使用File对象创建流对象
File file = new File("files/a.txt");
FileReader fr = new FileReader(file);

// 使用文件名称创建流对象
FileReader fr = new FileReader("files/b.txt");

FileReader读取字符数据

①、读取字符read方法,每次可以读取一个字符,返回读取的字符(转为 int 类型),当读取到文件末尾时,返回-1。代码示例如下:

// 使用文件名称创建流对象
FileReader fr = new FileReader("files/abc.txt");
// 定义变量,保存数据
int b;
// 循环读取
while ((b = fr.read())!=-1) {
    System.out.println((char)b);
}
// 关闭资源
fr.close();

②、读取指定长度的字符read(char[] cbuf, int off, int len),并将其存储到字符数组中。其中,cbuf 表示存储读取结果的字符数组,off 表示存储结果的起始位置,len 表示要读取的字符数。代码示例如下:

			File textFile = new File("files/abc.txt");
        // 给一个 FileReader 的示例
        // try-with-resources FileReader
        try(FileReader reader = new FileReader(textFile);) {
            // read(char[] cbuf)
            char[] buffer = new char[1024];
            int len;
            while ((len = reader.read(buffer, 0, buffer.length)) != -1) {
                System.out.print(new String(buffer, 0, len));
            }
        }catch (Exception e){

        }

使用 FileReader 从文件中读取字符数据,并将其存储到一个大小为 1024 的字符数组中。每次读取 len 个字符,然后使用 String 构造方法将其转换为字符串并输出。

FileReader 实现了 AutoCloseable 接口,因此可以使用 try-with-resources语句自动关闭资源,避免了手动关闭资源的繁琐操作。

字符输出流(Writer)

java.io.Writer字符输出流类的超类(父类),可以将指定的字符信息写入到目的地,来看它定义的一些共性方法:

  • 1、write(int c) 写入单个字符。
  • 2、write(char[] cbuf) 写入字符数组。
  • 3、write(char[] cbuf, int off, int len) 写入字符数组的一部分,off为开始索引,len为字符个数。
  • 4、write(String str) 写入字符串。
  • 5、write(String str, int off, int len) 写入字符串的某一部分,off 指定要写入的子串在 str 中的起始位置,len 指定要写入的子串的长度。
  • 6、flush() 刷新该流的缓冲。
  • 7、close() 关闭此流,但要先刷新它。

java.io.FileWriter 类是 Writer 的子类,用来将字符写入到文件。

FileWriter 构造方法

  • FileWriter(File file): 创建一个新的 FileWriter,参数为要读取的File对象。
  • FileWriter(String fileName): 创建一个新的 FileWriter,参数为要读取的文件的名称。
// 第一种:使用File对象创建流对象
File file = new File("files/a.txt");
FileWriter fw = new FileWriter(file);

// 第二种:使用文件名称创建流对象
FileWriter fw = new FileWriter("files/b.txt");

FileWriter写入数据

①、写入字符write(int b) 方法,每次可以写出一个字符,代码示例如下:

FileWriter fw = null;
try {
    fw = new FileWriter("output.txt");
    fw.write(72); // 写入字符'H'的ASCII码
    fw.write(101); // 写入字符'e'的ASCII码
    fw.write(108); // 写入字符'l'的ASCII码
    fw.write(108); // 写入字符'l'的ASCII码
    fw.write(111); // 写入字符'o'的ASCII码
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
        if (fw != null) {
            fw.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

在这个示例代码中,首先创建一个 FileWriter 对象 fw,并指定要写入的文件路径 “output.txt”。然后使用 fw.write() 方法将字节写入文件中,这里分别写入字符’H’、‘e’、‘l’、‘l’、'o’的 ASCII 码。最后在 finally 块中关闭 FileWriter 对象,释放资源。

需要注意的是,使用 write(int b) 方法写入的是一个字节,而不是一个字符。如果需要写入字符,可以使用 write(char cbuf[])write(String str) 方法。

写入字符数组write(char[] cbuf) 方法,将指定字符数组写入输出流。代码示例如下:

FileWriter fw = null;
try {
    fw = new FileWriter("output.txt");
    char[] chars = {'H', 'e', 'l', 'l', 'o'};
    fw.write(chars); // 将字符数组写入文件
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
        if (fw != null) {
            fw.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1127148.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解决样本不均衡问题

一、样本不均衡问题 样本&#xff08;类别&#xff09;不平衡指的是分类任务中不同类别的训练样例数目差别很大的情况&#xff0c;一般地&#xff0c;样本类别比例&#xff08;多数类VS少数类&#xff09;明显大于1&#xff1a;1&#xff08;例如4&#xff1a;1&#xff09;就…

软考信息安全工程师备考

软考信息安全工程师备考 报名 公告地址 通知是否有考试和考试安排的公告 https://www.ruankao.org.cn/arrange报名地址 https://bm.ruankao.org.cn/sign/welcome刷题 51cto刷题小程序 5cto题库点击进去选择信息安全工程师 可以刷选择题和大题 还可以刷真题非常好用 …

Mysql数据库指定某数据库或某表赋予增删改查操作权限各类划分权限的方法总结实战

一、mysql创建用户只赋予指定数据库的增删改查操作权限 在日常生产运维工作中&#xff0c;我们经常需要给其他厂商或者合作伙伴提供数据库的账号&#xff0c;并且需要指定某个用户只能查询指定的数据库&#xff0c;并且赋予增删改查的指定权限。 &#xff08;1&#xff09;创…

面试算法38:每日温度

题目 输入一个数组&#xff0c;它的每个数字是某天的温度。请计算每天需要等几天才会出现更高的温度。例如&#xff0c;如果输入数组[35&#xff0c;31&#xff0c;33&#xff0c;36&#xff0c;34]&#xff0c;那么输出为[3&#xff0c;1&#xff0c;1&#xff0c;0&#xff…

软硬件架构分层总结

一、前言 软件系统很多架构图我们经常看到是这样的三段 就是这三段就可以演化出很多层 二、硬件架构分层 硬件层&#xff0c;基本是计算机硬件的体系结构&#xff0c;包括硬盘设备&#xff0c;cpu&#xff0c;内存&#xff0c;控制器&#xff0c;运算器&#xff0c;寄存器&am…

清除excel中换行符方法

1、选择要删除或替换换行符的单元格。 2、按 Ctrl H 以打开“查找和替换”对话框。 3、在“查找内容”栏中输入Ctrl J 或 Ctrl Enter 这时会出现一个闪烁的小点。如下图所示&#xff0c;然后点击全部替换即可。

【机器学习合集】参数初始化合集 ->(个人学习记录笔记)

文章目录 综述1. 全零与随机初始化2. 标准初始化(固定方差)3. Xavier初始化(方差缩放)4. He初始化5. 正交初始化6. MSRA初始化 综述 这些是不同的权重初始化方法&#xff0c;用于初始化神经网络的权重参数。它们的主要区别在于初始化权重的策略和数学原理。以下是这些初始化方法…

RTI-DDS代码分析使用介绍

DDS(Data Distribution Service数据分发服务)是对象管理组织OMG的有关分布式实时系统中数据发布的规范。 DDS规范采用了发布/订阅体系结构&#xff0c;但对实时性要求提供更好的支持。DDS是以数据为中心的发布/订阅通信模型。 以下工程基于rti_connext_dds-7.2.0 hello_world.…

Spark简单回顾

星光下的赶路人star的个人主页 大鹏一日同风起&#xff0c;扶摇直上九万里 文章目录 1、Spark1.1 Spark入门1.1.1 Spark部署模式1.1.2 常用端口 1.2 SparkCore1.2.1 RDD不可变和五大属性1.2.2 RDD的弹性1.2.3 cache和Checkpoint的区别1.2.4 算子 1.3 SparkSQL1.4 内核1.4.1提交…

在Linux上安装RStudio工具并实现本地远程访问【内网穿透】

文章目录 前言1. 安装RStudio Server2. 本地访问3. Linux 安装cpolar4. 配置RStudio server公网访问地址5. 公网远程访问RStudio6. 固定RStudio公网地址 前言 RStudio Server 使你能够在 Linux 服务器上运行你所熟悉和喜爱的 RStudio IDE&#xff0c;并通过 Web 浏览器进行访问…

音频怎么录制?让你轻松成为录音专家!

“音频可以录制吗&#xff1f;如果可以那应该怎么去操作呢&#xff1f;参加了一个配音比赛&#xff0c;需要录制自己配音的视频&#xff0c;但是我不懂怎么录制音频&#xff0c;眼看比赛就要截止了&#xff0c;真的很着急&#xff0c;大家帮帮我。” 音频录制是一项常见但强大…

【数据结构初阶】算法的时间复杂度和空间复杂度

算法的时间复杂度和空间复杂度 1.算法效率1.1 如何衡量一个算法的好坏1.2 算法的复杂度 2.时间复杂度2.1 时间复杂度的概念2.2 大O的渐进表示法2.3常见时间复杂度计算举例 3.空间复杂度4. 常见复杂度对比 1.算法效率 1.1 如何衡量一个算法的好坏 如何衡量一个算法的好坏呢&am…

【pdf密码】为什么我的PDF文件不能复制文字?

大家现在接触PDF文件越来越多&#xff0c;有的时候在网上下载的PDF文件打开之后&#xff0c;发现选中文字之后无法复制。甚至其他功能也都无法使用&#xff0c;这是怎么回事&#xff1f;该怎么办&#xff1f; 当我们发现文件打开之后&#xff0c;编辑功能无法使用&#xff0c;很…

设置中添加UI设置系统默认NTP服务器

经常遇到客户在内网中使用无法与ntp服务器通讯导致系统时间错乱&#xff0c;他们想自己替换ntp地址要么是用adb命令要么是重新刷机&#xff0c;这样比较浪费客户的时间。 看了一下Android系统中选择ntp地址的逻辑&#xff0c;发现在framework中已经有了个ntp地址那么系统将会选…

window10彻底关闭系统管理员控制(所有软件以管理员身份运行)

window10彻底关闭系统管理员控制&#xff08;所有软件以管理员身份运行&#xff09; gpedit.msc》计算机配置》windows设置》安全设置》安全选项》 1.用户账户控制&#xff1a;以管理员批准模式运行所有管理员 2.用户账户控制&#xff1a;用于内置管理员账户的管理员批准模式 1…

GeoHash分享

写在前边 复制的一个内部分享&#xff0c;所以可能更偏向PPT性质&#xff0c;本文提出的问题&#xff0c;在末尾参考材料中都会有所提及&#xff0c;包括更深层次的实现原理和各大API对于GeoHash的优化。感兴趣的读者可以拓展看一下。 START GeoHash是一种地址编码&#xff…

又被罚了~新生支付

近日&#xff0c;中国人民银行海南省分行公布行政处罚公示信息内容&#xff0c;具有清算机构新生支付有限公司因存违规行为领罚款单。 行政处罚决定书批准文号“琼银罚决字〔2023〕22号”表明&#xff0c;新生支付有限公司&#xff08;通称“新生支付”&#xff09;存有三项违…

深入 Maven:构建杰出的软件项目的完美工具

掌握 Meven&#xff1a;构建更强大、更智能的应用程序的秘诀 Maven1.1 初识Maven1.1.1 什么是Maven1.1.2 Maven的作用 02. Maven概述2.1 Maven介绍2.2 Maven模型2.3 Maven仓库2.4 Maven安装2.4.1 下载2.4.2 安装步骤 03. IDEA集成Maven3.1 配置Maven环境3.1.1 当前工程设置3.1.…

PX4-Autopilot下载与编译

文章目录 1 Git clone 代码2 下载子模块3 编译4 可能遇到的问题参考 1 Git clone 代码 Github Repository 链接&#xff1a;PX4-Autopilot 查看现有版本&#xff1a; 在终端用命令下载&#xff0c;-b表示branch git clone -b v1.14.0 https://github.com/PX4/PX4-Autopilot.…

最新Workerman 在线客服系统源码/附搭建教程-ThinkPHP网站在线客服系统源码

源码简介&#xff1a; Workerman开发的Ai智能客服在线客服系统网站源码,里面有附带安装教程文档搭建教程。它是最新Workerman 在线客服系统源码。 源码链接&#xff1a; 网盘源码 密码&#xff1a;hma8 源码特点&#xff1a; 作为网站在线客服系统源码&#xff0c;它有下…