1

有没有办法使用 PHP 的流包装器读取特定字符编码(如 UTF-16)的文件,就像我可以使用读取 base64 编码的文件一样php://filter/convert.base64-decode/resource=file.txt

4

1 回答 1

1

PHP 字符串对编码一无所知,因此 PHP 文件函数本质上将每个文件都视为二进制文件。

如果您知道应该将一组字节读取为 UTF-16,则可以使用以下任何一种(取决于您安装的扩展)将其转换您选择的其他编码(这里使用 UTF-8 作为示例):

// Requires ext/iconv; arguments are From, To, String
$utf8_string = iconv('UTF-16', 'UTF-8', $utf16_string);
// Requires ext/mbstring; arguments are String, To, From
$utf8_string = mb_convert_encoding($utf16_string, 'UTF-8', 'UTF-16');
// Requires ext/intl; arguments are String, To, From
$utf8_string = UConverter::transcode($utf16_string, 'UTF-8', 'UTF-16');

相反,如果您知道字符串采用某种特定的编码(再次以 UTF-8 为例),并希望它是 UTF-16,您可以按相反的顺序排列:

// Requires ext/iconv; arguments are From, To, String
$utf16_string = iconv('UTF-8', 'UTF-16', $utf8_string);
// Requires ext/mbstring; arguments are String, To, From
$utf16_string = mb_convert_encoding($utf8_string, 'UTF-16', 'UTF-8');
// Requires ext/intl; arguments are String, To, From
$utf16_string = UConverter::transcode($utf8_string, 'UTF-16', 'UTF-8');

在这两种情况下,生成的字符串只是不同的字节序列;其他 PHP 函数仍然不会“知道”它的“含义”。


“iconv”扩展还提供了一个转换过滤器iconv,它在读取文件或流时运行等效的函数。因此,如果您有一个您知道应该以 UTF-16 格式读取的文件,并且希望其内容为 UTF-8,您可以编写:

$fp = fopen('php://filter/convert.iconv.utf-16.utf-8/resource=/path/to/utf16-file.txt', 'r');
$first_10_bytes_of_utf16_converted_to_utf8 = fgets($fp, 10);
fclose($fp);

或者反过来 - 一个您想要读取为 UTF-16 的 UTF-8 文件:

$fp = fopen('php://filter/convert.iconv.utf-8.utf-16/resource=/path/to/utf8-file.txt', 'r');
$first_10_bytes_of_utf8_converted_to_utf16 = fgets($fp, 10);
fclose($fp);

同样,重要的是要记住 PHP 以字节为单位工作,因此上述fgets调用可能会导致文本损坏,因为第 10 个字节不是 Unicode 代码点的结尾。

于 2021-12-12T19:22:43.810 回答