Skip to content

iconv 字符编码转换

PHP 的 iconv 扩展提供了字符编码之间的转换功能。在处理多语言数据时,字符编码转换是必不可少的操作。iconv 支持几乎所有常见的字符编码格式,包括 UTF-8、GBK、BIG5、ISO-8859-1、Shift-JIS 等。

前置知识

阅读本节前,建议先了解:字符串处理intl 扩展

基础概念

安装

bash
# 编译安装
./configure --with-iconv

# Ubuntu/Debian
sudo apt-get install php-iconv

# 检查可用编码
echo iconv -l | head -20

iconv 函数

基本转换

php
<?php
declare(strict_types=1);

// GBK 转 UTF-8
$utf8 = iconv('GBK', 'UTF-8', '中文内容');
echo $utf8 . PHP_EOL;

// UTF-8 转 GBK
$gbk = iconv('UTF-8', 'GBK', '中文内容');
echo $gbk . PHP_EOL;

// UTF-8 转 ISO-8859-1
$iso = iconv('UTF-8', 'ISO-8859-1//IGNORE', 'Hello 世界');
// //IGNORE 忽略无法转换的字符

// BIG5 转 UTF-8
$utf8 = iconv('BIG5', 'UTF-8', $big5String);

错误处理选项

php
<?php
declare(strict_types=1);

// 输出编码后缀选项:
// //IGNORE   - 忽略无法转换的字符
// //TRANSLIT - 将无法转换的字符用近似字符替代

// 忽略无法转换的字符
$result = iconv('UTF-8', 'ISO-8859-1//IGNORE', 'Hello 世界');
echo $result . PHP_EOL; // Hello

// 音译替代
$result = iconv('UTF-8', 'ASCII//TRANSLIT', 'cafe résumé');
echo $result . PHP_EOL; // cafe resume

// 同时使用
$result = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', 'cafe résumé 世界');
echo $result . PHP_EOL;

获取编码信息

php
<?php
declare(strict_types=1);

// 检测字符串编码
$encoding = mb_detect_encoding($string, ['UTF-8', 'GBK', 'BIG5', 'ISO-8859-1'], true);
echo "检测到的编码: {$encoding}" . PHP_EOL;

// iconv 获取支持的编码列表
// $encodings = iconv_get_encoding('all');

实战示例

文件编码转换

php
<?php
declare(strict_types=1);

/**
 * 将文件从一种编码转换为另一种
 */
function convertFileEncoding(
    string $inputPath,
    string $outputPath,
    string $fromEncoding,
    string $toEncoding
): void {
    $content = file_get_contents($inputPath);
    $converted = iconv($fromEncoding, $toEncoding . '//IGNORE', $content);
    file_put_contents($outputPath, $converted);
}

// GBK 文件转 UTF-8
convertFileEncoding('/path/to/gbk-file.txt', '/path/to/utf8-file.txt', 'GBK', 'UTF-8');

批量文件编码检测与转换

php
<?php
declare(strict_types=1);

class EncodingConverter
{
    private string $targetEncoding;

    public function __construct(string $targetEncoding = 'UTF-8')
    {
        $this->targetEncoding = $targetEncoding;
    }

    /**
     * 检测并转换字符串编码
     */
    public function convert(string $content, ?string $fromEncoding = null): string
    {
        if ($fromEncoding === null) {
            $fromEncoding = mb_detect_encoding($content, ['UTF-8', 'GBK', 'BIG5', 'ISO-8859-1'], true);
        }

        if ($fromEncoding === $this->targetEncoding) {
            return $content;
        }

        $result = @iconv($fromEncoding, $this->targetEncoding . '//IGNORE', $content);

        return $result !== false ? $result : $content;
    }

    /**
     * 转换目录下所有文件
     */
    public function convertDir(string $dir, array $extensions = ['txt', 'php', 'html']): void
    {
        $iterator = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS)
        );

        foreach ($iterator as $file) {
            $ext = $file->getExtension();
            if (!in_array($ext, $extensions)) {
                continue;
            }

            $content = file_get_contents($file->getPathname());
            $converted = $this->convert($content);

            if ($converted !== $content) {
                file_put_contents($file->getPathname(), $converted);
                echo "已转换: {$file->getPathname()}" . PHP_EOL;
            }
        }
    }
}

注意事项

  • iconv() 在转换失败时返回 false
  • 使用 //IGNORE//TRANSLIT 处理无法转换的字符
  • PHP 8.2+ 中 iconv 扩展始终可用

下一节

继续学习:Gettext 本地化

参考链接