如何从包含换行符的字符串中正确截取指定长度的子串?
问题根因
你遇到的长度不一致问题来自两个认知偏差:
- C# 中
string.Length统计的是运行时字符串包含的Unicode字符数,单个换行符\n只会被统计为1个字符。你粘贴到Notepad时长度变大,是因为Notepad默认使用Windows换行格式(CRLF),会自动将单个\n转换为\r\n两个字符,导致总长度增加。 - 你补充示例里的预期偏差是因为你把字符串字面量里的转义符
\算成了独立字符,实际运行时\n是一个整体字符,并不会占2个长度。你的示例中"Hi\nHello."的字符索引依次为0:H、1:i、2:\n、3:H、4:e...,调用Substring(0,4)自然会取出前4个字符Hi\nH,和你实际运行结果一致。
解决方案
根据你的实际需求可以选择两种处理方式:
方案1:按运行时字符长度截取(通用场景)
如果你只需要保证C#运行时的截取长度符合4096的要求,只需要修复原有代码中Substring可能越界的问题即可:
string response = // API返回的响应内容 int chunkSize = 4096; if (response.Length > chunkSize) { for (int i = 0; i < response.Length; i += chunkSize) { // 计算当前分片实际可取长度,避免超出字符串总长度 int currentLength = Math.Min(chunkSize, response.Length - i); string rplymsg = response.Substring(i, currentLength); // 其他处理rplymsg的业务逻辑 } } else { // 直接处理response的业务逻辑 }
如果需要避免粘贴到Notepad++时的长度差异,可以在截取前统一将换行符替换为你需要的格式:
- 统一为LF格式:
response = response.Replace("\r\n", "\n"); - 统一为CRLF格式:
response = response.Replace("\n", "\r\n").Replace("\r\r\n", "\r\n");
方案2:按转义后字面量长度截取(匹配你补充示例的预期)
如果你需要将\n按2个长度统计,和字符串字面量的写法长度对齐,可以自定义截取方法:
/// <summary> /// 按转义后长度截取字符串,\n、\r均按2个长度计算 /// </summary> public static string SubstringByEscapedCount(string input, int startIndex, int targetEscapedLength) { int escapedCount = 0; int endIndex = startIndex; while (endIndex < input.Length && escapedCount < targetEscapedLength) { escapedCount += input[endIndex] is '\n' or '\r' ? 2 : 1; if (escapedCount <= targetEscapedLength) { endIndex++; } else { break; } } return input.Substring(startIndex, endIndex - startIndex); }
调用示例:
string value = "Hi\nHello."; string result = SubstringByEscapedCount(value, 0, 4); // 输出结果为 "Hi\n",符合你的预期
内容的提问来源于stack exchange,提问作者Harshad Raval
相关产品推荐
相关产品推荐

