Как получить строковый тип шестнадцатеричного значения, представляющего символ верхнего значения ascii - PullRequest
0 голосов
/ 20 сентября 2008

Часть нашего приложения анализирует документы RTF, и мы столкнулись со специальным символом, который плохо переводит. При просмотре в Word символом является elipsis (...), и он закодирован в 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;
}

Ответы [ 7 ]

2 голосов
/ 20 сентября 2008

Это похоже на проблему кодировки символов для меня. Unicode не содержит символов с номерами в верхнем диапазоне ASCII 128-255, поэтому попытка преобразовать символ 133. завершится неудачей.

Сначала необходимо преобразовать его в символ, используя правильное декодирование, Convert.toChar, похоже, использует UTF-16.

Иногда есть ручная манипуляция с битами для преобразования символа из верхнего ASCII в соответствующий символ Unicode, но поскольку многоточие отсутствует в большинстве широко используемых расширенных кодовых страниц ASCII, это вряд ли сработает здесь.

Что вы действительно хотите сделать, так это использовать метод Encoding.GetString (Byte []) с правильной кодировкой. Поместите ваше значение в байтовый массив, затем GetString, чтобы получить нативную строку C # для символа.

Подробнее о кодировках символов RTF вы можете узнать на странице RTF Wikipedia .

К вашему сведению: многоточие по горизонтали составляет символ U + 2026 (pdf) .

1 голос
/ 20 сентября 2008

Ваш оригинальный код прекрасно работает для меня. Он может конвертировать любой Hex от 00 до FF в соответствующий символ. Использование vs2008.

0 голосов
/ 17 января 2009

Просто используйте эту функцию, которую я изменил (очень немного) с сайта Криса:

    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 / Hex таблица здесь: http://www.cs.mun.ca/~michael/c/ascii-table.html

Сайт Криса: http://seattlesoftware.wordpress.com/2008/09/11/hexadecimal-value-0-is-an-invalid-character/

-Tom

0 голосов
/ 20 сентября 2008

Вот примерный код, который должен работать для вас:

// 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);
0 голосов
/ 20 сентября 2008

Вы, вероятно, используете кодировку символов по умолчанию при чтении в файле RTF, то есть UTF-8, когда файл RTF фактически сохраняется с использованием расширенной латинской кодировки ASCII "windows-1252".

В строках C # используется 16-битный формат широких символов. Перевод символа windows-1252 0x85 в его эквивалент юникода включает в себя сложное отображение, поскольку кодовые точки (номера символов) очень разные. К счастью, 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.
}
0 голосов
/ 20 сентября 2008

Я полагаю, что Char в .NET на самом деле составляет два байта (16 бит), так как они кодируются в UTF-16. Может быть, вы только перехватываете / записываете первый байт значения?

По существу, вы что-то делаете со значением char после этого, предполагая, что оно равно 8 битам вместо 16, и поэтому его усекает?

0 голосов
/ 20 сентября 2008
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
}
...