参考:,这是一个自我回答的问题.它的目的是分享知识,问答风格。
如何在PHP中检测线路末端字符的类型?
PS:我从头到尾写这段代码已经太久了,所以我决定分享它,另外,我肯定有人会找到改进的方法。
发布于 2014-07-24 07:12:32
这里已经给出的答案为用户提供了足够的信息。下面的代码(基于已经给出的anwers)可能会有更多帮助:
我希望这对你们大家都有用。
/**
Newline characters in different Operating Systems
The names given to the different sequences are:
============================================================================================
NewL Chars Name Description
----- ----------- -------- ------------------------------------------------------------------
LF 0x0A UNIX Apple OSX, UNIX, Linux
CR 0x0D TRS80 Commodore, Acorn BBC, ZX Spectrum, TRS-80, Apple II family, etc
LFCR 0x0A 0x0D ACORN Acorn BBC and RISC OS spooled text output.
CRLF 0x0D 0x0A WINDOWS Microsoft Windows, DEC TOPS-10, RT-11 and most other early non-Unix
and non-IBM OSes, CP/M, MP/M, DOS (MS-DOS, PC DOS, etc.), OS/2,
----- ----------- -------- ------------------------------------------------------------------
*/
const EOL_UNIX = 'lf'; // Code: \n
const EOL_TRS80 = 'cr'; // Code: \r
const EOL_ACORN = 'lfcr'; // Code: \n \r
const EOL_WINDOWS = 'crlf'; // Code: \r \n
然后在静态类实用程序中使用以下代码来检测
/**
Detects the end-of-line character of a string.
@param string $str The string to check.
@param string $key [io] Name of the detected eol key.
@return string The detected EOL, or default one.
*/
public static function detectEOL($str, &$key) {
static $eols = array(
Util::EOL_ACORN => "\n\r", // 0x0A - 0x0D - acorn BBC
Util::EOL_WINDOWS => "\r\n", // 0x0D - 0x0A - Windows, DOS OS/2
Util::EOL_UNIX => "\n", // 0x0A - - Unix, OSX
Util::EOL_TRS80 => "\r", // 0x0D - - Apple ][, TRS80
);
$key = "";
$curCount = 0;
$curEol = '';
foreach($eols as $k => $eol) {
if( ($count = substr_count($str, $eol)) > $curCount) {
$curCount = $count;
$curEol = $eol;
$key = $k;
}
}
return $curEol;
} // detectEOL
然后对于一个文件:
/**
Detects the EOL of an file by checking the first line.
@param string $fileName File to be tested (full pathname).
@return boolean false | Used key = enum('cr', 'lf', crlf').
@uses detectEOL
*/
public static function detectFileEOL($fileName) {
if (!file_exists($fileName)) {
return false;
}
// Gets the line length
$handle = @fopen($fileName, "r");
if ($handle === false) {
return false;
}
$line = fgets($handle);
$key = "";
<Your-Class-Name>::detectEOL($line, $key);
return $key;
} // detectFileEOL
将您的类名称更改为实现类的名称(所有静态成员)。
发布于 2016-10-24 20:33:09
我的答案,因为我既不能使奥哈尔的一个,也不能转西维的一个工作,是:
function detect_newline_type($content) {
$arr = array_count_values(
explode(
' ',
preg_replace(
'/[^\r\n]*(\r\n|\n|\r)/',
'\1 ',
$content
)
)
);
arsort($arr);
return key($arr);
}
解释:
两种拟议解决方案的总体思路都很好,但实施细节妨碍了这些答案的有用性。
实际上,这个函数的目的是返回文件中使用的换行符类型,并且该换行符可以是一个或两个字符长的。
仅这一点就会导致str_split()
的使用不正确。正确剪切令牌的唯一方法是使用一个函数,该函数根据字符检测来裁剪长度可变的字符串。这就是explode()
发挥作用的时候。
但是为了给有用的标记爆炸,有必要用正确的匹配替换正确的字符,在适当的数量。大部分魔法发生在正则表达式中。
必须考虑3点:
.*
的建议使用奥哈尔是行不通的。虽然.
确实不匹配换行符,但在系统中,\r
不是换行符,或者是换行符的一部分,但.
将不正确地匹配换行符(提醒:我们正在检测换行符,因为它们可能与系统上的换行符不同。否则就没有意义)。/[^\r\n]*/
将“工作”以使文本消失,但是只要我们想要一个分隔符(因为我们删除了除换行符以外的所有字符,任何不是换行符的字符都将是有效的分隔符),这将是一个问题。因此,使用换行符创建匹配,并在替换中使用对该匹配的反向引用的想法。发布于 2013-11-14 12:24:04
根据欧哈尔的回答。
这可以为LF、CR+LF等EOL返回一两个字符。
$eols = array_count_values(str_split(preg_replace("/[^\r\n]/", "", $string)));
$eola = array_keys($eols, max($eols));
$eol = implode("", $eola);
https://stackoverflow.com/questions/11066857
复制相似问题