如何正确显示日语RTF字体

5
我正在使用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\'83\'56\'83\'62\'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的不同翻译可能是潜在原因。如果RTF编写器发出读者无法理解的代码,则任何事情都有可能发生。 - mjn
当在Windows 10上使用Wordpad打开时,字体名称“82l'82r'82o'83S'83V'83b'83N”显示为“'MS PGothic'”。当在LibreOffice中打开或在Win 7上使用Wordpad打开时,它将显示为“'MS Pゴシック'”。 - mjn
请注意,您问题中的字体名称“l?r ?o?S?V?b?N”似乎已经损坏,我猜测它在文档之前的某个状态下是“82l'82r '82o'83S'83V'83b'83N”。 - mjn
你能添加一些RTF的示例吗? - mjn
2个回答

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

1
进一步调查表明更改字体不是一个好主意。具体来说,更改指定的字符集是不可取的,因为\fcharset0是ANSI,\fcharset128是Shift-JIS。至少在表面上,似乎在不同字符集的不同字体之间切换将允许您正确编码用户输入的内容。不幸的是,这仍然不能完全解释为什么RTF控件无法找出正确的显示方式。 - Ryan

1
我遇到了类似的问题,但不是与日语字体有关。只是特殊字符,如微(如微升)和上标。问题在于,即使我从ASP.NET网页向用户发送的RTF字符串是正确的(我可以使用Fiddler2查看编码的RTF流),当MS Word实际打开RTF时,它会添加一堆垃圾转义代码,就像我在您的示例中看到的那样。
我所做的是将整个RTF文本通过转换程序运行,将所有字符交换到其特殊的Unicode点等效位置以上127个ascii。因此,对于特殊字符,我会得到类似于\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

不确定这是否能解决你的问题,但对我来说它是有效的。


感谢提供示例代码!我最初尝试了类似的方法,但由于RTF字符流本身不包含任何Unicode,所以没有任何区别。然而,这仍然是一个非常有用的函数,值得保留。 - Ryan

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