43

我已将某些文件从 Windows 机器复制到 Linux 机器。所以所有的 Windows 编码(windows-1252)文件都需要转换为 UTF-8。不应更改已在 UTF-8 中的文件。我打算为此使用该recode实用程序。如何指定该recode实用程序只应转换 windows-1252 编码文件而不是 UTF-8 文件?

重新编码的示例用法:

recode windows-1252.. myfile.txt

myfile.txt将从 windows-1252 转换为 UTF-8。在这样做之前,我想知道它myfile.txt实际上是 windows-1252 编码的,而不是 UTF-8 编码的。否则,我相信这会损坏文件。

4

11 回答 11

82

iconv -f WINDOWS-1252 -t UTF-8 filename.txt

于 2010-01-06T15:50:04.460 回答
39

您希望 recode 如何知道文件是 Windows-1252?理论上,我相信任何文件都是有效的 Windows-1252 文件,因为它将每个可能的字节映射到一个字符。

现在肯定有一些特征强烈表明它是 UTF-8——例如,如果它以 UTF-8 BOM 开头——但它们不是确定的。

一种选择是首先检测它是否实际上是一个完全有效的 UTF-8 文件,我想......再次,这只是暗示性的。

我不熟悉重新编码工具本身,但您可能想看看它是否能够将文件重新编码为相同的编码 - 如果您使用无效文件(即包含无效 UTF-8 字节序列的文件)执行此操作) 它很可能将无效序列转换为问号或类似的东西。此时,您可以通过将文件重新编码为 UTF-8 并查看输入和输出是否相同来检测文件是有效的 UTF-8。

或者,以编程方式执行此操作,而不是使用重新编码实用程序 - 例如,在 C# 中它会非常简单。

只是重申一下:所有这些都是启发式的。如果您真的不知道文件的编码,那么没有什么可以 100% 准确地告诉您。

于 2010-01-06T15:42:34.927 回答
9

这是我对类似问题给出的另一个答案的转录:

如果将 utf8_encode() 应用于已经是 UTF8 的字符串,它将返回一个乱码的 UTF8 输出。

我做了一个函数来解决所有这些问题。它被称为 Encoding::toUTF8()。

你不需要知道你的字符串的编码是什么。它可以是 Latin1 (iso 8859-1)、Windows-1252 或 UTF8,或者字符串可以混合使用它们。Encoding::toUTF8() 会将所有内容转换为 UTF8。

我这样做是因为一项服务向我提供了一个混乱的数据源,将 UTF8 和 Latin1 混合在同一个字符串中。

用法:

$utf8_string = Encoding::toUTF8($utf8_or_latin1_or_mixed_string);

$latin1_string = Encoding::toLatin1($utf8_or_latin1_or_mixed_string);

下载:

https://github.com/neitanod/forceutf8

更新:

我已经包含了另一个函数,Encoding::fixUFT8(),它将修复每个看起来乱码的 UTF8 字符串。

用法:

$utf8_string = Encoding::fixUTF8($garbled_utf8_string);

例子:

echo Encoding::fixUTF8("Fédération Camerounaise de Football");
echo Encoding::fixUTF8("Fédération Camerounaise de Football");
echo Encoding::fixUTF8("FÃÂédÃÂération Camerounaise de Football");
echo Encoding::fixUTF8("Fédération Camerounaise de Football");

将输出:

Fédération Camerounaise de Football
Fédération Camerounaise de Football
Fédération Camerounaise de Football
Fédération Camerounaise de Football

更新:我已将函数 (forceUTF8) 转换为名为 Encoding 的类上的一系列静态函数。新函数是 Encoding::toUTF8()。

于 2012-09-20T00:15:38.133 回答
8

没有一般方法可以判断文件是否使用特定编码进行编码。请记住,编码只不过是文件中的位应如何映射到字符的“协议”。

如果您不知道哪些文件实际上已经用 UTF-8 编码,哪些文件用 windows-1252 编码,则必须检查所有文件并自己找出答案。在最坏的情况下,这可能意味着您必须使用两种编码中的任何一种打开它们中的每一个,并查看它们是否“看起来”正确——即,所有字符都正确显示。当然,您可以使用工具支持来做到这一点,例如,如果您确定某些字符包含在 windows-1252 与 UTF-8 中具有不同映射的文件中,您可以为它们 grep通过 Seva Akekseyev 提到的“iconv”运行文件后。

另一个幸运的情况是,如果您知道文件实际上只包含在 UTF-8 和 windows-1252 中编码相同的字符。在这种情况下,当然,你已经完成了。

