javaIO流之转换流

news2024/10/5 14:34:00

目录

  • 简介
  • 一、编码和解码
  • 二、字符集
    • 2.1ASCII 字符集
    • 2.2Unicode 字符集
    • 2.3GBK 字符集
  • 三、乱码
  • 四、InputStreamReader
    • 4.1构造方法
    • 4.2解决编码问题
  • 五、OutputStreamWriter
  • 六、小结

简介

转换流可以将一个字节流包装成字符流,或者将一个字符流包装成字节流。这种转换通常用于处理文本数据,如读取文本文件或将数据从网络传输到应用程序。

转换流主要有两种类型:InputStreamReader 和 OutputStreamWriter。

InputStreamReader 将一个字节输入流转换为一个字符输入流,而 OutputStreamWriter 将一个字节输出流转换为一个字符输出流。它们使用指定的字符集将字节流和字符流之间进行转换。常用的字符集包括 UTF-8、GBK、ISO-8859-1 等。
在这里插入图片描述

一、编码和解码

在计算机中,数据通常以二进制形式存储和传输。

  • 编码就是将原始数据(比如说文本、图像、视频、音频等)转换为二进制形式。
  • 解码就是将二进制数据转换为原始数据,是一个反向的过程。

常见的编码和解码方式有很多,举几个例子:

  • ASCII 编码和解码:在计算机中,常常使用 ASCII 码来表示字符,如键盘上的字母、数字和符号等。例如,字母 A 对应的 ASCII 码是 65,字符 + 对应的 ASCII 码是 43。
  • Unicode 编码和解码:Unicode 是一种字符集,支持多种语言和字符集。在计算机中,Unicode 可以使用 UTF-8、UTF-16 等编码方式将字符转换为二进制数据进行存储和传输。
  • Base64 编码和解码:Base64 是一种将二进制数据转换为 ASCII 码的编码方式。它将 3 个字节的二进制数据转换为 4 个 ASCII 字符,以便在网络传输中使用。例如,将字符串 “Hello, world!” 进行 - Base64 编码后,得到的结果是 “SGVsbG8sIHdvcmxkIQ==”。
  • 图像编码和解码:在图像处理中,常常使用 JPEG、PNG、GIF 等编码方式将图像转换为二进制数据进行存储和传输。在解码时,可以将二进制数据转换为图像,以便显示或处理。
  • 视频编码和解码:在视频处理中,常常使用 H.264、AVC、MPEG-4 等编码方式将视频转换为二进制数据进行存储和传输。在解码时,可以将二进制数据转换为视频,以便播放或处理。

简单一点说就是:

  • 编码:字符(能看懂的)–>字节(看不懂的)
  • 解码:字节(看不懂的)–>字符(能看懂的)
String str = "追风少年";
String charsetName = "UTF-8";

// 编码
byte[] bytes = str.getBytes(Charset.forName(charsetName));
System.out.println("编码: " + bytes);

// 解码
String decodedStr = new String(bytes, Charset.forName(charsetName));
System.out.println("解码: " + decodedStr);

在这个示例中,首先定义了一个字符串变量 str 和一个字符集名称 charsetName。然后,使用 Charset.forName() 方法获取指定字符集的 Charset 对象。接着,使用字符串的 getBytes() 方法将字符串编码为指定字符集的字节数组。最后,使用 new String() 方法将字节数组解码为字符串。

需要注意的是,在编码和解码过程中,要保证使用相同的字符集,以便正确地转换数据。

二、字符集

Charset:字符集,是一组字符的集合,每个字符都有一个唯一的编码值,也称为码点。

常见的字符集包括 ASCII、Unicode 和 GBK,而 Unicode 字符集包含了多种编码方式,比如说 UTF-8、UTF-16。

在这里插入图片描述

2.1ASCII 字符集

ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)字符集是一种最早的字符集,包含 128 个字符,其中包括控制字符、数字、英文字母以及一些标点符号。ASCII 字符集中的每个字符都有一个唯一的 7 位二进制编码(由 0 和 1 组成),可以表示为十进制数或十六进制数。

