我们的部分应用程序解析了RTF文档,我们遇到了一个不能很好地翻译的特殊字符。在Word中查看时,该字符是省略号(...),它在RTF中编码为('85)。
在我们的vb代码中,我们将十六进制(85)转换为int(133),然后将Chr(133)转换为(...)
这是C#中的代码 - 问题是这对127以上的值不起作用。有什么想法吗?
致电代码:
// S is Hex number!!!
return Convert.ToChar(HexStringToInt(s)).ToString();
帮助方法:
private static int HexStringToInt(string hexString)
{
int i;
try
{
i = Int32.Parse(hexString, NumberStyles.HexNumber);
}
catch (Exception ex)
{
throw new ApplicationException("Error trying to convert hex value: " + hexString, ex);
}
return i;
}
答案 0 :(得分:2)
这看起来像是一个字符编码问题。 Unicode不包括数字在ASCII-128-255范围内的任何字符,因此尝试转换字符133将失败。
需要使用正确的解码将其首先转换为字符,Convert.toChar似乎使用UTF-16。
有时会有一个手动位操作黑客将字符从上部ASCII转换为适当的unicode字符,但由于省略号不在大多数广泛使用的扩展ASCII代码页中,因此不太可能在这里工作。
您真正想要做的是使用Encoding.GetString(Byte[])方法,并使用正确的编码。将您的值放入一个字节数组,然后使用GetString获取该字符的C#本机字符串。
您可以在RTF Wikipedia page上了解有关RTF字符编码的更多信息。
仅供参考:水平省略号为character U+2026 (pdf)。
答案 1 :(得分:1)
您的原始代码对我来说非常合适。它能够将任何十六进制从00转换为FF到适当的字符。使用vs2008。
答案 2 :(得分:0)
private static int HexStringToInt(string hexString)
{
try
{
return Convert.ToChar(hexString);
}
catch (FormatException ex)
{
throw new ArgumentException("Is not a valid hex character.", "hexString", ex);
}
// Convert.ToChar() will throw an ArgumentException also
// if hexString is bad
}
答案 3 :(得分:0)
我的猜测是.NET中的Char实际上是两个字节(16位),因为它们是UTF-16编码的。也许你只是捕获/写入值的第一个字节?
基本上,您是否正在使用char值进行某些操作,假设它是8位而不是16位,因此会截断它?
答案 4 :(得分:0)
当使用“windows-1252”扩展ASCII拉丁语编码实际存储RTF文件时,读取RTF文件(UTF-8)时可能正在使用默认字符编码。
C#字符串使用16个unicode位宽字符格式。将windows-1252字符0x85转换为其unicode等效项涉及复杂的映射,因为代码点(字符编号)非常不同。幸运的是,Windows可以为您完成工作。
通过在打开流时明确指定源编码,您可以更改在文本中阅读时转换字符的方式。
using System.IO;
using System.Text.Encoding;
using (TextReader tr = new StreamReader(path_to_RTF_file, Encoding.GetEncoding(1252)))
{
// Read from the file as usual.
}
答案 5 :(得分:0)
以下是一些适合您的粗略代码:
// Convert hex number, which represents an RTF code-page escaped character,
// to the desired character (uses '85' from your example as a literal):
var number = int.Parse("85", System.Globalization.NumberStyles.HexNumber);
Debug.Assert(number <= byte.MaxValue);
byte[] bytes = new byte[1] { (byte)number };
char[] chars = Encoding.GetEncoding(1252).GetString(bytes).ToCharArray();
// or, use:
// char[] chars = Encoding.Default.GetString(bytes).ToCharArray();
string result = new string(chars);
答案 6 :(得分:0)
只需使用我在Chris网站上修改过的功能(非常轻微):
private static string charScrubber(string content)
{
StringBuilder sbTemp = new StringBuilder(content.Length);
foreach (char currentChar in content)
{
if ((currentChar != 127 && currentChar > 1))
{
sbTemp.Append(currentChar);
}
}
content = sbTemp.ToString();
return content;
}
您可以修改“当前Char”条件以删除需要删除的任何字符(如此处显示,您将不会获得任何0x00字符,或者(char)127或0x57字符。)
ASCII / Hex表格:http://www.cs.mun.ca/~michael/c/ascii-table.html
Chris'网站:http://seattlesoftware.wordpress.com/2008/09/11/hexadecimal-value-0-is-an-invalid-character/
- 汤姆