当前位置: 首页 > news >正文

Java学习之——“IO流“的进阶流之转换流的学习

        在博主的上一篇博文中,详细的介绍了“IO”流中最基本的一些知识,包括基本的常见的字节流和字符流,以及对应的缓冲流,对于“IO”流基础知识相对薄弱的同学可以先去看博主的上一篇博文Java学习之——万字详解“IO流”中基本的字节流和字符流 后在回头来看这篇进阶文章效果会更好。

        Java IO流中的“进阶”流:转换流、序列化流、打印流和压缩流。它们构建在基础字节流和字符流之上,提供了更强大、更便捷的功能。

一、转换流

1.核心概念:为什么需要转换流?

要理解转换流,首先要明白 Java I/O 流体系中的两个核心分支:

  • 字节流:以字节(8 bit)为基本单位,处理所有类型的数据(如图片、视频、音频等二进制文件,也包括文本文件)。基类是 InputStream 和 OutputStream
  • 字符流:以字符(16 bit,一个char)为基本单位,专门为方便处理文本数据而设计。它底层仍然是字节操作,但会自动处理字符编码。基类是 Reader 和 Writer

问题:我们经常遇到这样的场景——一个字节流(例如,来自网络、文件的 FileInputStream 或 Socket.getInputStream())传输的是文本内容。如果我们直接使用字节流读取,得到的是一个个字节,我们需要自己将这些字节按照正确的字符编码(如 UTF-8, GBK)拼接和转换成字符,非常麻烦且容易出错。

解决方案:转换流(InputStreamReader / OutputStreamWriter)。