ASCII 编码方式是一种固定长度的编码方式,每个字符都使用 7 位二进制编码来表示。ASCII 编码只能表示英文字母、数字和少量的符号,不能表示其他语言的文字和符号,因此在全球范围内的应用受到了很大的限制。

2.2Unicode 字符集

Unicode 包含了世界上几乎所有的字符,用于表示人类语言、符号和表情等各种信息。Unicode 字符集中的每个字符都有一个唯一的码点(code point),用于表示该字符在字符集中的位置,可以用十六进制数表示。

为了在计算机中存储和传输 Unicode 字符集中的字符,需要使用一种编码方式。UTF-8、UTF-16 和 UTF-32 都是 Unicode 字符集的编码方式,用于将 Unicode 字符集中的字符转换成字节序列,以便于存储和传输。它们的差别在于使用的字节长度不同。

UTF-8 是一种可变长度的编码方式,对于 ASCII 字符(码点范围为 0x00~0x7F),使用一个字节表示,对于其他 Unicode 字符,使用两个、三个或四个字节表示。UTF-8 编码方式被广泛应用于互联网和计算机领域,因为它可以有效地压缩数据,适用于网络传输和存储。
UTF-16 是一种固定长度的编码方式,对于基本多语言平面(Basic Multilingual Plane,Unicode 字符集中的一个码位范围,包含了世界上大部分常用的字符,总共包含了超过 65,000 个码位)中的字符(码点范围为 0x0000~0xFFFF),使用两个字节表示,对于其他 Unicode 字符,使用四个字节表示。
UTF-32 是一种固定长度的编码方式,对于所有 Unicode 字符,使用四个字节表示。

2.3GBK 字符集

GBK 包含了 GB2312 字符集中的字符,同时还扩展了许多其他汉字字符和符号,共收录了 21,913 个字符。GBK 采用双字节编码方式,每个汉字占用 2 个字节,其中高字节和低字节都使用了 8 位,因此 GBK 编码共有 2^16=65536 种可能的编码,其中大部分被用于表示汉字字符。

GBK 编码是一种变长的编码方式,对于 ASCII 字符(码位范围为 0x00 到 0x7F),使用一个字节表示,对于其他字符,使用两个字节表示。GBK 编码中的每个字节都可以采用 0x81 到 0xFE 之间的任意一个值,因此可以表示 2^15=32768 个字符。为了避免与 ASCII 码冲突,GBK 编码的第一个字节采用了 0x81 到 0xFE 之间除了 0x7F 的所有值,第二个字节采用了 0x40 到 0x7E 和 0x80 到 0xFE 之间的所有值,共 94 个值。

GB2312 的全名是《信息交换用汉字编码字符集基本集》,也被称为“国标码”。采用了双字节编码方式,每个汉字占用 2 个字节,其中高字节和低字节都使用了 8 位,因此 GB2312 编码共有 2^16=65536 种可能的编码,其中大部分被用于表示汉字字符。GB2312 编码中的每个字节都可以采用 0xA1 到 0xF7 之间的任意一个值,因此可以表示 126 个字符。

GB2312 是一个较为简单的字符集,只包含了常用的汉字和符号,因此对于一些较为罕见的汉字和生僻字,GB2312 不能满足需求,现在已经逐渐被 GBK、GB18030 等字符集所取代。

GB18030 是最新的中文码表。收录汉字 70244 个,采用多字节编码,每个字可以由 1 个、2 个或 4 个字节组成。支持中国国内少数民族的文字,同时支持繁体汉字以及日韩汉字等。

三、乱码

当使用不同的编码方式读取或者写入文件时,就会出现乱码问题,来看示例。

String s = "追风少年!";

try {
    // 将字符串按GBK编码方式保存到文件中
    OutputStreamWriter out = new OutputStreamWriter(
            new FileOutputStream("logs/test_utf8.txt"), "GBK");
    out.write(s);
    out.close();

    FileReader fileReader = new FileReader("logs/test_utf8.txt");
    int read;
    while ((read = fileReader.read()) != -1) {
        System.out.print((char)read);
    }
    fileReader.close();
} catch (IOException e) {
    e.printStackTrace();
}

