从大型文本文件中读取unicode字符

3
如何读取 Unicode 字符,例如 "ä"?
public static string Read(int length, string absolutePath)
{
    StringBuilder resultAsString = new StringBuilder();

    using (MemoryMappedFile memoryMappedFile = MemoryMappedFile.CreateFromFile(absolutePath))
    using (MemoryMappedViewStream memoryMappedViewStream = memoryMappedFile.CreateViewStream(0, length))
    {
        for (int i = 0; i < length; i++)
        {                  
            int result = memoryMappedViewStream.ReadByte();

            if (result == -1)
            {
                break;
            }
            char letter = (char)result;

            resultAsString.Append(letter);
        }
    }

    return resultAsString.ToString();
}

读取 int (result) 的值为195,而对其进行 char 类型转换后结果并不是预期的。


它使用的是什么编码? - canton7
Unicode是一种多字符编码(多字节)。UTF-8可以使用1到4个字节来编码Unicode代码点。[易于性能:您可以随机查找,然后在下一个字节中查找Unicode代码点的起始位置[唯一的位序列]。注意:一个字形可能有多个代码点(通常是字符+组合字符[例如重音符号])。正如您所看到的,它很复杂,但通常不需要所有部分。您应该更好地说明您想要什么?(即结果的用途是什么) - Giacomo Catenazzi
编码应该是ASCII...但我不知道如何改为Unicode。我想显示所有正确的字符。 - mty
2个回答

2
不确定这是否是您所要求的,但您可以使用StreamReader。最初的回答。
StreamReader sr = new StreamReader(stream, Encoding.Unicode);

我需要性能,这就是为什么要使用MemoryMappedViewStream的原因。 - mty
@mty:你想要性能,但你却用一个for循环来进行转换,并且还使用了“append”?我建议你先构建一个好的版本,然后再做一个性能版本(但你需要测试,以便快速检查你是否正确地进行了优化)。 - Giacomo Catenazzi
这个注释没有帮助,你可以看到我使用了特定的长度。 - mty

0
如果您只想将一个UTF-8文件加载并读入字符串变量中,代码可以非常简单。
var text = File.ReadAllText(filePath, Encoding.UTF8);

如果您坚持逐字节处理UTF-8数据,那么解析会更加复杂一些。
这是一个粗略但可行的草图,可与您的原始代码配合使用:

StringBuilder resultAsString = new StringBuilder();

using (MemoryMappedFile memoryMappedFile = MemoryMappedFile.CreateFromFile(filePath))
using (MemoryMappedViewStream viewStream = memoryMappedFile.CreateViewStream(0, new FileInfo(filePath).Length))
{
    int b;
    while((b = viewStream.ReadByte()) != -1)
    {
        int acc = b;

        bool readUtfDataBytes(int bytesToRead)
        {
            while (bytesToRead-- > 0)
            {
                var nextB = viewStream.ReadByte();
                if (nextB == -1) return false; // EOS reached
                if ((nextB & 0xC0) != 0x80) return false; // invalid UTF-8 data byte
                acc <<= 6;
                acc |= nextB & 0x3F;
            }
            return true;
        }

        if (b >= 0xF0) // 1111 0000
        {
            acc &= 0x07;
            if (!readUtfDataBytes(3)) break; // break on malformed UTF-8
        }
        else if (b >= 0xE0) // 1110 0000
        {
            acc &= 0x0F;
            if (!readUtfDataBytes(2)) break; // break on malformed UTF-8
        }
        else if (b >= 0xC0) // 1100 0000
        {
            acc &= 0x1F;
            if (!readUtfDataBytes(1)) break; // break on malformed UTF-8
        }
        else if (b >= 0x80)
        {
            break; // break on malformed UTF-8
        }

        if (acc == 0xFEFF)
        {
            // ignore UTF-8 BOM
        }
        else
        {
            resultAsString.Append(Char.ConvertFromUtf32(acc));
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接