reader.skip() 方法尽力跳过指定字符数但不保证成功,实际跳过数可能少于请求值甚至为0;需循环调用并累计,遇0应处理流末尾或异常情况。

Reader.skip() 方法用于跳过输入流中指定数量的字符,但它不保证一定跳过你传入的全部数量,实际跳过的字符数可能少于请求值,甚至为 0。
skip() 的行为特点
Java 中的 Reader.skip(long n) 是一个“尽力而为”的操作:
- 它尝试跳过 n 个字符,但可能因流末尾、阻塞、缓冲限制等原因只跳过部分或零个字符
- 返回值是实际跳过的字符数(long 类型),必须检查该值,不能假设等于传入的 n
- 如果传入负数,直接抛出 IllegalArgumentException
- 如果底层流不支持跳过(比如某些包装流未重写 skip),可能抛出 IOException
如何确保跳过确切数量的字符
若业务逻辑要求必须跳过 n 个字符(例如解析固定格式文本),需循环调用 skip() 并累计跳过量:
- 用 while 循环反复调用 skip(),直到累计跳过数达到目标
- 每次调用后检查返回值,若为 0 表示已到流末尾或无法继续跳过,应按需处理(如抛异常或提前结束)
- 注意:对某些 Reader(如 InputStreamReader 包装网络流),频繁 skip 可能效率较低,可考虑用 read() 配合丢弃更可控
示例代码片段:
long toSkip = 10; long skipped = 0; while (skipped
常见 Reader 的 skip 实现差异
不同子类对 skip() 的支持程度不同:
- StringReader 和 CharArrayReader:通常能精确跳过(只要未超界)
- BufferedReader:利用内部缓冲,skip 效率较高,但仍可能因缓冲区不足而分多次执行
- InputStreamReader:依赖底层 InputStream 的 skip,而字节流 skip 不等于字符 skip(尤其含多字节编码时),可能导致乱码或跳错位置
- FileReader:本质是 InputStreamReader,同样受编码和底层字节 skip 影响
替代方案:read() + 丢弃更可靠
当 skip() 行为不确定或需跨平台稳定时,可用 read() 读取并忽略字符:
- 分配一个临时 char 数组(如 new char[8192]),循环 read() 直到累计读取 n 个字符
- 比 skip() 更可控,尤其对编码敏感场景(如 UTF-8 中跳过字节 vs 字符)
- 缺点是会消耗少量内存和 CPU,但语义明确、可预测
简单实现:
char[] buf = new char[1024];
long remaining = n;
while (remaining > 0) {
int readCount = reader.read(buf, 0, (int) Math.min(remaining, buf.length));
if (readCount == -1) break; // 流结束
remaining -= readCount;
}
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











