写的时候编码有问题

Something wrong with encoding while writing

我正在尝试使用这段代码将一些(生成的)数据写入文件:

define("LANG_DIR", "/var/www/html/app/lang/");
define("TAB", "\t");
define("NL", "\n");
define('FILE_START', '<?php' . NL . NL . "return array(" . NL);
define('FILE_END', NL . ');');

// Some parsing here    

foreach ($fileContent as $fileName => $value) {
    $fileString = FILE_START;

    foreach ($value as $arrayKey => $arrayValue) {
        $fileString .= TAB . "'" . $arrayKey . "'" . TAB . TAB . "=>" . TAB . TAB .  "'" . $arrayValue . "'," . NL;
    }

    $fileString .= FILE_END;

    $filePath = LANG_DIR . $desLang . "/" . $fileName . ".php";
    $filePath = strval(str_replace("[=10=]", "", $filePath));

    $handle = fopen($filePath, "w+b");
    fwrite($handle, $fileString); // "\xEF\xBB\xBF" .
    fclose($handle);

    echo $filePath . "<br />";
    echo '<br /><textarea rows="10" cols="100"> ' . $fileString . '</textarea><br />';
}

这将导致文件如下所示:

3c3f 7068 700a 0a72 6574 7572 6e20 6172
7261 7928 0a09 2700 6900 6e00 6100 6300
7400 6900 7600 6500 2709 093d 3e09 0927
0049 006e 0061 006b 0074 0069 0076 0065
0020 0047 0061 0062 0065 006c 0073 0074
0061 0070 006c 0065 0072 0027 2c0a 0927
006e 0069 0065 0075 0077 0027 0909 3d3e
0909 2700 4e00 6500 7500 6500 7200 2000
4700 6100 6200 6500 6c00 7300 7400 6100
7000 6c00 6500 7200 272c 0a09 2700 6900
6400 2709 093d 3e09 0927 0049 0044 0027
2c0a 0927 006e 0061 006d 0065 0027 0909
3d3e 0909 2700 4e00 6100 6d00 6500 2000
4700 6100 6200 6500 6c00 7300 7400 6100
7000 6c00 6500 7200 272c 0a09 2700 7300
7400 6100 7400 7500 7300 2709 093d 3e09
0927 0053 0074 0061 0074 0075 0073 0027
2c0a 0927 0069 0070 0027 0909 3d3e 0909
2700 4900 5000 2000 4e00 7500 6d00 6d00
6500 7200 272c 0a09 2700 6100 6300 7400
6900 6f00 6e00 2709 093d 3e09 0927 0041
006b 0074 0069 006f 006e 0065 006e 0027
2c0a 0927 0061 0063 0074 0069 0076 0065
0027 0909 3d3e 0909 2700 4100 6b00 7400
6900 7600 272c 0a09 2700 6200 7500 7400
7400 6f00 6e00 5f00 7400 6900 7400 6c00
6500 5f00 6e00 6500 7700 2709 093d 3e09
0927 0045 0069 006e 0065 006e 0020 006e
0065 0075 0065 006e 0020 0047 0061 0062
0065 006c 0073 0074 0061 0070 006c 0065
0072 0020 0068 0069 006e 007a 0075 0066
00fc 0067 0065 006e 0027 2c0a 0927 0062
0075 0074 0074 006f 006e 005f 0074 0069
0074 006c 0065 005f 0065 0064 0069 0074
0027 0909 3d3e 0909 2700 4400 6900 6500
7300 6500 6e00 2000 4700 6100 6200 6500
6c00 7300 7400 6100 7000 6c00 6500 7200
2000 6200 6500 6100 7200 6200 6500 6900
7400 6500 6e00 272c 0a0a 293b 

如果我像这样使用所谓的 UTF-8 BOM:

fwrite($handle, "\xEF\xBB\xBF" . $fileString);

我将此写入文件:

但是当我将它回显到 textarea 时,我得到以下输出:

return array(
    'inactive'      =>      'Inaktive Gabelstapler',
    'nieuw'     =>      'Neuer Gabelstapler',
    'id'        =>      'ID',
    'name'      =>      'Name Gabelstapler',
    'status'        =>      'Status',
    'ip'        =>      'IP Nummer',
    'action'        =>      'Aktionen',
    'active'        =>      'Aktiv',
    'button_title_new'      =>      'Einen neuen Gabelstapler hinzufügen',
    'button_title_edit'     =>      'Diesen Gabelstapler bearbeiten',

);

所以我的问题很简单...发生了什么事?我听到有人说一些关于 utf-8 和 ISO 的东西,但我对此一无所知....

编辑 正如@axiac 所评论的那样,我现在以这种方式对定义进行了编码:

$fileString = convertEnc(FILE_START);

foreach ($value as $arrayKey => $arrayValue) {
    $fileString .= convertEnc(TAB) . "'" . $arrayKey . "'" . convertEnc(TAB) . convertEnc(TAB) . "=>" . convertEnc(TAB) . convertEnc(TAB) .  "'" . $arrayValue . "'," . convertEnc(NL);
}

$fileString .= convertEnc(FILE_END);

// 更多代码...

function convertEnc($input){
    return mb_convert_encoding($input, 'UTF-16');
}

这将导致:

哪个更好(您现在可以阅读一些文字),但仍然不是我所期待的...

正如问题评论中所讨论的(以及在聊天中进一步讨论的),我认为 $fileContent 中的数据编码错误;它似乎是 UTF-16UTF-8 更有用且更易于操作。

我建议您尝试在源(生成文件时)修复来自 $fileContent 的数据的编码。

如果这不可能,我会这样写代码:

// Create the converting function
// It assumes the input string is encoded as UTF-16
// and converts the encoding to UTF-8
$fnFixEncoding = function ($input) {
    return mb_convert_encoding($input, 'UTF-8', 'UTF-16');
};

// Process all the files
foreach ($fileContent as $fileName => $value) {
    // Fix the encoding of the keys and values of $value individually
    // then re-compose the array
    $value = array_combine(
        array_map($fnFixEncoding, array_keys($value)),
        array_map($fnFixEncoding, array_values($value))
    );

    // Generate the PHP code
    $text = '<?php return '.var_export($value, TRUE).';';

    // Generate the file path
    $filePath = LANG_DIR.$desLang.'/'.$fileName.'.php';
    // If $fileName is also encoded as UTF-16 you need to change its encoding too
    // Use $fnFixEncoding($fileName) instead of $fileName in the line above

    // Write the code in the file
    file_put_contents($filePath, $text);
}

// That's all!

备注

如果输入字符串的编码未知或不总是相同,则编码函数必须有更精细的实现,可以使用 mb_detect_encoding() to find the encoding of the input string and pass it as the third argument to mb_convert_encoding():

$fnFixEncoding = function ($input) {
    // The third argument is a list of possible encodings used by $input
    $enc = mb_detect_encoding($input, ['UTF-16', 'UTF-8', 'ISO8859-1']);
    return mb_convert_encoding($input, 'UTF-8', $enc);
};