Php 从导入的.csv文件中删除BOM(ï;»;¿;)

Php 从导入的.csv文件中删除BOM(ï;»;¿;),php,csv,import,fgetcsv,Php,Csv,Import,Fgetcsv,我想从导入的文件中删除BOM表,但它似乎不起作用 我尝试了preg\u替换('/[\x00-\x1F\x80-\xFF]/','.$file)和str_替换。 我希望任何人都知道我做错了什么 $filepath = get_bloginfo('template_directory')."/testing.csv"; setlocale(LC_ALL, 'nl_NL'); ini_set('auto_detect_line_endings',TRUE

我想从导入的文件中删除BOM表,但它似乎不起作用

我尝试了
preg\u替换('/[\x00-\x1F\x80-\xFF]/','.$file)和str_替换。

我希望任何人都知道我做错了什么

$filepath = get_bloginfo('template_directory')."/testing.csv";
            setlocale(LC_ALL, 'nl_NL');
            ini_set('auto_detect_line_endings',TRUE);
            $file = fopen($filepath, "r") or die("Error opening file");
            $i = 0;
            while(($line = fgetcsv($file, 1000, ";")) !== FALSE) {
                if($i == 0) {
                    $c = 0;
                    foreach($line as $col) {
                        $cols[$c] = utf8_encode($col);
                        $c++;
                    }
                } else if($i > 0) {
                    $c = 0;
                    foreach($line as $col) {
                        $data[$i][$cols[$c]] = utf8_encode($col);
                        $c++;
                    }
                }
                $i++;
            }
-----------
已解决版本:

setlocale(LC_ALL, 'nl_NL');
ini_set('auto_detect_line_endings',TRUE);
require_once(ABSPATH.'wp-admin/includes/file.php' );

$path = get_home_path();        
$filepath = $path .'wp-content/themes/pon/testing.csv';
$content = file_get_contents($filepath); 
file_put_contents($filepath, str_replace("\xEF\xBB\xBF",'', $content));

// FILE_PUT_CONTENTS AUTOMATICCALY CLOSES THE FILE
$file = fopen($filepath, "r") or die("Error opening file"); 

$i = 0;
while(($line = fgetcsv($file, 1000, ";")) !== FALSE) {
    if($i == 0) {
        $c = 0;
        foreach($line as $col) {
            $cols[$c] = $col;
            $c++;
        }
    } else if($i > 0) {
        $c = 0;
        foreach($line as $col) {
            $data[$i][$cols[$c]] = $col;
            $c++;
        }
    }
    $i++;
}

我发现它会删除BOM表,并通过使用新数据覆盖来调整文件。问题是我的脚本的其余部分不再工作了,我不明白为什么。它是一个新的.csv文件

读取带有
文件内容的数据
然后使用
mb\u convert\u编码
转换为UTF-8

更新 试试这个:

function removeBomUtf8($s){
  if(substr($s,0,3)==chr(hexdec('EF')).chr(hexdec('BB')).chr(hexdec('BF'))){
       return substr($s,3);
   }else{
       return $s;
   }
}

如果字符编码函数不适用于您(在某些情况下我就是这样),并且您知道您的文件总是有一个BOM表,那么您可以简单地使用fseek()跳过前3个字节,即BOM表的长度

$fp = fopen("testing.csv", "r");
fseek($fp, 3);
您也不应该使用explode()拆分CSV行和列,因为如果列包含拆分时使用的字符,则会得到错误的结果。改用这个:

while (!feof($fp)) {
    $arrayLine = fgetcsv($fp, 0, ";", '"');
    ...
}
以此作为主要灵感,以及:


BOM不是给你一个提示,告诉你如何重新编码你的脚本/应用程序/数据库所需的输入吗?只是删除是没用的

这就是我如何强制将字符串(从带有
file\u get\u contents()

switch (true) { 
    case (substr($string,0,3) == "\xef\xbb\xbf") :
        $string = substr($string, 3);
        break;
    case (substr($string,0,2) == "\xfe\xff") :                            
        $string = mb_convert_encoding(substr($string, 2), "UTF-8", "UTF-16BE");
        break;
    case (substr($string,0,2) == "\xff\xfe") :                            
        $string = mb_convert_encoding(substr($string, 2), "UTF-8", "UTF-16LE");
        break;
    case (substr($string,0,4) == "\x00\x00\xfe\xff") :
        $string = mb_convert_encoding(substr($string, 4), "UTF-8", "UTF-32BE");
        break;
    case (substr($string,0,4) == "\xff\xfe\x00\x00") :
        $string = mb_convert_encoding(substr($string, 4), "UTF-8", "UTF-32LE");
        break;
    default:
        $string = iconv(mb_detect_encoding($string, mb_detect_order(), true), "UTF-8", $string);
};

正确的方法是跳过文件()中的BOM表:


$cols[$c]
在您的第一个foreach中是没有意义的
$cols
是您正在处理的任何行/字段的副本。您需要
foreach($key=>lines as$col){$lines[$key]=utf8_encode($col)}
PHP文档对fgetcsv的注释有一个很好的答案,-打开文件,读取并移动文件指针,检查前3个字节是否与BOM字符串相等,如果不相等,请倒带,然后继续使用fgetcv fixedstring=decodeURIComponent(escape(utfstring))@交互式
文件\u获取内容
读取整个文件<代码>分解
按“\n”或“\r\n”进行分解。它返回一个数组。然后遍历这个数组。如果我运行它,它会给我一个数组,其中“titlefields”位于第一个数组中,并且每个后面的数组都包含每个人的信息。这是伟大的,但我不知道如何使用它为我所做的。所以我想我会开一个通宵。我稍微改变了你的想法(不知道这是否是最好的,但它有效。)我发现
file\u put\u contents
关闭了文件,所以我不得不重新打开它。感谢您的帮助它给了我以下信息:
警告:substr()希望参数1是字符串,给定的资源
您将向该函数传递什么?它应该是这样的:
$file='something.csv'
$content=file\u get\u contents($file)
var_转储(removeBomUtf8($content))
然后开始处理此文件。在此行中:
$content=file\u get\u contents($file)
$file
更改为
$filepath
好的,这是一些进步。Thnx。现在,我得到一个字符串,其中包含所有csv数据,但没有BOM表。令人惊叹的。如果我删除
var_dump
并让我的脚本继续执行
($line=fgetcsv(removeBomUtf8($content),1000,;))!==FALSE){
它会给我一个没有错误或进度的空白页。有什么想法吗?删除UTF16小尾端BOM
(substr($s,0,2)==chr(0xFF)。chr(0xFE))
如果您不能确定是否有BOM标记,最好检查它,如果没有,则倒带:
如果(!fread($handle,3)=chr(0xEF).chr(0xBB).chr(0xBF)){rewind($handle);}
而不是
fseek
,这是正确的,但它不会删除BOM,这就是问题所在
// Strip byte order marks from a string
function strip_bom($string, $type = 'utf8') {
    $length = 0;

    switch($type) {
        case 'utf8':
            $length = substr($string, 0, 3) === chr(0xEF) . chr(0xBB) . chr(0xBF) ? 3 : 0;
        break;

        case 'utf16_little_endian':
            $length = substr($string, 0, 2) === chr(0xFF) . chr(0xFE) ? 2 : 0;
        break;
    }

    return $length ? substr($string, $length) : $string;
}
switch (true) { 
    case (substr($string,0,3) == "\xef\xbb\xbf") :
        $string = substr($string, 3);
        break;
    case (substr($string,0,2) == "\xfe\xff") :                            
        $string = mb_convert_encoding(substr($string, 2), "UTF-8", "UTF-16BE");
        break;
    case (substr($string,0,2) == "\xff\xfe") :                            
        $string = mb_convert_encoding(substr($string, 2), "UTF-8", "UTF-16LE");
        break;
    case (substr($string,0,4) == "\x00\x00\xfe\xff") :
        $string = mb_convert_encoding(substr($string, 4), "UTF-8", "UTF-32BE");
        break;
    case (substr($string,0,4) == "\xff\xfe\x00\x00") :
        $string = mb_convert_encoding(substr($string, 4), "UTF-8", "UTF-32LE");
        break;
    default:
        $string = iconv(mb_detect_encoding($string, mb_detect_order(), true), "UTF-8", $string);
};
ini_set('auto_detect_line_endings',TRUE);
$file = fopen($filepath, "r") or die("Error opening file");
if (fgets($file, 4) !== "\xef\xbb\xbf") //Skip BOM if present
        rewind($file); //Or rewind pointer to start of file

$i = 0;
while(($line = fgetcsv($file, 1000, ";")) !== FALSE) {
    ...
}