我正在研究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字体表:
的
更新:单独更新字体名称不会有所作为。区域设置似乎是一个大问题。我已经看到一些网站讨论将日语RTF显示转换为大多数读者可以处理的方法,但我还没有找到解决方案,例如: here和here。
答案 0 :(得分:1)
我的猜测是,改变RTF中的字体名称可能会让事情变得更糟。如果RTF中指定的字体不是Unicode字体,那么应该以该字体呈现的字符将被编码为Shift-JIS,而不是Unicode。然后文本中的其他字符也将如此。因此将整个事物视为Unicode或附加Unicode文本将导致您看到的损坏。您需要确定导入的RTF是编码为Shift-JIS还是Unicode,以及您运行的计算机(以及D2009默认输入格式)是否为日语。在日本,如果文本文件没有Unicode BOM,则通常是Shift-JIS(但并非总是如此)。
答案 1 :(得分:1)
我看到类似的东西,但没有日文字体。只是特殊的字符,如微(如微升)和上标。问题是,即使我从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
不确定这是否有助于解决您的问题,但这对我有用。