【问题标题】:How to convert a file to UTF-8 in php?如何在php中将文件转换为UTF-8?
【发布时间】:2018-04-01 05:48:18
【问题描述】:

我可以将文件转换为 UTF-8 吗?

如果我在提交后可以访问文件

$_FILES['file']['tmp_name']

注意:用户可以上传任何字符集的 CSV 文件,我通常会遇到 unknown 8-bit 字符集。

我试试

$row = array();
$datas = file($_FILES['file']['tmp_name']);
foreach($datas as $data) {
    $data = mb_convert_encoding($data, 'UTF-8');
    $row[] = explode(',', $data);
}

但问题是,这段代码删除了像单引号这样的特殊字符。

我的第一个问题是htmlspecialchars remove the value inside the array?

我放它是为了获得更多信息。感谢那些可以提供帮助的人!

【问题讨论】:

  • 任何示例文件可以尝试吗?
  • 您可能会在这里找到答案:stackoverflow.com/a/7980354/1348344
  • 所以最好的解决方案就是检测它是否包含 utf-8?
  • 我认为这是 TomášVotruba (stackoverflow.com/questions/7979567/…) 链接的问题的副本。您的字符串来自文件这一事实没有任何区别,因为实际上这里的所有代码都是填充$data,就像在另一个问题中一样,它是一个未知编码的字符串。不过,在赏金开放期间,我似乎无法关闭为重复项。
  • 查看 PHP 的 iconv 扩展,它有一些非常好的字符编码转换机制,比 mb_family 函数好多了...

标签: php encoding utf-8


【解决方案1】:

在将其转换为 utf-8 之前,您需要知道它是什么字符集。 如果您无法弄清楚,则无法以任何理智的方式将其转换为utf8 .. 但是,如果无法确定编码,则将其转换为 utf-8 是一种疯狂的方法, 是简单地剥离在 utf-8 中不合法的任何字节,你 也许可以将其用作后备...

警告,未经测试的代码(我突然很匆忙),但可能看起来像这样:

foreach ( $datas as $data ) {
    $encoding = guess_encoding ( $data );
    if (empty ( $encoding )) {
        // encoding cannot be determined...
        // as a fallback, we simply strip any bytes that isnt valid utf-8...
        // obviously this isn't a reliable conversion scheme.
        // also this could probably be improved
        $data = iconv ( "ASCII", "UTF-8//TRANSLIT//IGNORE", $text );
    } else {
        $data = mb_convert_encoding ( $data, 'UTF-8', $encoding );
    }
    $row [] = explode ( ',', $data );
}
function guess_encoding(string $str): string {
    $blacklist = array (
            'pass',
            'auto',
            'wchar',
            'byte2be',
            'byte2le',
            'byte4be',
            'byte4le',
            'BASE64',
            'UUENCODE',
            'HTML-ENTITIES',
            '7bit',
            '8bit' 
    );
    $encodings = array_flip ( mb_list_encodings () );
    foreach ( $blacklist as $tmp ) {
        unset ( $encodings [$tmp] );
    }
    $encodings = array_keys ( $encodings );
    $detected = mb_detect_encoding ( $str, $encodings, true );
    return ( string ) $detected;
}

