如何从 UTF-8 编码文件中删除无效字符?

问题描述 投票:0回答:2

解释

我在编写网络应用程序时遇到了一个边缘情况。我接受要上传的 UTF-8 文件,并且我已经进行了检查以确认它是 UTF-8 编码的(或者至少是可能的最佳检查,显然没有灵丹妙药,我知道有很多关于该特定问题的 Stack Overflow 上的其他问题)。

作为测试,我采用了 ANSI 编码文件并将其转换为 UTF-8,方法是(在单独的测试中)在 Notepad++ 中将其转换为 UTF-8,并在上将其解码为 UTF-8(即使它是 ANSI) C# 中的苍蝇使用

Encoding.UTF.GetBytes(inputStream)

问题出现在哪里

随后,我将文件的原始数据作为 XML 文件中的元素之一放置。这就是问题出现的地方。看起来 ANSI 文件中保留了一个字符(我假设)在 UTF-8 中无效。当我尝试使用以下命令加载 XML 时...

XDocument xmlSample = XDocument.Load(outputPath);

我遇到了这个异常...

{"Invalid character in the given encoding. Line 10, position 14."}

在 Visual Studio 中看起来像这样...

VSImg

就像在 Notepad++ 中这样...

NPPImg

以下是字符复制粘贴。

来自 NPP:

¡
来自 Visual Studio 字符串查看器:

问题

如何从 UTF-8 编码文件中删除无效字符,或者至少以合理的方式发现它们,以便我可以拒绝该文件?

c# unicode encoding utf-8 character-encoding
2个回答
2
投票

首先,就您的示例而言,“温度”一词表明有问题的字符实际上是“度”符号(°,Unicode 176),因此全文为“温度(°C)”。在这种情况下,字符将在 ANSI 中编码为

\260
字节,在 UTF-8 中编码为两个字节
\302\260
\260
(在本例中前面带有左括号)不是有效的 UTF-8。

第二 – 如果一年多后您仍然感兴趣 – 您能否澄清一下如何使用

Encoding.UTF.GetBytes()
“将文件解码为 UTF-8”?
GetBytes()
读取字符,而不是字节,并且C#中的字符没有编码;读取文件并将其转换为字符时已应用编码。
UTF.GetBytes()
的作用是将字符编码(而不是解码)为 UTF-8 字节序列。

为了检查传入的字节序列,您可以使用

Encoding.UTF.GetChars()
将字节序列解码为字符。根据您使用的构造函数,您可以获得“清理”的字符串(如果出现问题,则会丢失数据)或在有问题的字节序列上收到
DecoderFallbackException
,因此您可以拒绝输入。


0
投票

如果您想过滤掉无效的 UTF-8 字符,例如来自未知来源的字符,或者作为截断字符串的结果,您可以使用

DecoderFallbackException
,如 @Renardo 所描述。

实现示例:

public static string GetValidString(Encoding encoding, byte[] bytes)
{
    try
    {
        // Try to encode the bytes
        return encoding.GetString(bytes);
    }
    catch (DecoderFallbackException ex)
    {
        // Get the succesful part
        var start = encoding.GetString(bytes[..ex.Index]);

        // If there is any part after the invalid bytes, add it to start
        int? resume = ex.BytesUnknown != null
            ? ex.Index + ex.BytesUnknown.Length
            : null;

        return resume != null && bytes.Length > resume
            ? start + GetValidString(encoding, bytes[resume.Value..])
            : start;
    }
}

用途:

var utf8 = new UTF8Encoding(false, true); // throw DecoderFallbackException on invalid characters
var bytes = utf8.GetBytes("🐞🐞")[..5]; // [0xF0, 0x9F, 0x90, 0x9E, 0xF0]
var validString = GetValidString(utf8, bytes); // "🐞"

如果你愿意,你可以将其作为

Encoding
的扩展方法。

© www.soinside.com 2019 - 2024. All rights reserved.