核心是读原始字节、逐字节异或运算、原样写回;必须全程使用FileInputStream/FileOutputStream等字节流,严禁混入字符流操作;密钥需显式指定编码,推荐8KB缓冲区与try-with-resources确保健壮性。

用字节流做文件加解密,核心就三点:读原始字节、逐字节运算、原样写回。不需要额外库,Java标准IO就能跑通,适合快速隐藏配置、作业或临时文件。
选对流类型:只用字节流,不用字符流
二进制文件(图片、PDF、ZIP)必须全程走 FileInputStream / FileOutputStream 或带缓冲的 BufferedInputStream / BufferedOutputStream。一旦混入 FileWriter、PrintWriter、String.valueOf() 这类字符处理,就会乱码或损坏。
- 加密时:读出 byte[] → 每个字节异或密钥 → 直接 write(byte[]) 写入新文件
- 解密时:读出加密后的 byte[] → 同样异或密钥 → write(byte[]) 输出原文件
- 错误示例:把加密后字节数组转成 String 再写入,等于二次编码,无法还原
密钥怎么设才靠谱
密钥必须是 byte 类型,别用字符串直接.getBytes()——平台默认编码不稳定。推荐显式指定:
- 单字节密钥(教学/轻量场景):
byte pwd = (byte) 0x5A;或new byte[]{(byte)123} - 字符串密钥转字节(更可控):
"MyKey".getBytes(StandardCharsets.UTF_8) - 避免:
"abc".getBytes()(依赖系统默认编码,Windows 和 Linux 可能不同)
提升性能和健壮性的实操要点
小文件可一次读完;大文件务必分块处理,否则容易 OOM 或卡死。
- 缓冲区大小建议
new byte[8192](8KB),平衡内存与 I/O 效率 - 用 try-with-resources 自动关流,防止 Stream closed 异常
- 读取时检查
read()返回值,不假设一次读完全部内容 - 加密/解密逻辑完全一致,只换输入输出路径和文件名
为什么异或能“一招两用”
数学上恒成立:a ^ b ^ b == a。所以同一密钥对同一数据异或两次,必然还原。这是它轻量又可逆的根本原因,但也是它的局限——没有扩散、无混淆,不适合高安全场景。
- 适合:防同事随手打开、隐藏学生作业、本地配置临时保护
- 不适合:对抗自动化扫描、网络传输、含敏感凭证的生产配置
- 进阶提示:真要提升安全性,可结合 SHA-256 生成动态密钥流,或直接切换 AES


















