strlen() 计算字符串字节数,包含换行符;mb_strlen() 按字符计数,换行符仍计入;需显式清理换行符才能排除其影响。

strlen() 计算字符串长度时包含换行符
strlen() 统计的是字节数,不是字符数,所有字节都会被计入,包括 \n、\r、\r\n 这些换行相关字节。比如:
echo strlen("a\nb"); // 输出 3:'a'(1字节) + '\n'(1字节) + 'b'(1字节)
在 Windows 下若用双引号写 "a\r\nb",strlen() 会返回 4;Linux/macOS 下 "a\nb" 是 3。
- 换行符在 ASCII 中是单字节:
\n= 0x0A(1 字节),\r= 0x0D(1 字节) - 文件读入时换行符保留原样,
fgets()、file_get_contents()都不会自动过滤 - 如果从表单或 textarea 接收文本,用户按 Enter 输入的极大概率就是
\n(浏览器统一标准化为 LF)
mb_strlen() 同样计入换行符,但按字符而非字节
mb_strlen() 的行为取决于 $encoding 参数,但它依然把换行符当作一个“字符”来计数——只不过这个“字符”在 UTF-8 中占 1 字节,在 GBK 中也占 1 字节,所以结果通常和 strlen() 一致(除非遇到多字节汉字)。
echo mb_strlen("你好\n", 'UTF-8'); // 输出 3:'你' + '好' + '\n'
- 换行符在绝大多数编码下都是单字符单字节,所以
mb_strlen()和strlen()对含换行的纯 ASCII 文本结果相同 - 真正差异出现在中文、日文等场景:
strlen("你好")返回 6(UTF-8 下每个汉字 3 字节),而mb_strlen("你好", 'UTF-8')返回 2 - 别指望
mb_strlen()自动“忽略换行”,它不负责语义过滤
想排除换行符再算长度?得先清理
没有内置函数直接“算不含换行的长度”,必须显式移除换行符后再调用长度函数。常见做法:
立即学习“PHP免费学习笔记(深入)”;
- 用
str_replace(["\r\n", "\r", "\n"], '', $str)彻底清除所有换行变体 - 用
preg_replace('/[\r\n]+/', '', $str)更简洁,但注意 PCRE 开销略高 - 若只要去除首尾换行,用
trim($str, "\r\n")更轻量,但中间的换行仍保留
示例:
$text = "line1\r\nline2\nline3"; $clean = str_replace(["\r\n", "\r", "\n"], '', $text); echo strlen($clean); // 输出 15("line1line2line3")
实际校验场景中容易忽略的点
做字段长度限制(如数据库 varchar(255))时,如果后端没清理换行符,用户粘贴带空行的文本就可能超长报错,而前端 JS 的 .length 在大多数情况下也计入 \n,看似一致,但 JS 的 \r\n 是两个字符,PHP 的 "\r\n" 是两个字节 —— 表面一致,底层逻辑不同。
- MySQL
TEXT类型存储时保留换行符,但某些客户端显示会折叠,造成“长度对不上”的错觉 - 使用
wordwrap()或nl2br()前,先确认原始字符串是否已含多余换行,否则可能重复处理 - API 接口接收 JSON 字段时,JSON 解析器(如
json_decode())不会修改字符串内容,换行符原样保留
换行符不是隐形的,它实实在在占空间。判断长度前,先想清楚:你要的是“用户看到的行数”,还是“存进数据库的字节数”,还是“前端展示的视觉宽度”——三者完全不是一回事。











