商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > Java中 DataInputStream 读取字符串时 readUTF 超过 65535 字节报错排查

Java中 DataInputStream 读取字符串时 readUTF 超过 65535 字节报错排查

  发布于2026-07-15 阅读(0)

扫一扫,手机访问

你可能遇到过这样的情况:用 DataInputStream 的 readUTF 方法读取字符串时,突然抛出一个 ja va.io.UTFDataFormatException: encoded string too long 的错误。这不是什么奇怪的 bug,而是 readUTF 本身的一道“硬门槛”——它要求字符串的 UTF-8 编码字节长度不能超过 65535(也就是 216−1)。

这个限制的根源在于 readUTF 的工作方式。它先读 2 个字节,这两个字节是一个无符号短整型,用来表示后续 UTF 编码字节的长度。2 个字节能表示的最大值就是 65535,超出这个范围,协议层面就不认了。

这里有个很容易被忽略的点:字符串的字符数和它的 UTF-8 编码字节数,完全是两码事。一个字符串可能只有几万个字符,但里面只要混入中文、emoji 或其他 Unicode 字符,编码后的体积就可能迅速膨胀(一个汉字就要占 3 个字节)。而这个限制跟 JVM 或 JDK 版本无关,是 DataInputStream 规范中雷打不动的强制要求。

如何判断是否真的超限了?

别只盯着 String.length() 看,那个数字是字符数,对判断这个限制没什么帮助。真正要查的是 UTF-8 编码后的字节数:

  • string.getBytes(StandardCharsets.UTF_8).length 拿到真实的字节长度
  • 如果结果大于等于 65536,那在 writeUTF/readUTF 的流程里就一定会失败
  • 值得警惕的是:writeUTF 在写入时就会做同样的校验。所以问题往往在写入端就已经埋下了,只是到读取时才暴露出来

替代方案:怎么绕过 readUTF 的限制?

当需要传输长文本时,最直接的办法就是放弃 readUTF,改用更灵活的组合方式。比如:

  • 写入端:先写一个 int 类型的长度(dos.writeInt(len)),再写原始字节(dos.write(bytes)
  • 读取端:先读 int 拿到长度,再用 new String(din.readNBytes(len), StandardCharsets.UTF_8) 还原字符串
  • 或者直接用 BufferedReader/BufferedWriter 加行协议,也可以考虑 ObjectOutputStream(但要留意序列化开销和兼容性问题)

哪些场景容易踩坑?

有意思的是,这个限制虽然不复杂,但踩坑的人确实不少。以下几个场景尤其容易中招:

  • 直接把日志、JSON、XML 这类大文本内容丢进 writeUTF,完全没有预估编码后的体积
  • 前后端混用时,Ja va 端用 DataInputStream.readUTF,而另一端(比如 Python 的 socket)手动拼接 UTF-8 字节,却没有做长度截断
  • 升级数据格式后,读写逻辑没同步更新。旧版本能存的长字符串,新版本一读就报错

说到底,这个问题不复杂,但确实容易忽略。关键在于区分“字符数”和“UTF-8 字节数”,并且在设计阶段就把传输协议的边界明确下来。

Ja va中 DataInputStream 读取字符串时 readUTF 超过 65535 字节报错排查

本文转载于:https://www.php.cn/faq/2822913.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注