如何获取代表上位ascii值字符的十六进制值的字符串类型

时间:2020-03-06 14:27:58  来源:igfitidea点击:

我们的应用程序的一部分会解析RTF文档,我们遇到了一个翻译不好的特殊字符。在Word中查看时,该字符是一个省略号(...),并且在RTF中被编码为('85)。

在我们的vb代码中,我们将十六进制(85)转换为int(133),然后执行Chr(133)返回(...)

这是Cproblem中的代码,它不适用于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;
}

解决方案

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
}

我的猜测是,.NET中的Char实际上是两个字节(16位),因为它们是UTF-16编码的。也许我们只是捕获/写入值的第一个字节?

基本上,我们之后是否使用char值做一些事情,假设它是8位而不是16,因此将其截断?

当实际使用" windows-1252"扩展ASCII拉丁语编码存储RTF文件时,我们可能会在读取RTF文件(即UTF-8)时使用默认字符编码。

Cstring使用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.
}

原始代码对我来说非常好。能够将十六进制从00到FF转换为适当的字符。使用vs2008.

在我看来,这似乎是字符编码问题。 Unicode不包括数字在ASCII高128-255范围内的任何字符,因此尝试转换字符133将失败。

需要首先使用正确的解码将其转换为字符,Convert.toChar似乎使用的是UTF-16.

有时有一个手动的位操纵技巧可以将字符从高位ASCII转换为适当的Unicode字符,但是由于省略号在大多数广泛使用的扩展ASCII码页中并不存在,因此在这里不太可能使用。

我们真正想做的是使用具有正确编码的Encoding.GetString(Byte [])方法。将值放入字节数组,然后将GetString放入字符的Cnative字符串。

我们可以在RTF Wikipedia页面上了解有关RTF字符编码的更多信息。

仅供参考:水平省略号是字符U + 2026(pdf)。

以下是一些适合粗略代码:

// 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);

只需使用我从克里斯的网站(非常轻微)修改的此功能即可:

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;
    }

我们可以修改"当前字符"条件以删除需要消除的任何字符(如此处所示,我们将不会获得任何0x00字符,(char)127或者0x57字符)。

此处的ASCII /十六进制表: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/

汤姆