bufferedreader 本身不支持直接限制单行最大字符数,其 readline() 会持续缓存字符直至换行符,超长行易致内存溢出或阻塞;需手动实现带长度校验的行读取逻辑,或选用 apache commons io 等成熟库增强安全性。

BufferedReader 本身不支持直接限制单行最大字符数,它没有内置的“最大行长度”防护机制。防范超长行攻击(如拒绝服务、内存溢出)需要开发者在读取逻辑中主动控制,不能依赖 BufferedReader 的默认 readLine() 方法。
为什么 readLine() 有风险
BufferedReader 的 readLine() 会持续读取直到遇到换行符(\n、\r\n 或 \r),期间所有字符都会被缓存到内部 StringBuilder 中。如果输入流中存在超长行(例如百万字符无换行),就会导致:
- 内存占用急剧上升,可能触发
OutOfMemoryError - 线程长时间阻塞,影响服务响应能力
- 成为 DoS 攻击入口
手动实现带长度限制的行读取
核心思路:不用 readLine(),改用 read(char[], int, int) 或 read() 逐字符/批量读取,并实时计数。
- 定义最大允许行长度(如 8192 字符)
- 每次读取前检查已读字符数是否已达上限
- 遇到换行符立即返回当前行;超限时抛出异常或截断处理
- 注意区分
\r、\n、\r\n,避免误判
推荐做法:封装安全的 SafeLineReader
可封装一个工具类,例如:
- 维护一个固定大小的 char 数组(如 8192)作为缓冲区
- 循环调用
br.read(buffer, offset, remaining),累加读取长度 - 扫描 buffer 中的换行符位置,及时截断
- 累计长度超过阈值时,抛出
IOException("Line too long") - 保留未读完的字符(如 \r 后紧跟 \n),避免丢数据
更稳妥的选择:使用成熟库
避免重复造轮子,可考虑:
-
Apache Commons IO 的
LineIterator配合自定义 Reader 包装器 -
Google Guava 的
CharSource+ 自定义readLines()回调,加入长度校验 - Spring 的
StreamUtils不直接支持限长,但可结合InputStream层做字节级预检
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