在上面的示例代码中,首先定义了一个包含中文字符的字符串,然后将该字符串按 GBK 编码方式保存到文件中,接着将文件按默认编码方式(UTF-8)读取,并显示内容。此时就会出现乱码问题,显示为“��Ĭ������”。

这是因为文件中的 GBK 编码的字符在使用 UTF-8 编码方式解析时无法正确解析,从而导致出现乱码问题。

那如何才能解决乱码问题呢?

这就引出我们今天的主角了——转换流。

四、InputStreamReader

java.io.InputStreamReader 是 Reader 类的子类。它的作用是将字节流(InputStream)转换为字符流(Reader),同时支持指定的字符集编码方式,从而实现字符流与字节流之间的转换。

4.1构造方法

  • InputStreamReader(InputStream in): 创建一个使用默认字符集的字符流。
  • InputStreamReader(InputStream in, String charsetName): 创建一个指定字符集的字符流。
    代码示例如下:
InputStreamReader isr = new InputStreamReader(new FileInputStream("in.txt"));
InputStreamReader isr2 = new InputStreamReader(new FileInputStream("in.txt") , "GBK");

4.2解决编码问题

下面是一个使用 InputStreamReader 解决乱码问题的示例代码:

String s = "沉默王二!";

try {
    // 将字符串按GBK编码方式保存到文件中
    OutputStreamWriter outUtf8 = new OutputStreamWriter(
            new FileOutputStream("logs/test_utf8.txt"), "GBK");
    outUtf8.write(s);
    outUtf8.close();

    // 将字节流转换为字符流,使用GBK编码方式
    InputStreamReader isr = new InputStreamReader(new FileInputStream("logs/test_utf8.txt"), "GBK");
    // 读取字符流
    int c;
    while ((c = isr.read()) != -1) {
        System.out.print((char) c);
    }
    isr.close();
} catch (IOException e) {
    e.printStackTrace();
}

由于使用了 InputStreamReader 对字节流进行了编码方式的转换,因此在读取字符流时就可以正确地解析出中文字符,避免了乱码问题。

五、OutputStreamWriter

java.io.OutputStreamWriter 是 Writer 的子类,字面看容易误以为是转为字符流,其实是将字符流转换为字节流,是字符流到字节流的桥梁。

  • OutputStreamWriter(OutputStream in): 创建一个使用默认字符集的字符流。
  • OutputStreamWriter(OutputStream in, String charsetName):创建一个指定字符集的字符流。
    代码示例如下:
OutputStreamWriter isr = new OutputStreamWriter(new FileOutputStream("a.txt"));
OutputStreamWriter isr2 = new OutputStreamWriter(new FileOutputStream("b.txt") , "GBK");

通常为了提高读写效率,我们会在转换流上再加一层缓冲流,来看代码示例:

try {
    // 从文件读取字节流,使用UTF-8编码方式
    FileInputStream fis = new FileInputStream("test.txt");
    // 将字节流转换为字符流,使用UTF-8编码方式
    InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
    // 使用缓冲流包装字符流,提高读取效率
    BufferedReader br = new BufferedReader(isr);
    // 创建输出流,使用UTF-8编码方式
    FileOutputStream fos = new FileOutputStream("output.txt");
    // 将输出流包装为转换流,使用UTF-8编码方式
    OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
    // 使用缓冲流包装转换流,提高写入效率
    BufferedWriter bw = new BufferedWriter(osw);

    // 读取输入文件的每一行,写入到输出文件中
    String line;
    while ((line = br.readLine()) != null) {
        bw.write(line);
        bw.newLine(); // 每行结束后写入一个换行符
    }

    // 关闭流
    br.close();
    bw.close();
} catch (IOException e) {
    e.printStackTrace();
}

在上面的示例代码中,首先使用 FileInputStream 从文件中读取字节流,使用 UTF-8 编码方式进行读取。然后,使用 InputStreamReader 将字节流转换为字符流,使用 UTF-8 编码方式进行转换。接着,使用 BufferedReader 包装字符流,提高读取效率。然后,创建 FileOutputStream 用于输出文件,使用 UTF-8 编码方式进行创建。接着,使用 OutputStreamWriter 将输出流转换为字符流,使用 UTF-8 编码方式进行转换。最后,使用 BufferedWriter 包装转换流,提高写入效率。