【讨论】:

    【解决方案2】:

    试试这个。
    我使用的示例是我在测试环境中所做的,您可能需要稍微更改代码。

    我有一个包含以下数据的文本文件:

    test
    café
    áÁÁÁááá
    žžœš¥±
    ÆÆÖÖÖasØØ
    ß
    

    然后我有一个表单,它接受文件输入并执行以下代码:

    function neatify_files(&$files) {
        $tmp = array();
        for ($i = 0; $i < count($_FILES); $i++) {
            for ($j = 0; $j < count($_FILES[array_keys($_FILES)[$i]]["name"]); $j++) {
                $tmp[array_keys($_FILES)[$i]][$j]["name"] = $_FILES[array_keys($_FILES)[$i]]["name"][$j];
                $tmp[array_keys($_FILES)[$i]][$j]["type"] = $_FILES[array_keys($_FILES)[$i]]["type"][$j];
                $tmp[array_keys($_FILES)[$i]][$j]["tmp_name"] = $_FILES[array_keys($_FILES)[$i]]["tmp_name"][$j];
                $tmp[array_keys($_FILES)[$i]][$j]["error"] = $_FILES[array_keys($_FILES)[$i]]["error"][$j];
                $tmp[array_keys($_FILES)[$i]][$j]["size"] = $_FILES[array_keys($_FILES)[$i]]["size"][$j];
            }
        }
        return $files = $tmp;
    }
    
    if (isset($_POST["submit"])) {
        neatify_files($_FILES);
        $file = $_FILES["file"][0];
    
        $handle = fopen($file["tmp_name"], "r");
        while ($line = fgets($handle)) {
            $enc = mb_detect_encoding($line, "UTF-8", true);
            if (strtolower($enc) != "utf-8") {
                echo "<p>" . (iconv($enc, "UTF-8", $line)) . "</p>";
            } else {
                echo "<p>$line</p>";
            }
        }
    }
    ?>
    <form action="<?= $_SERVER["PHP_SELF"]; ?>" method="POST" enctype="multipart/form-data">
        <input type="file" name="file[]" />
        <input type="submit" name="submit" value="Submit" />
    </form>
    

    neatify_files 函数是我编写的,目的是使 $_FILES 数组的布局更符合逻辑。

    该表单是一个标准表单,只需POSTs 将数据发送到服务器。
    注意:使用$_SERVER["PHP_SELF"] 存在安全风险,see here for more

    发布数据后,我将文件存储在一个变量中。显然,如果您使用 multiple 属性,您的代码将不会像这样。

    $handle 以只读格式存储文本文件的全部内容;因此"r" 参数。

    $enc 使用mb_detect_encoding 函数来检测编码(呵呵)。
    起初我无法获得正确的编码。将encoding_list 设置为仅使用UTF-8,并将strict 设置为true。

    如果编码是 UTF-8,那么我只需打印该行,如果不是,我使用 iconv 函数将其转换为 UTF-8。

    【讨论】:

    • @OblivionCoder 您是否有机会确认此答案是否解决了您的问题?
    【解决方案3】:

    您可以使用以下方法将文件文本转换为二进制数据

    FUNCTION bin2text($bin_str) 
    { 
        $text_str = ''; 
        $chars = EXPLODE("\n", CHUNK_SPLIT(STR_REPLACE("\n", '', $bin_str), 8)); 
        $_I = COUNT($chars); 
        FOR($i = 0; $i < $_I; $text_str .= CHR(BINDEC($chars[$i])), $i  ); 
        RETURN $text_str; 
    } 
    
    FUNCTION text2bin($txt_str) 
    { 
        $len = STRLEN($txt_str); 
        $bin = ''; 
        FOR($i = 0; $i < $len; $i  ) 
        { 
            $bin .= STRLEN(DECBIN(ORD($txt_str[$i]))) < 8 ? STR_PAD(DECBIN(ORD($txt_str[$i])), 8, 0, STR_PAD_LEFT) : DECBIN(ORD($txt_str[$i])); 
        } 
        RETURN $bin; 
    }
    

    将数据转换为二进制后,您只需将文本更改为 php 方法 mb_convert_encoding($fileText, "UTF-8");

    【讨论】:

    • PHP 关键字为什么要大写?
    • 不是问题,但这有点奇怪。这是否意味着你从不使用编辑器的自动补全和 sn-ps?
    【解决方案4】:

    让我们试试这个:

    function encode_utf8($data)
    {
        if ($data === null || $data === '') {
            return $data;
        }
        if (!mb_check_encoding($data, 'UTF-8')) {
            return mb_convert_encoding($data, 'UTF-8');
        } else {
            return $data;
        }
    }
    

    用法:

    $content = file_get_contents($_FILES['file']['tmp_name']);
    $content = encode_utf8($content);
    
    $rows = explode("\n", $content);
    foreach ($rows as $row) {
        print_r($row);
    }
    

    【讨论】:

      【解决方案5】:
      function convert_file_to_utf8($source, $target) {
          $content=file_get_contents($source);
          # detect original encoding
          $original_encoding=mb_detect_encoding($content, "UTF-8, ISO-8859-1, ISO-8859-15", true);
          # now convert
          if ($original_encoding!='UTF-8') {
              $content=mb_convert_encoding($content, 'UTF-8', $original_encoding);
      
          }
          $bom=chr(239) . chr(187) . chr(191); # use BOM to be on safe side
          file_put_contents($target, $bom.$content);
      }
      

      【讨论】:

      • 出色地解决了我通过 LOAD DATA LOCAL INFILE 处理格式不可预测的 CSV 的问题。
      猜你喜欢
      • 1970-01-01
      • 2010-09-16
      • 1970-01-01
      • 1970-01-01
      • 2017-12-08
      • 2023-03-16
      • 2015-04-07
      • 2012-08-04
      • 1970-01-01
      相关资源
      最近更新 更多