它们的作用就是作为一座“桥梁”,将底层的字节流 转换为顶层的字符流,并在转换过程中完成字节到字符的编码解码工作

  • InputStreamReader: 将一个字节输入流(InputStream转换为一个字符输入流(Reader)。【解码:字节 -> 字符】
  • OutputStreamWriter: 将一个字符输出流(Writer转换为一个字节输出流(OutputStream)。【编码:字符 -> 字节】

2.InputStreamReader 详解

核心功能:InputStreamReader是 Reader的子类。它包裹着一个字节输入流(InputStream),并读取字节,然后使用指定的或默认的字符集将其解码为字符。

关键构造函数:

// 使用默认字符集创建一个 InputStreamReader
InputStreamReader(InputStream in)// 使用指定的字符集名称创建一个 InputStreamReader
// 字符集如:"UTF-8", "GBK", "ISO-8859-1"
InputStreamReader(InputStream in, String charsetName)// 使用指定的 Charset 对象创建一个 InputStreamReader
InputStreamReader(InputStream in, Charset cs)

工作原理:

当你调用 InputStreamReader 的 read() 方法时,会发生以下步骤:

  1. 它从内部的 InputStream 中读取一个或多个字节。
  2. 这些字节根据构造时指定的字符集(Charset)进行解码。
  3. 将解码后的结果以一个 char(或多个 char 放入数组)的形式返回。

代码示例:

        假设我们有一个文本文件 text.txt,其编码是 GBK。如果我们用默认字符集(通常是 UTF-8)的 FileReader(它是 InputStreamReader 的子类)读取,可能会乱码。使用 InputStreamReader 指定编码可以完美解决。

import java.io.*;public class InputStreamReaderDemo {public static void main(String[] args) {try (// 1. 创建一个字节流 FileInputStreamFileInputStream fis = new FileInputStream("text.txt");// 2. 创建一个转换流 InputStreamReader,并指定编码为 GBKInputStreamReader isr = new InputStreamReader(fis, "GBK");// 3. 为了高效,通常用 BufferedReader 包裹 InputStreamReaderBufferedReader br = new BufferedReader(isr)) {String line;// 此时读取到的字符已经是正确解码后的文本,不会乱码while ((line = br.readLine()) != null) {System.out.println(line);}} catch (IOException e) {e.printStackTrace();}}
}

3.OutputStreamWriter 详解

        OutputStreamWriter 是 Writer 的子类。它接收字符,然后使用指定的或默认的字符集将其编码为字节,并写入到底层的字节输出流(OutputStream)中。

关键构造函数

// 使用默认字符集创建一个 OutputStreamWriter
OutputStreamWriter(OutputStream out)// 使用指定的字符集名称创建一个 OutputStreamWriter
OutputStreamWriter(OutputStream out, String charsetName)// 使用指定的 Charset 对象创建一个 OutputStreamWriter
OutputStreamWriter(OutputStream out, Charset cs)

工作原理

当你调用 OutputStreamWriter 的 write() 方法时,会发生以下步骤:

  1. 你传入的字符(或字符串)根据构造时指定的字符集(Charset)进行编码。
  2. 编码后得到的一个或多个字节被写入到底层的 OutputStream 中。
  3. OutputStream 最终将这些字节写入到目标(文件、网络等)。

我们想要将一个字符串以 GBK 编码写入到文件中。

import java.io.*;public class OutputStreamWriterDemo {public static void main(String[] args) {try (// 1. 创建一个字节流 FileOutputStreamFileOutputStream fos = new FileOutputStream("output.txt");// 2. 创建一个转换流 OutputStreamWriter,并指定编码为 GBKOutputStreamWriter osw = new OutputStreamWriter(fos, "GBK");// 3. 为了高效和方便,通常用 BufferedWriter 包裹BufferedWriter bw = new BufferedWriter(osw)) {String content = "你好,世界!";bw.write(content);bw.newLine();bw.write("This is a test.");} catch (IOException e) {e.printStackTrace();}// 最终文件 output.txt 的编码将是 GBK}
}

与 FileReader / FileWriter 的关系

  • FileReader 本质上是 InputStreamReader 的子类,它简化了文件的读取,但无法指定编码,只能使用默认编码。FileWriter 同理。

  • 结论:在需要明确指定编码的场合(绝大多数国际化和跨平台场景),不要直接使用 FileReader 和 FileWriter,而应该使用 InputStreamReader 和 OutputStreamWriter 并手动指定编码。FileReader/FileWriter 仅适用于处理与系统默认编码一致的文件。


文章转载自:

http://4PQsBgze.kcLkb.cn
http://AtCVFvli.kcLkb.cn
http://gbKVCtfp.kcLkb.cn
http://51tZwVkJ.kcLkb.cn
http://iS6sk8hR.kcLkb.cn
http://SEtUTsLL.kcLkb.cn
http://l5GISqF7.kcLkb.cn
http://jsBra8W0.kcLkb.cn
http://eIjOzAjl.kcLkb.cn
http://C8uZKLln.kcLkb.cn
http://SH3Dzu2j.kcLkb.cn
http://wahRdu2T.kcLkb.cn
http://G3jZ36mS.kcLkb.cn
http://6suY8Ynh.kcLkb.cn
http://mOgF53Z0.kcLkb.cn
http://jIIPajIC.kcLkb.cn
http://CYsV9kIs.kcLkb.cn
http://ehqxmsIK.kcLkb.cn
http://R67qh73U.kcLkb.cn
http://bkUxRnoh.kcLkb.cn
http://jLodLK6n.kcLkb.cn
http://pOjeYnHt.kcLkb.cn
http://EhE7iFeo.kcLkb.cn
http://Ymb8lTyw.kcLkb.cn
http://zIBZ5xCv.kcLkb.cn
http://5iItqRln.kcLkb.cn
http://cvU9XB2p.kcLkb.cn
http://T3TyXeeb.kcLkb.cn
http://fKBPdmia.kcLkb.cn
http://yHG1z7V8.kcLkb.cn
http://www.dtcms.com/a/375562.html

相关文章:

  • git 如何直接拉去远程仓库的内容且忽略本地与远端不一致的commit
  • 每日一算:分发糖果
  • 神经算子学习
  • AI大模型入门1.1-python基础字符串代码
  • Tlias管理系统(多表查询-内连接外连接)
  • win11家庭版配置远程桌面
  • 8. LangChain4j + 提示词工程详细说明
  • ChatGPT大模型训练指南:如何借助动态代理IP提高训练效率
  • 利用git进行版本控制
  • 深入理解synchronized:从使用到原理的进阶指南
  • 第八章 矩阵按键实验
  • 【CSS 3D 实战】从零实现旋转立方体:理解 3D 空间的核心原理
  • C++互斥锁使用详解与案例分析
  • Python+DRVT 从外部调用 Revit:批量创建柱
  • Matlab机器人工具箱6.2 导入stl模型——用urdf文件描述
  • 网页设计模板 HTML源码网站模板下载
  • 南京大学计算机学院 智能软件工程导论 + Luciano Baresi 教授讲座
  • Rust/C/C++ 混合构建 - Buck2构建工具一探究竟
  • Drawnix:开源一体化白板工具,让你的创意无限流动!
  • stm32 链接脚本没有 .gcc_except_table 段也能支持 C++ 异常
  • K8S集群管理(4)
  • flutter TabBar 设置isScrollable 第一个有间距
  • 学习 Android (二十一) 学习 OpenCV (六)
  • Maven项目中修改公共依赖项目并发布到nexus供三方引用全流程示例
  • GD32VW553-IOT开发板移植适配openharmony
  • nuxt3在使用vue-echarts报错 document is not defined
  • 嵌入式第四十九天(ARM汇编指令)
  • RS485通信 , 和modus RTU
  • 7. LangChain4j + 记忆缓存详细说明
  • 【超简单】Anaconda 安装教程(Windows 图文版)