gpt4 book ai didi

delphi - 当非 unicode 页面为韩语 (949) 时,为什么 ReadLine 会误解 UTF 8 文本?

转载 作者:行者123 更新时间:2023-12-01 21:48:16 25 4
gpt4 key购买 nike

在 Delphi XE2 中,当系统语言环境为英语时,我只能使用 AssignFileReadLn() 例程读取和显示 unicode 字符(来自 UTF8 编码文件)。

失败的地方
如果我将非 unicode 应用程序的系统区域设置设置为韩语(我认为代码页 949)并重复相同的读取,我的一些 UTF8 多字节对将被替换为 $3F。这仅适用于使用 ReadLn,而不适用于使用 TFile.ReadAllText(aFilename, TEncoding.UTF8)TFileStream.Read()

测试
1. 我创建一个文本文件,UTF8 w/o BOM (Notepad++),其中包含以下字符(第二行显示的十六进制等效值):

테스트
ed 85 8c ec 8a a4 ed 8a b8
  • 使用 TMemo 控件编写 Delphi XE 2 Windows 窗体应用程序:

    procedure TForm1.ReadFile(aFilename:string);
    var
    gFile : TextFile;
    gLine : RawByteString;
    gWideLine : string;
    begin
    AssignFile(gFile, aFilename);
    try
    Reset(gFile);
    Memo1.Clear;
    while not EOF(gFile) do
    begin
    ReadLn(gFile, gLine);
    gWideLine := UTF8ToWideString(gLine);
    Memo1.Lines.Add(gWideLine);
    end;
    finally
    CloseFile(gFile);
    end;
    end;
  • 在执行 UTF8ToWideString 对话之前,我检查了 gLine 的内容,在英语/美国语言环境 Windows 下,它是:

    $ED $85 $8C $EC $8A $A4 $ED $8A $B8

  • 顺便说一句,如果我读取带有 BOM 的同一文件,我会得到正确的 3 字节前导码,并且执行 UTF8 解码时的输出是相同的。到目前为止一切正常!

  • 切换 Windows 7 (x64) 以使用韩语作为不支持 Unicode 的应用程序的代码页(区域和语言 --> 管理选项卡 --> 更改系统区域设置 --> 韩语(韩国)。重新启动计算机。

  • 使用上述应用程序读取同一文件(UTF8 w/o BOM),并且 gLine 现在具有十六进制值:

    $3F $8C $EC $8A $A4 $3F $3F

    TMemo 中的输出:?�스??

  • 假设 ReadLn()(以及与此相关的 Read())尝试将 UTF8 序列映射为韩语多字节序列(即尝试解释 $ ED $85,不能,所以在问号中的潜艇 $3F)。

  • 使用 TFileStream 准确读取预期的字节数(9 个无 BOM),内存中的十六进制现在正好是:

    $ED $85 $8C $EC $8A $A4 $ED $8A $B8

    TMemo 中的输出:테스트(完美!)

  • 问题: 懒惰 - 我有很多遗留例程,可以逐行解析可能很大的文件,并且我想确保不需要编写例程来手动读取新文件每个文件的行。

    问题:

    1. 为什么 Read() 没有返回文件中找到的确切字节字符串?是因为我使用的是 TextFile 类型,所以 Delphi 使用非 unicode 代码页进行一定程度的解释吗?

    2. 是否有内置方法可以逐行读取 UTF8 编码文件?

    更新:

    刚刚遇到 Rob Kennedy 的解决方案 this post这让我重新认识了 TStreamReader,它回答了如何优雅地逐行读取 UTF8 文件的问题。

    最佳答案

    Is there a built in way to read a UTF8 encoded file line by line?

    使用TStreamReader 。它有一个 ReadLine()方法。

        procedure TForm1.ReadFile(aFilename:string);
    var
    gFile : TStreamReader;
    gLine : string;
    begin
    Memo1.Clear;
    gFile := TStreamReader.Create(aFilename, TEncoding.UTF8, True);
    try
    while not gFile.EndOfStream do
    begin
    gLine := gFile.ReadLine;
    Memo1.Lines.Add(gLine);
    end;
    finally
    gFile.Free;
    end;
    end;

    话虽如此,这个特定的示例可以大大简化:

        procedure TForm1.ReadFile(aFilename:string);
    begin
    Memo1.Lines.LoadFromFile(aFilename, TEncoding.UTF8);
    end;

    关于delphi - 当非 unicode 页面为韩语 (949) 时,为什么 ReadLine 会误解 UTF 8 文本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29186026/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com