为什么PHP将回车换行组合视为单个字节?

7

我有一个PHP脚本,将字符串截断为41个字节。我使用strlen函数检查其大小。然而,如果字符串有"\r\n"组合,则此组合被视为一个字节。因此,在我的情况下,PHP认为它是41个字节而不是42个字节。

另外,substr将其截断为42个字节而不是41个字节。

  if (strlen($value) > 41)
  {
   $value = substr($value, 0, 41);

又是一个奇怪的情况。我有一大批数据要通过这个函数传递。成千上万个字符串。如果我使用一个更简单的测试数据集,那么代码就能正确地处理"\r\n"作为2个字节。

有什么想法吗? 谢谢。


NetCoder - 版本为5.2.9。但是正如我所说,我并不总是看到这种行为,只有在一个数千个字符串长的特定数据集上才会出现。更简单的数据集显示了预期的行为。因此,我并不相信5.3.4会起作用。 - jriggs
3
请告诉我您的平台和使用情况。如果您在Windows上从文件中读取数据,除非使用了fopen上的b标志,否则它会将\r\n转换为\n。因此,如果42字节的假设源于文件大小或fread长度,那么它不会与strlen匹配。 - mario
Mario - 你的评论让我思考。但我仍然认为这不是问题所在。我正在Windows上使用Xampp运行。我从数据库(varchar)中读取字符串,而数据库有\r\n。然后我使用上面的代码进行截断,并将其传递给php xml DomDocument,然后发送到第三方软件Quickbooks。Quickbooks发现该字符串太长(42个字节),无法接受它。 - jriggs
值是如何输入到数据库中的?例如:最终用户通过网页输入数据。我问这个问题的原因是每个操作系统输入回车或换行符的方式都不同。我相信Mac OSX使用\r,*nix使用\n,而Windows使用\r\n。 - Phill Pafford
谢谢Mario,我相信你已经解决了它。问题不在于PHP函数,而是我的测试存在缺陷,因为我的测试工具会在事后插入回车符。这并不能解释为什么Quickbooks认为字符串更长,只有在特定的数据集上才会出现。但我不再认为这是PHP问题了。 - jriggs
显示剩余7条评论
1个回答

1

将组合 \r\n 转换为 \n,进行任何必要的操作,然后将所有的 \n 恢复为组合...

str_replace("\r\n","\n",$value);
if (strlen($value) > 41)
  {
   $value = substr($value, 0, 41);
str_replace("\n","\r\n",$value);

希望这对你有用,不知道你在尝试做什么。

嗨Ronan,我考虑过这个选项,但我真的想知道发生了什么。我猜可能还有另一个字符组合会出现同样的问题,而我还不知道。 - jriggs
只是 strlen 函数以它所显示的组合为准(一个字符),因为它被设计成计算在屏幕上占用的空间大小,所以他们编码时将组合看作一个字符。而 substr 函数使用内存块来识别字符,而不需要尝试辨认它是什么。 - Rami Dabain
strlen通常将这个组合视为2个字符。在我所有简单的测试用例中,它被视为2个字符。只有在我的大数据集中才被视为1个字符。 - jriggs
你确定大数据集确实有 \r\n 而不是 \n 吗?如果是的话,这可能是函数忽略了 \r 的原因。请在大数据集中搜索以确定它是否真的有 \r。 - Rami Dabain
是的。实际上这似乎就是问题所在。感谢这里的评论,我发现了我的测试中的一个缺陷,数据库实际上并没有像我想象的那样有回车符。因此,问题不在于php字符串函数,而是在其他地方,我需要找到它。 - jriggs
只是想让你知道,我遇到了与 Unicode 相似的问题!对于 Unicode 字符串,有一个字符,当它涉及到 DOM 时非常麻烦!!! - Rami Dabain

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接