六、小结

InputStreamReader 和 OutputStreamWriter 是将字节流转换为字符流或者将字符流转换为字节流。通常用于解决字节流和字符流之间的转换问题,可以将字节流以指定的字符集编码方式转换为字符流,或者将字符流以指定的字符集编码方式转换为字节流。

InputStreamReader 类的常用方法包括:

  • read():从输入流中读取一个字符的数据。
  • read(char[] cbuf, int off, int len):从输入流中读取 len 个字符的数据到指定的字符数组 cbuf 中,从 off 位置开始存放。
  • ready():返回此流是否已准备好读取。
  • close():关闭输入流。

OutputStreamWriter 类的常用方法包括:

  • write(int c):向输出流中写入一个字符的数据。
  • write(char[] cbuf, int off, int len):向输出流中写入指定字符数组 cbuf 中的 len 个字符,从 off 位置开始。
  • flush():将缓冲区的数据写入输出流中。
  • close():关闭输出流。
    在使用转换流时,需要指定正确的字符集编码方式,否则可能会导致数据读取或写入出现乱码。

相关文章链接:
javaIO之各种流的分类与实际应用
javaIO流之文件流
javaIO流之字节流
javaIO流之字符流
javaIO流之缓冲流
javaIO流之转换流
javaIO流之序列流

且随疾风前行,身后亦需留心。——亚索 。如果觉得有用,点个赞吧~~~~~

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

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

相关文章

Ajax、Promise、Axios前端三剑客

文章目录 🐳前言关系二维表: 🐳Ajax定义:特点:🐡核心对象XMLHttpRequest:XMLHttpRequest对象的五种状态: 使用:1.Jquery的ajax:2.Vue的ajax: &…

【C#】GridControl增加选择列(不用二次点击)

系列文章 【C#】单号生成器(编号规则、固定字符、流水号、产生业务单号) 本文链接:https://blog.csdn.net/youcheng_ge/article/details/129129787 【C#】日期范围生成器(开始日期、结束日期) 本文链接:h…

【FMC156】基于VITA57.1标准的2路2.5GSPS采样率16位分辨率直流耦合DA播放FMC子卡模块(DAC38J82)

产品概述 FMC156 是一款基于VITA57.1 标准规范,实现2 路2.5GSPS 采样率16 位分辨率直流耦合DAC 播放子卡模块。该模块遵循VITA57.1 标准,可直接与FPGA 载卡配合使用,板卡DAC 器件采用TI 公司的DAC38J82 芯片,该芯片提供4 个模拟输…

2023,有哪些适合网工跳槽的好公司?(不是BAT)

大家好啊,我的网工朋友 都说行业内卷,卷的不成人形,这内卷,一卷就卷了好几年。 很多网工同行都讨厌被卷来卷去,但是看到同行进了大厂,免不了还是要羡慕嫉妒恨一波。 作为主编几年,我就发现了…

注册ChatGPT时提示Oops! The email you provided is not supported

