outputstreamwriter的write(string str)本质是按指定字符集将utf-16字符串确定性编码为字节序列,再写入底层字节流;该过程为可逆查表映射,不涉及哈希计算。

字符流调用 write(String str) 时,底层不涉及哈希计算,也不是直接“转换哈希”——这是一个常见误解。真实过程是:字符编码(encoding),即把 Java 内存中以 UTF-16 表示的字符串,按指定字符集(如 UTF-8、GBK)逐字符编码为字节序列,再交由底层字节流写出。
字符流写入 String 的真实流程
Java 中 String 在内存中统一用 UTF-16 编码(每个 char 是 16 位,代理对表示增补字符)。但文件或网络传输必须是字节,所以:
-
Writer子类(如OutputStreamWriter)接收到String - 它根据构造时指定的
charsetName(如"UTF-8"),调用对应CharsetEncoder - 将字符串中的每个字符(或代码点)查表编码为 1~4 个字节(UTF-8)或 2~4 个字节(GBK/UTF-16BE 等)
- 编码后的字节被写入包装的
OutputStream(如FileOutputStream) - 中间可能经过缓冲,最终刷盘
✅ 关键点:这是确定性编码映射(查表/算法),不是哈希;哈希是单向、不可逆、用于校验或索引的,和字符转字节完全无关。
为什么有人误以为是“哈希”?
- 看到
String.getBytes("UTF-8")返回一串看不出规律的字节数组,误以为“被哈希了” - 不理解编码是可逆映射:
"你好".getBytes("UTF-8")→[0xe4, 0xbd, 0xa0, 0xe5, 0xa5, 0xbd],再用new String(bytes, "UTF-8")能 100% 还原 - 哈希(如
str.hashCode())则无法还原原始字符串,且相同字符串每次结果固定,但不同字符串可能碰撞
实际编码行为举例
String s = "A你";
OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("test.txt"), "UTF-8");
osw.write(s); // 底层执行:
// 'A' → 0x41(1 字节)
// '你' → U+4F60 → UTF-8 编码为 0xe4 0xbd 0xa0(3 字节)
// 最终写入字节序列:[0x41, 0xe4, 0xbd, 0xa0]
osw.close();
如果换成 "GBK":
-
'你'→ GBK 编码为0xc4, 0xe3(2 字节) - 同样
write(s),但底层字节完全不同,且只能用 GBK 正确读回
编码转换的关键前提
- 写用什么 charset,读就必须用什么 charset,否则乱码
-
OutputStreamWriter和InputStreamReader是成对使用的转换桥梁 -
FileWriter/FileReader是简化版,隐式使用系统默认编码(不可靠,应避免)
总结一句话
write(String) 的本质是:按指定字符集,把内存中的 UTF-16 字符序列,确定性地翻译成字节序列;它依赖编码标准(如 Unicode + UTF-8 规则),不调用哈希函数,也不生成摘要,更不加密。所谓“转换”,就是查表+拼接字节,干净、可逆、严格遵循 RFC 或国家标准。











