我正在 Delphi 2009 中开发一个应用程序,该应用程序大量使用 RTF,并使用 TRichEdit 和 TLMDRichEdit 进行编辑。在这些 RTF 控件中输入日语文本的用户不断提交报告,称在安装了东方语言支持的 Win XP 和 Vista 上重新加载内容时,日语文本显示为乱码。

通常,英语和日语是混合的,并且大部分显示都没有问题,例如:

Inventory turns partnerships.  在庫回転率の

(如果日语文本被错误地破坏,我深表歉意 - 我不会说或读这种语言)。

然而,经常只有文本的日语部分会是乱码,例如:

ŒÉñ?“]-¦Œüã‚Ì·•Ê‰?-vˆö‚ðŽû‰v‚ÉŒø‰?“I‚ÉŒ‹‚т‚¯‚é’mŽ¯‚ª‘÷Ý‚·‚é?(マーケットセクター、
見込み客の優  先順位と彼らに販売する知識)

从广泛的在线搜索来看,问题似乎是由于保存为 RTF 一部分的字体造成的。日语版 Windows 上的字体不一定与美国英语版相同。可以通过编程方式替换 RTF 文件中的字体,这会产生几乎可以接受的结果,即

-D‚‚スƒIƒyƒŒ[ƒVƒ・“‚ニƒƒWƒXƒeƒBƒbƒN‚フƒpƒtƒH[ƒ}ƒ“ƒX‚-˜‰v‚ノŒ‹‚ム‚ツ‚ッ‚ネ‚「‚±ニ‚ヘ?A‘‚「‚ノ-ウ‘ハ‚ナ‚ ‚驕B‚サ‚‚ヘAl“セ‚オ‚ス・‘P‚フˆロ‚ƒƒXƒN‚ノ‚ウ‚‚キB

然而,其中仍然有相当多的“垃圾”字符没有被正确识别为日语字符。查看原始 RTF,您将看到以下内容:

-D\'82\'82\u65405?\'83I\'83y\'83\'8c[\'83V\'83\u12539?\ldblquote\'82\u65414?

显然,Unicode 字符已正确呈现,但例如“82”82 对字符应该是其他字符?我的猜测是,它实际上代表某种双字节字符,出于某种神秘的原因,它被编码为两个单独的字符而不是单个 Unicode 字符。

是否有一种通用的、(相对)万无一失的方法来获取包含东方语言的 RTF 并可靠地再次显示它?

为了完整起见,我按以下方式更新了 RTF 字体表:

  • 更换字体名称“?l?r?o?s?v?b?n;”带有“ '82 '6C '82 '72 '82 '6f '83 '53 '53 '83 '56 '56 '83 '62 '83 '83 '4e;”
  • 通过将“\froman\fprq1\fcharset0”替换为“\fnil\fprq1\fcharset128”来更新字体名称
  • 通过将“\froman\fprq1\fcharset238”替换为“\fnil\fprq1\fcharset128”来更新字体名称
  • 通过将“\froman\fprq1”替换为“\fnil\fprq1\fcharset128”来更新字体名称
  • 替换字体名称“????????;”与“\'82\'6c\'82\'72\'82\'6f\'83\'53\'83\'56\'83\'62\'83\' 4e;”

更新:单独更新字体名称不会产生任何影响。区域设置似乎是个大问题。我见过一些网站讨论如何将日语 RTF 的显示转换为大多数读者可以处理的内容,但我还没有找到解决方案,例如:这里这里.

有帮助吗?

解决方案

我的猜测是,更改 RTF 中的字体名称可能会让事情变得更糟。如果 RTF 中指定的字体不是 Unicode 字体,那么以该字体呈现的字符肯定会被编码为 Shift-JIS,而不是 Unicode。然后文本中的其他角色也会如此。因此,将整个内容视为 Unicode,或附加 Unicode 文本,将导致您看到的损坏。您需要确定导入的 RTF 编码是 Shift-JIS 还是 Unicode,以及您运行的计算机(因此 D2009 默认输入格式)是否是日语。在日本,如果文本文件没有 Unicode BOM,则通常是 Shift-JIS(但并非总是如此)。

其他提示

我看到了类似的东西,但不是日语字体。只是特殊字符,例如微(如微升)和上标。问题是,即使我从 ASP.NET 网页发送给用户的 RTF 字符串是正确的(我可以使用 Fiddler2 看到编码的 RTF 流),但当 MS Word 实际打开 RTF 时,它添加了一堆垃圾转义符代码就像我在你的示例中看到的那样。

我所做的是通过一个转换例程运行整个 RTF 文本,该例程将 ascii 127 上的所有字符交换为其特殊的 unicode 点等效值。所以我会得到类似 \uc1\u181 的东西?(微)用于特殊字符。当我这样做时,Word 能够毫无问题地打开该文件。讽刺的是,它重新编码了 \uc1\uxxx?回到他们的 RTF 转义等价物。

Private Function ConvertRtfToUnicode(ByVal value As String) As String

    Dim ch As Char() = value.ToCharArray()
    Dim c As Char
    Dim sb As New System.Text.StringBuilder()
    Dim code As Integer

    For i As Integer = 0 To ch.Length - 1
        c = ch(i)
        code = Microsoft.VisualBasic.AscW(c)
        If code <= 127 Then
            'Don't need to replace if one of your typical ASCII codes
            sb.Append(c)
        Else
            'MR: Basic idea came from here http://www.eggheadcafe.com/conversation.aspx?messageid=33935981&threadid=33935972
            '  swaps the character for it's Unicode decimal code point equivalent
            sb.Append(String.Format("\uc1\u{0:d}?", code))
        End If
    Next

    Return sb.ToString()

End Function

不确定这是否能帮助您解决问题,但它对我有用。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top