问题描述 今天本想出一个ChatGPT的注册与使用的教程,结果上来吃了个闭门羹。之前我通过微软账号登录验证是没有问题的,但这次想使用另一个微软账号,结果提示Oops! The email you provided is not supported(您提供的电子邮件不支…

C# 给winfrom窗体添加皮肤控件

如何快速给C# winform添加好看的皮肤C# Winform中窗体的美化 SkinEngine的应用 皮肤控件换肤素材包,IrisSkin2.dll皮肤素材资源下载 压缩包内一共有22种皮肤素材,使用说明:把控件拖到你的form上,只需一行代码,即可实…

Ubuntu安装时没注册root用户密码,怎么登录root

一、Ubuntu设置root密码: 1.桌面空白处右键菜单 点击“打开终端“。 2.输入命令 "sudo passwd root

Cinema 4d 和 3ds Max:哪个软件更好?

3D 设计有很多挑战。设计师通常需要克服他们的看法和偏见,此外还要学习一些深入的程序来有效地使用 3D 风格的软件系统。市场上有很多用于3D设计的软件,因此对于哪一种对您的需求最有效会令人困惑。如果您不熟悉3D,或者您正在四处寻找新的软件…

数据进行分组后同一字段字符串连接方法

数据源如下:期望将同一个id_supplier_basic_info输出的supplier_type写在一行上,可以按‘/’分隔 一开始的时候使用的是但是一直提示找不到这个函数,一时陷入迷惑,难道是mysql不支持这个函数?但是百度明明都说mysql是支…

Mss32.dll丢失怎么办?怎么修复Mss32.dll文件

Mss32.dll丢失怎么办?如果你打开游戏或者应用程序时出现了如下错误提示:“找不到Mss32.dll”,那么你就需要解决这个问题。 Mss32.dll是一个动态链接库文件,它通常用于多媒体应用程序和游戏中的音频功能。如果该文件丢失或损坏&…

谷歌seo怎么做?2023做好谷歌seo的7个关键点

谷歌seo怎么做? 谷歌搜索引擎优化(SEO)是一系列的技术和策略,旨在通过改进网站结构、内容和其他因素,提高网站在搜索引擎结果页面(SERP)中的排名和可见性。以下是一些常用的谷歌SEO技术和策略&…

C语言——指针初阶

哈喽,大家好,今天我们来学习C语言中的指针,今天主要学习初阶指针,后期我们将继续学习指针进阶。 目录 1. 指针是什么 2. 指针和指针类型 2.1 指针-整数 2.2 指针的解引用 3. 野指针 3.1 野指针成因 3.2 如何规避野指针 4.…

苹果浏览器safari打不开网页怎么办?参考方法在这!

案例:为啥苹果自带的浏览器打不开网页?输入名称或者网址,打开的网页都是空白的。 【不知道怎么回事,我在safari浏览器里面输入网址,但是打不开正确的网页,一直打开的是空白网页。】 当您使用苹果自带的浏览…

构件连接器

构件连接器 1.构件连接器是什么 构件之间传递信息的器件称为构件连接器,简称为连接器。connector。 构件连接器就是在构件之间进行信息传递的通道,可以通过该通道实现信息由一个构件的端口传递 给另一个构件的端口或者是接口。 2.常见的连接器关系 委…

Python-PyEcharts绘制柱状图

更多优秀文章,请关注个人微信公众号: 程序猿小杨 Python-PyEcharts绘制柱状图 一、简介 核心创建流程: 1.通过Bar()构建一个柱状图对象 2.和折线图一样,通过add xaxis()和add_yaxis()添加x和y轴数据 3.通过柱状图对象的&#x…

Talk预告 | 香港中文大学博士生徐英豪:从不规则的单目图片数据构建3D生成模型

本期为TechBeat人工智能社区第498期线上Talk! 北京时间5月18日(周四)20:00,香港中文大学博士生 — 徐英豪的Talk将准时在TechBeat人工智能社区开播! 他与大家分享的主题是: “从不规则的单目图片数据构建3D生成模型”,届时将介绍…

ipa怎么装到苹果手机

下面介绍ipa怎么装到苹果手机? 方法/步骤 进入手机上的设置,如下图所示: 在设置页面中,点击进入通用,如下图所示: 进入通用页面后,点击页面上的描述文件,如下图所示: …

软件测试基础知识整理(五)- 软件开发模型、测试过程模型

目录 一、软件开发模型 1.1 瀑布模型 1.1.1 特点 1.1.2 优缺点 1.2 快速原型模型(了解) 1.2.1 特点 1.2.2 优缺点 1.3 螺旋模型(了解) 1.3.1 特点 1.3.2 优缺点 二、测试过程模型 2.1 V模型(重点&#xff…

chatgpt赋能Python-python3_6_4怎么用

Python3.6.4简介 Python3.6.4是Python编程语言的一个版本,于2017年12月19日发布。这个版本是Python3系列的一个重要更新版本,包含许多新的特性、改进以及Bug修复。 Python3.6.4有一个众所周知的特点:它是一个不断发展的语言,因此…

springcloud再次学习

对应版本关系,如果不对应可能会报错 在启动类配置,也可以在配置类配置 远程调用使用RestTemplate Eureka配置 步骤 Docker部署Eureka 先创建一个文件将打好的jar包文件去,再写一个Dockerfile文件 负载均衡 (LoadBalanced&#xf…