
本文详解如何将长字符串按每行最多20字符进行智能换行——不强行截断单词,而是查找第20个字符后的第一个空格位置作为断点,并循环处理剩余文本,避免索引越界错误。
本文详解如何将长字符串按每行最多20字符进行智能换行——不强行截断单词,而是查找第20个字符后的第一个空格位置作为断点,并循环处理剩余文本,避免索引越界错误。
在文本处理中,简单按固定长度(如20字符)截断字符串极易导致单词被硬性割裂(例如 "programming" 变成 "programmi"),严重影响可读性。理想方案是:在接近目标长度的位置寻找最近的空格,以保证每行结尾均为完整单词。这需要结合字符串索引查找与循环切片逻辑,而非静态偏移。
核心思路如下:
- 每次从 startPos 开始,向后查找 首个位于 startPos + 20 及之后的空格;
- 若找到该空格,则以其位置 endPos 为截断点;
- 若未找到(即剩余文本不足20字符或无后续空格),则直接取到字符串末尾;
- 更新 startPos = endPos + 1 是为了跳过当前行末的空格,使下一行从下一个非空格字符开始——这正是原提问者困惑的关键:+1 并非随意加一,而是语义上“越过分隔符”,防止重复输出空格或陷入死循环。
以下是健壮、可直接运行的 Java 实现:
import java.util.Scanner;
public class LineWrapper {
public static void main(String[] args) {
System.out.println("Please input a sentence: ");
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine().trim();
if (input.isEmpty()) return;
final int MAX_LINE_LENGTH = 20;
int startPos = 0;
while (startPos < input.length()) {
int endPos = startPos + MAX_LINE_LENGTH;
// 边界保护:不可超出字符串长度
if (endPos >= input.length()) {
System.out.println(input.substring(startPos));
break;
}
// 向后查找第一个空格(从 startPos + MAX_LINE_LENGTH 开始)
int spaceIndex = input.indexOf(' ', endPos);
// 若找到空格,截断到该空格前;否则截断到当前最大长度
if (spaceIndex != -1) {
System.out.println(input.substring(startPos, spaceIndex));
startPos = spaceIndex + 1; // ✅ 关键:跳过空格,下一行从下一字符起
} else {
// 剩余部分无空格(如长单词、URL等),强制截断
System.out.println(input.substring(startPos, endPos));
startPos = endPos;
}
}
scanner.close();
}
}✅ 运行效果示例:
输入:"Hello there, I am doing some coding, I need some help"
输出:
Hello there, I am doing some coding, I need some help
⚠️ 注意事项与常见陷阱:
- 索引越界异常(StringIndexOutOfBoundsException):原始代码中 endPos = 20 固定赋值,未校验字符串长度,第二次循环时 startPos=21 已超限,substring(21, 20) 直接报错。务必在每次 substring 前确保 startPos ≤ endPos
- 末尾空格处理:indexOf(" ", 20) 在 endPos 超出范围时返回 -1,需显式判断,否则 substring(startPos, -1) 将抛异常。
- 全角空格或换行符:本方案仅识别 ASCII 空格 ' '。如需支持 Unicode 分隔符(如 'u3000' 全角空格),应改用正则 input.split("\s+", 2) 或增强空格检测逻辑。
- 性能考量:对超长文本(如数万字符),频繁 indexOf 查找仍属 O(n) 级别,实际生产环境可预构建空格索引表优化。
总结:智能换行的本质是「语义对齐」而非「机械切分」。通过 String.indexOf(char, fromIndex) 精准定位分隔符,并严格维护 startPos/endPos 的语义一致性(startPos 指向行首字符,endPos 指向行尾空格位置),即可兼顾可读性与鲁棒性。掌握这一模式,亦可轻松扩展至 Markdown 段落渲染、终端日志自动折行等真实场景。

















