【发布时间】:2011-04-23 03:22:39
【问题描述】:
我正在尝试搜索和替换我从 csv 文件解析的字符串中的特殊字符。当我用 vim 打开文本文件时,它显示字符是 。我终其一生都无法弄清楚使用 preg_replace 的字符是什么。任何帮助,将不胜感激。
谢谢,
克里斯·爱德华兹
【问题讨论】:
-
你能检查一下使用的是什么字符编码吗?
file -bi [filename]
标签: php
我正在尝试搜索和替换我从 csv 文件解析的字符串中的特殊字符。当我用 vim 打开文本文件时,它显示字符是 。我终其一生都无法弄清楚使用 preg_replace 的字符是什么。任何帮助,将不胜感激。
谢谢,
克里斯·爱德华兹
【问题讨论】:
file -bi [filename]
标签: php
按照 Bobince 的建议,以下内容对我有用:
analysis_file() -> http://www.php.net/manual/en/function.fgetcsv.php#101238
function file_get_contents_utf8($fn) {
$content = file_get_contents($fn);
return mb_convert_encoding($content, 'UTF-8', mb_detect_encoding($content, 'UTF-8, ISO-8859-1', true));
}
if( !($_FILES['file']['error'] == 4) ) {
foreach($_FILES as $file) {
$n = $file['name'];
$s = $file['size'];
$filename = $file['tmp_name'];
ini_set('auto_detect_line_endings',TRUE); // in case Mac csv
// dealing with fgetcsv() special chars
// read the file into a string, do your pre-processing changes
// write it back out to a temporary file, and have fgetcsv() read that.
$file = file_get_contents_utf8($filename);
$tempFile = tempnam(sys_get_temp_dir(), '');
$handle = fopen($tempFile, "w+");
fwrite($handle,$file);
fseek($handle, 0);
$filename = $tempFile;
// END -- dealing with fgetcsv() special chars
$Array = analyse_file($filename, 10);
$csvDelim = $Array['delimiter']['value'];
while (($data = fgetcsv($handle, 1000, $csvDelim)) !== FALSE) {
// process the csv file
}
} // end foreach
}
【讨论】:
0x95 可能应该代表字符 U+2022 Bullet (•),编码为 Windows code page 1252。您可以使用以下方法在字节字符串中删除它:
$line= str_replace("\x95", '', $line);
或者你可以使用iconv 将数据的字符集从cp1252 转换为utf8(或任何其他你想要的编码),如果你有一个可以读取非ASCII 字符的CSV 解析器可靠。否则,您可能想要删除 所有 个非 ASCII 字符,例如:
$line= preg_replace("/[\x80-\xFF]/", '', $line);
如果您的 CSV 解析器是 fgetcsv(),您就会遇到问题。从理论上讲,您应该能够在将字符串传递给str_getcsv()(PHP 5.3)之前将其作为预处理步骤来执行。不幸的是,这也意味着您必须自己读取文件并逐行拆分,鉴于引用的 CSV 值可能包含换行符,这并非易事。当您编写代码以正确处理时,您几乎已经编写了一个 CSV 解析器。因此,您实际上需要做的是将文件读入字符串,进行预处理更改,将其写回临时文件,然后让fgetcsv() 读取那个。
另一种方法是单独对fgetcsv() 返回的每个字符串进行后处理。但这也是不可预测的,因为 PHP 通过使用系统默认编码解码输入来破坏输入,而不是仅仅给你该死的字节。 Windows 之外的默认编码通常是 UTF-8,它不会自行读取 0x95 字节,因为那将是无效的字节序列。虽然您可以尝试使用 setlocale() 更改系统默认编码来解决这个问题,但 that 是一种非常糟糕的做法,它不会与您运行的任何其他应用程序很好地配合,这取决于系统语言环境。
总而言之,PHP 内置的 CSV 解析东西很垃圾。
【讨论】: