仓颉 std.io MultiOutputStream 实战:一次写入、多路分发到多个输出流
人工智能AI 技能文档开发工具【免费下载链接】DocAgent项目地址https://gitcode.com/Cangjie-SIG/DocAgent点击查看免费下载本篇指南围绕仓颉标准库std.io包中的MultiOutputStreamT类展开讲解如何将同一份字节数据同时写入到一组OutputStream输出流中。读完本文你将掌握MultiOutputStream的类声明、构造函数与write/flush成员函数的使用方法并能结合ByteBuffer、BufferedOutputStream等流式组件在日志多路归档、双写备份等场景中直接落地使用。一、MultiOutputStream 是什么MultiOutputStreamT是仓颉标准库std.io包提供的多路输出流类它的核心能力是将数据同时写入到OutputStream数组中每个输出流中。从包概览std/io/io_package_overview.md可以看到std.io提供了流式 I/O 的通用接口和一批具体实现输入输出流被抽象为类似数据通道的载体程序从输入流读取数据向输出流写入数据。MultiOutputStream属于其中的流组合类实现——与顺序读取的ChainedInputStreamT按顺序从多个输入流读取正好形成对照一个是读的串联一个是写的并联。类声明MultiOutputStreamT的完整声明在 std/io/io_package_api/io_package_classes.md 中给出public class MultiOutputStreamT : OutputStream where T : OutputStream { public init(output: ArrayT) }关键点泛型约束where T : OutputStreamMultiOutputStream绑定的每个元素都必须是 OutputStream 接口的实现类型。父类型OutputStreamMultiOutputStream自身也实现了OutputStream接口因此它可以被当作一个普通输出流使用甚至可以作为其他组合流的输入再次被包装。OutputStream接口契约见 std/io/io_package_api/io_package_interfaces.md只包含两个成员func write(buffer: ArrayByte): Unit与func flush(): Unitflush提供默认空实现。这意味着任何实现了这两个方法的类型都可以被绑定进MultiOutputStream。二、核心 API 解析MultiOutputStream的 API 非常精简包含 1 个构造函数和 2 个成员函数全部信息收录在 std/io/io_package_index/MultiOutputStream_class.md。1. 构造函数init(output: ArrayT)名称原型说明init(output: ArrayT)创建 MultiOutputStream 实例绑定指定输出流数组。参数说明output: ArrayT—— 待绑定的输出流数组数组中的每个元素都必须满足T : OutputStream。异常行为来自 std/io/io_package_api/io_package_classes.md 的实现说明当output为空数组时抛出 IllegalArgumentException该类属于std.core包。因此构造前应确保输出流数组非空。2. 成员函数write(buffer: ArrayByte)名称原型说明write(buffer: ArrayByte) - Unit将 buffer 同时写入到绑定的 OutputStream 数组里的每个输出流中。这是MultiOutputStream的核心方法调用一次write同一份buffer数据会被顺序分发到绑定的每一个输出流中实现一次写入、多路分发。参数buffer是待写入数据的字节缓冲区ArrayByte 类型。3. 成员函数flush()名称原型说明flush() - Unit刷新绑定的输出流数组里的每个输出流。调用flush()会遍历绑定的输出流数组逐一调用每个输出流的flush()。对于带内部缓冲区的输出流如BufferedOutputStream、StringWriter这一步会把缓冲区内剩余数据真正推送到底层目标对于ByteBuffer这类本身不依赖刷新的流调用也不会产生副作用。三、完整实战示例一次写入多个 ByteBuffer仓库中提供了经过验证!-- verify --的可运行示例完整代码位于 std/io/io_samples/multi_output_stream.mdimport std.io.* main(): Unit { const size 2 /* 将两个 ByteBuffer 绑定到 MultiOutputStream */ let streamArr ArrayOutputStream(size, {_ ByteBuffer()}) let multiOutputStream MultiOutputStream(streamArr) /* 往 MultiOutputStream 写入数据会同时写入绑定的两个 ByteBuffer */ multiOutputStream.write(test.toArray()) /* 读取 ByteBuffer 中数据验证结果 */ for (i in 0..size) { match (streamArr[i]) { case v: ByteBuffer println(String.fromUtf8(readToEnd(v))) case _ throw Exception() } } }运行结果test test示例拆解构造输出流数组ArrayOutputStream(size, {_ ByteBuffer()})创建了两个ByteBuffer实例。ByteBuffer是std.io中基于ArrayByte的内存字节缓冲区实现IOStream Seekable详见 std/io/io_package_api/io_package_classes.md非常适合用来做内存中的输出目标方便后续直接读取验证。绑定并写入MultiOutputStream(streamArr)完成绑定随后multiOutputStream.write(test.toArray())一次性把test的字节同时写入两个ByteBuffer。注意这里只调用了一次write两个目标流都收到了相同的数据。验证结果通过match模式匹配将数组元素还原为ByteBuffer再用readToEnd(v)读取其全部剩余数据readToEndT是std.io提供的便捷函数见 std/io/io_package_api/io_package_funcs.md最终两个流都输出了test证明数据被完整地双路写入。从实现原理看可结合OutputStream接口契约推断MultiOutputStream.write内部会对绑定的数组做遍历对每个元素调用其write(buffer)flush()同理遍历调用各元素的flush()。因此绑定的流数量越多单次写入的开销线性增长适合少量目标、同批数据的分发场景。四、扩展实战绑定自定义输出流与组合流由于MultiOutputStream的约束是T : OutputStream而OutputStream接口只有write与flush两个抽象成员开发者可以非常容易地自定义输出流并将其接入多路分发。下面的示例基于接口定义编写一个记录写入次数的自定义输出流并与ByteBuffer一起绑定import std.io.* /* 自定义输出流记录写入次数与累计字节数 */ public class CountingStream : OutputStream { public var writeCount: Int64 0 public var totalBytes: Int64 0 public func write(buffer: ArrayByte): Unit { writeCount 1 totalBytes buffer.size } public func flush(): Unit {} } main(): Unit { let counter CountingStream() let buffer ByteBuffer() let multi MultiOutputStreamOutputStream([counter, buffer]) /* 一次 write同时写入两个目标 */ multi.write(Hello.toArray()) multi.write(World.toArray()) multi.flush() println(writeCount ${counter.writeCount}, totalBytes ${counter.totalBytes}) println(String.fromUtf8(readToEnd(buffer))) }运行结果writeCount 2, totalBytes 10 HelloWorld该示例展示了两个实用点MultiOutputStream可以绑定任意OutputStream实现包括内存流ByteBuffer与自定义统计流天然适合写日志的同时做指标统计这类场景write的入参是字节数组调用前需要通过toArray()等途径把字符串转换为ArrayByte。此外由于MultiOutputStream自身实现了OutputStream还可以与带缓冲的输出流组合使用例如将MultiOutputStream绑定到BufferedOutputStreamstd/io/io_package_api/io_package_classes.md之上让多路分发之前先经过一层缓冲减少底层目标的写入次数也可以与StringWriter搭配把格式化后的文本一次性分发到多个目标。这些组合方式体现了std.io流式组件可嵌套、可组装的设计思路。五、典型应用场景结合MultiOutputStream的语义它在以下场景中非常契合日志多路输出同一份日志同时写入控制台、内存缓冲区与文件流便于调试时同步比对数据双写/备份关键数据同时写入主存储与备份存储MultiOutputStream将写两次收敛为写一次;广播式分发需要向多个下游输出流推送相同字节序列时避免在每个目标上重复编写分发逻辑与ChainedInputStream对照使用输入侧用ChainedInputStreamT顺序串联多个输入流详见 std/io/io_package_api/io_package_classes.md输出侧用MultiOutputStreamT并联多个输出流一读一写覆盖常见的流式组合需求。需要留意的是MultiOutputStream的遍历写入是顺序执行的并非并发写入如果某个绑定的输出流write抛出异常如 IOException 或 ContentFormatException调用方需要自行处理异常与部分流已写入、部分流未写入的一致性问题。六、相关资源索引类 API 详情含异常说明std/io/io_package_api/io_package_classes.md类索引卡片std/io/io_package_index/MultiOutputStream_class.md含 JSON 元数据 std/io/io_package_index/MultiOutputStream_class.json官方示例可运行验证std/io/io_samples/multi_output_stream.mdOutputStream/InputStream/Seekable接口定义std/io/io_package_api/io_package_interfaces.md便捷读写函数copy、readToEnd、readStringstd/io/io_package_api/io_package_funcs.mdstd.io包总览std/io/io_package_overview.md 与 std/io/readme.md赞分享人工智能AI 技能文档开发工具【免费下载链接】DocAgent项目地址https://gitcode.com/Cangjie-SIG/DocAgent点击查看免费下载相关推荐仓颉标准库 std.io 多路输出流MultiOutputStream实战一次写入、多路分发详解仓颉标准库 std.io 多路输出流MultiOutputStream实战一次写入、多路分发详解 导读 MultiOutputStream 是仓颉标准库编程语言语言运行时标准库垃圾回收并发编程仓颉 MultiOutputStream 多输出流一次写入、广播到所有绑定输出流仓颉 MultiOutputStream 多输出流一次写入、广播到所有绑定输出流 本文围绕仓颉标准库 std.io 包中的 MultiOutputStream文档知识库教程OpenHarmony仓颉标准库 MultiOutputStream 详解多路输出流的绑定与数据广播写入实战仓颉标准库 MultiOutputStream 详解多路输出流的绑定与数据广播写入实战 MultiOutputStream 是仓颉标准库 std.io 中一个编程语言语言运行时标准库垃圾回收并发编程上一篇Hexo Next主题动画效果终极指南Velocity.js动效完全配置教程下一篇MuPDF JavaScript 高级实践PDF 创建、合并、缩略图与 Device 绘图创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考