如何在php中将文件转换为UTF-8?

9

我能否在本地将文件转换为UTF-8格式?

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

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

注意:用户可以上传任何字符集的CSV文件,我通常遇到一个未知的8位字符集。
我尝试。
$row = array();
$datas = file($_FILES['file']['tmp_name']);
foreach($datas as $data) {
    $data = mb_convert_encoding($data, 'UTF-8');
    $row[] = explode(',', $data);
}

但问题在于,这段代码会移除特殊字符,比如单引号。

我的第一个问题是htmlspecialchars是否会从数组中移除值?

我将其放置作为额外信息。感谢那些能够提供帮助的人!


Any sample file one can try? - Tarun Lalwani
5
您可以在此处找到答案:https://dev59.com/Zmsz5IYBdhLWcg3wVGEy#7980354。 - Tomas Votruba
{btsdaf} - Julio de Leon
{btsdaf} - IMSoP
请查看PHP的iconv扩展,它具有一些非常好的字符编码转换机制,比mb函数家族要好得多... - EJTH
5个回答

4
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时,这个方案非常出色。 - Eric P
谢谢,伙计,它工作得很出色! - Valentoni

3
在将其转换为UTF-8之前,您需要知道它的字符集。 如果您无法弄清楚,那么您就不能以任何明智的方式将其转换为UTF-8。 然而,一种不明智的方法是将其转换为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 数组在布局上更加合理。

表单是一个标准表单,只需将数据 POST 到服务器即可。
注意:使用 $_SERVER["PHP_SELF"] 是一种安全风险,请参见此处获取更多信息

当数据被提交时,我将文件存储在一个变量中。显然,如果您使用了 multiple 属性,则代码看起来不会完全像这样。

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

$enc 使用 mb_detect_encoding 函数来检测编码(duh)。
起初我遇到了获取正确编码的问题。将 encoding_list 设置为仅使用 UTF-8,并将 strict 设置为 true。

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


@OblivionCoder,您能否确认一下这个答案是否解决了您的问题? - JustCarty

1

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

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");

1
你为什么将 PHP 关键字转换为大写? - zessx
没问题,但这有点奇怪。这是否意味着您从未使用过编辑器的自动完成和片段? - zessx

1

让我们试试这个:

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);
}

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