于 2010-01-06T15:52:58.307 回答
8

如果你想在一个命令中重命名多个文件——假设你想转换所有*.txt文件——这里是命令:

find . -name "*.txt" -exec iconv -f WINDOWS-1252 -t UTF-8 {} -o {}.ren \; -a -exec mv {}.ren {} \;
于 2016-01-19T15:54:53.753 回答
2

使用iconv命令。

要确保该文件位于 Windows-1252 中,请在记事本(在 Windows 下)中打开它,然后单击另存为。记事本建议将当前编码作为默认编码;如果它是 Windows-1252(或任何 1 字节代码页,就此而言),它会说“ANSI”。

于 2010-01-06T15:42:51.933 回答
1

您可以使用记事本++ 等编辑器更改文件的编码。只需转到编码并选择您想要的。

我总是喜欢 Windows 1252

于 2013-03-27T17:03:25.077 回答
0

如果您确定您的文件是 UTF-8 或 Windows 1252(或 Latin1),您可以利用如果您尝试转换无效文件时 recode 将退出并出现错误的事实。

虽然 utf8 是有效的 Win-1252,但反之则不然:win-1252 不是有效的 UTF-8。所以:

recode utf8..utf16 <unknown.txt >/dev/null || recode cp1252..utf8 <unknown.txt >utf8-2.txt

将为所有 cp1252 文件吐出错误,然后继续将它们转换为 UTF8。

我会把它包装成一个更干净的 bash 脚本,保留每个转换文件的备份。

在进行字符集转换之前,您可能希望首先确保所有文件中的行尾一致。否则, recode 会因此而抱怨,并可能转换已经是 UTF8 的文件,但只是有错误的行尾。

于 2010-12-20T15:16:02.057 回答
0

找到TYPE 命令的文档

将 ASCII (Windows1252) 文件转换为 Unicode (UCS-2 le) 文本文件:

For /f "tokens=2 delims=:" %%G in ('CHCP') do Set _codepage=%%G    
CHCP 1252 >NUL    
CMD.EXE /D /A /C (SET/P=ÿþ)<NUL > unicode.txt 2>NUL    
CMD.EXE /D /U /C TYPE ascii_file.txt >> unicode.txt    
CHCP %_codepage%    

上述技术(基于 Carlos M. 的脚本)首先创建一个带有字节顺序标记 (BOM) 的文件,然后附加原始文件的内容。CHCP 用于确保会话使用 Windows1252 代码页运行,以便正确解释字符 0xFF 和 0xFE (ÿþ)。

于 2015-10-01T20:54:21.280 回答
0

UTF-8 没有 BOM,因为它既多余又无效。BOM 有帮助的地方是 UTF-16,它可以像 Microsoft 一样进行字节交换。UTF-16 如果用于内存缓冲区中的内部表示。使用 UTF-8 进行交换。默认情况下,UTF-8、从 US-ASCII 和 UTF-16 派生的任何其他内容都是自然/网络字节顺序。Microsoft UTF-16 需要 BOM,因为它是字节交换的。

为了将 Windows-1252 转换为 ISO8859-15,我首先将 ISO8859-1 转换为 US-ASCII 以获得具有相似字形的代码。然后我将 Windows-1252 转换为 ISO8859-15,其他非 ISO8859-15 字形转换为多个 US-ASCII 字符。

于 2016-05-30T05:43:40.130 回答
0

这个脚本在 Win10/PS5.1 CP1250 到 UTF-8 上为我工作

Get-ChildItem -Include *.php -Recurse | ForEach-Object {
    $file = $_.FullName

    $mustReWrite = $false
    # Try to read as UTF-8 first and throw an exception if
    # invalid-as-UTF-8 bytes are encountered.
    try
    {
        [IO.File]::ReadAllText($file,[Text.Utf8Encoding]::new($false, $true))
    }
    catch [System.Text.DecoderFallbackException]
    {
        # Fall back to Windows-1250
        $content = [IO.File]::ReadAllText($file,[Text.Encoding]::GetEncoding(1250))
        $mustReWrite = $true
    }

    # Rewrite as UTF-8 without BOM (the .NET frameworks' default)
    if ($mustReWrite)
    {
        Write "Converting from 1250 to UTF-8"
        [IO.File]::WriteAllText($file, $content)
    }
    else
    {
        Write "Already UTF-8-encoded"
    }
}
于 2022-01-09T16:34:11.577 回答