C#: Класс для Заключенного в кавычки декодирования - Печатаемое кодирование?

RScript имеет эту «прекрасную» функцию, не загружая для вас (базовый пакет) методы.

Итак, все, что вам нужно, это дополнительный

  require(methods)

или

  suppressMessages(library(methods))

Для чего стоит littler командной строки и скриптовый интерфейс для R, который Джефф Хорнер и я написали по умолчанию для методов загрузки для вас ...

26
задан Lopper 8 February 2010 в 17:54
поделиться

11 ответов

В библиотеках фреймворка есть функциональные возможности для этого, но, похоже, они не полностью раскрыты. Реализация находится во внутреннем классе System.Net.Mime.QuotedPrintableStream. Этот класс определяет метод с именем DecodeBytes, который делает то, что вы хотите. По-видимому, этот метод используется только одним методом, который используется для декодирования заголовков MIME. Этот метод также является внутренним, но вызывается довольно напрямую в нескольких местах, например, в установщике Attachment.Name. Демонстрация:

using System;
using System.Net.Mail;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Attachment attachment = Attachment.CreateAttachmentFromString("", "=?iso-8859-1?Q?=A1Hola,_se=F1or!?=");
            Console.WriteLine(attachment.Name);
        }
    }
}

Производит вывод:

¡Привет, _señor!

Возможно, вам придется провести некоторое тестирование, чтобы убедиться, что возврат каретки и т. д. обрабатываются правильно, хотя в быстром тесте я так и сделал Однако, возможно, не стоит полагаться на эту функциональность, если ваш вариант использования не достаточно близок к декодированию строки заголовка MIME, и вы не думаете, что она будет нарушена при любых изменениях, внесенных в библиотеку. Возможно, вам лучше написать собственный цитируемый для печати декодер.

19
ответ дан Dave 14 October 2019 в 21:49
поделиться

Обратите внимание: решения с «input.Replace» распространены по всему Интернету, и все же они не верны.

Смотрите, если у вас есть ОДИН декодированный символ и затем используется «заменить» , ВСЕ символов во «входе» будут заменены, и тогда все последующее декодирование будет прервано.

Более правильное решение:

public static string DecodeQuotedPrintable(string input, string charSet)
    {

        Encoding enc;

        try
        {
            enc = Encoding.GetEncoding(charSet);
        }
        catch
        {
            enc = new UTF8Encoding();
        }

        input = input.Replace("=\r\n=", "=");
        input = input.Replace("=\r\n ", "\r\n ");
        input = input.Replace("= \r\n", " \r\n");
        var occurences = new Regex(@"(=[0-9A-Z]{2})", RegexOptions.Multiline); //{1,}
        var matches = occurences.Matches(input);

        foreach (Match match in matches)
        {
            try
            {
                byte[] b = new byte[match.Groups[0].Value.Length / 3];
                for (int i = 0; i < match.Groups[0].Value.Length / 3; i++)
                {
                    b[i] = byte.Parse(match.Groups[0].Value.Substring(i * 3 + 1, 2), System.Globalization.NumberStyles.AllowHexSpecifier);
                }
                char[] hexChar = enc.GetChars(b);
                input = input.Replace(match.Groups[0].Value, new String(hexChar));

            }
            catch
            { Console.WriteLine("QP dec err"); }
        }
        input = input.Replace("?=", ""); //.Replace("\r\n", "");

        return input;
    }
0
ответ дан Don Joe 14 October 2019 в 21:49
поделиться

Иногда строка в EML-файл состоит из нескольких закодированных частей. Это функция для использования метода Дейва в следующих случаях:

public string DecodeQP(string codedstring)
{
    Regex codified;

    codified=new Regex(@"=\?((?!\?=).)*\?=", RegexOptions.IgnoreCase);
    MatchCollection setMatches = codified.Matches(cadena);
    if(setMatches.Count > 0)
    {
        Attachment attdecode;
        codedstring= "";
        foreach (Match match in setMatches)
        {
            attdecode = Attachment.CreateAttachmentFromString("", match.Value);
            codedstring+= attdecode.Name;

        }                
    }
    return codedstring;
}
0
ответ дан Armando Saenz 14 October 2019 в 21:49
поделиться
public static string DecodeQuotedPrintables(string input, Encoding encoding)
    {
        var regex = new Regex(@"\=(?<Symbol>[0-9A-Z]{2})", RegexOptions.Multiline);
        var matches = regex.Matches(input);
        var bytes = new byte[matches.Count];

        for (var i = 0; i < matches.Count; i++)
        {
            bytes[i] = Convert.ToByte(matches[i].Groups["Symbol"].Value, 16);
        }

        return encoding.GetString(bytes);
    }
0
ответ дан Kachalov Sergey 14 October 2019 в 21:49
поделиться

Единственный, который работал на меня.

http://sourceforge.net/apps/trac/syncmldotnet/wiki/Quoted%20Printable

Если вам просто нужно декодировать QP, потяните в свой код эти три функции по ссылке выше:

    HexDecoderEvaluator(Match m)
    HexDecoder(string line)
    Decode(string encodedText)

А потом просто:

var humanReadable = Decode(myQPString);

Наслаждайтесь

1
ответ дан Pizzaboy 14 October 2019 в 21:49
поделиться

Я искал динамическое решение и потратил 2 дня, пытаясь найти разные решения. Это решение будет поддерживать японские символы и другие стандартные наборы символов

private static string Decode(string input, string bodycharset) {
        var i = 0;
        var output = new List<byte>();
        while (i < input.Length) {
            if (input[i] == '=' && input[i + 1] == '\r' && input[i + 2] == '\n') {
                //Skip
                i += 3;
            } else if (input[i] == '=') {
                string sHex = input;
                sHex = sHex.Substring(i + 1, 2);
                int hex = Convert.ToInt32(sHex, 16);
                byte b = Convert.ToByte(hex);
                output.Add(b);
                i += 3;
            } else {
                output.Add((byte)input[i]);
                i++;
            }
        }


        if (String.IsNullOrEmpty(bodycharset))
            return Encoding.UTF8.GetString(output.ToArray());
        else {
            if (String.Compare(bodycharset, "ISO-2022-JP", true) == 0)
                return Encoding.GetEncoding("Shift_JIS").GetString(output.ToArray());
            else
                return Encoding.GetEncoding(bodycharset).GetString(output.ToArray());
        }

    }

. Затем вы можете вызвать функцию с помощью

Decode("=E3=82=AB=E3=82=B9=E3", "utf-8")

. Первоначально было найдено здесь

2
ответ дан Lee Harris 14 October 2019 в 21:49
поделиться

Лучшее решение

    private static string DecodeQuotedPrintables(string input, string charSet)
    {
        try
        {
            enc = Encoding.GetEncoding(CharSet);
        }
        catch
        {
            enc = new UTF8Encoding();
        }

        var occurences = new Regex(@"(=[0-9A-Z]{2}){1,}", RegexOptions.Multiline);
        var matches = occurences.Matches(input);

    foreach (Match match in matches)
    {
            try
            {
                byte[] b = new byte[match.Groups[0].Value.Length / 3];
                for (int i = 0; i < match.Groups[0].Value.Length / 3; i++)
                {
                    b[i] = byte.Parse(match.Groups[0].Value.Substring(i * 3 + 1, 2), System.Globalization.NumberStyles.AllowHexSpecifier);
                }
                char[] hexChar = enc.GetChars(b);
                input = input.Replace(match.Groups[0].Value, hexChar[0].ToString());
        }
            catch
            { ;}
        }
        input = input.Replace("=\r\n", "").Replace("=\n", "").Replace("?=", "");

        return input;
}
1
ответ дан Community 14 October 2019 в 21:49
поделиться

Этот цитируемый печатный декодер прекрасно работает!

public static byte[] FromHex(byte[] hexData)
    {
        if (hexData == null)
        {
            throw new ArgumentNullException("hexData");
        }

        if (hexData.Length < 2 || (hexData.Length / (double)2 != Math.Floor(hexData.Length / (double)2)))
        {
            throw new Exception("Illegal hex data, hex data must be in two bytes pairs, for example: 0F,FF,A3,... .");
        }

        MemoryStream retVal = new MemoryStream(hexData.Length / 2);
        // Loop hex value pairs
        for (int i = 0; i < hexData.Length; i += 2)
        {
            byte[] hexPairInDecimal = new byte[2];
            // We need to convert hex char to decimal number, for example F = 15
            for (int h = 0; h < 2; h++)
            {
                if (((char)hexData[i + h]) == '0')
                {
                    hexPairInDecimal[h] = 0;
                }
                else if (((char)hexData[i + h]) == '1')
                {
                    hexPairInDecimal[h] = 1;
                }
                else if (((char)hexData[i + h]) == '2')
                {
                    hexPairInDecimal[h] = 2;
                }
                else if (((char)hexData[i + h]) == '3')
                {
                    hexPairInDecimal[h] = 3;
                }
                else if (((char)hexData[i + h]) == '4')
                {
                    hexPairInDecimal[h] = 4;
                }
                else if (((char)hexData[i + h]) == '5')
                {
                    hexPairInDecimal[h] = 5;
                }
                else if (((char)hexData[i + h]) == '6')
                {
                    hexPairInDecimal[h] = 6;
                }
                else if (((char)hexData[i + h]) == '7')
                {
                    hexPairInDecimal[h] = 7;
                }
                else if (((char)hexData[i + h]) == '8')
                {
                    hexPairInDecimal[h] = 8;
                }
                else if (((char)hexData[i + h]) == '9')
                {
                    hexPairInDecimal[h] = 9;
                }
                else if (((char)hexData[i + h]) == 'A' || ((char)hexData[i + h]) == 'a')
                {
                    hexPairInDecimal[h] = 10;
                }
                else if (((char)hexData[i + h]) == 'B' || ((char)hexData[i + h]) == 'b')
                {
                    hexPairInDecimal[h] = 11;
                }
                else if (((char)hexData[i + h]) == 'C' || ((char)hexData[i + h]) == 'c')
                {
                    hexPairInDecimal[h] = 12;
                }
                else if (((char)hexData[i + h]) == 'D' || ((char)hexData[i + h]) == 'd')
                {
                    hexPairInDecimal[h] = 13;
                }
                else if (((char)hexData[i + h]) == 'E' || ((char)hexData[i + h]) == 'e')
                {
                    hexPairInDecimal[h] = 14;
                }
                else if (((char)hexData[i + h]) == 'F' || ((char)hexData[i + h]) == 'f')
                {
                    hexPairInDecimal[h] = 15;
                }
            }

            // Join hex 4 bit(left hex cahr) + 4bit(right hex char) in bytes 8 it
            retVal.WriteByte((byte)((hexPairInDecimal[0] << 4) | hexPairInDecimal[1]));
        }

        return retVal.ToArray();
    }
    public static byte[] QuotedPrintableDecode(byte[] data)
    {
        if (data == null)
        {
            throw new ArgumentNullException("data");
        }

        MemoryStream msRetVal = new MemoryStream();
        MemoryStream msSourceStream = new MemoryStream(data);

        int b = msSourceStream.ReadByte();
        while (b > -1)
        {
            // Encoded 8-bit byte(=XX) or soft line break(=CRLF)
            if (b == '=')
            {
                byte[] buffer = new byte[2];
                int nCount = msSourceStream.Read(buffer, 0, 2);
                if (nCount == 2)
                {
                    // Soft line break, line splitted, just skip CRLF
                    if (buffer[0] == '\r' && buffer[1] == '\n')
                    {
                    }
                    // This must be encoded 8-bit byte
                    else
                    {
                        try
                        {
                            msRetVal.Write(FromHex(buffer), 0, 1);
                        }
                        catch
                        {
                            // Illegal value after =, just leave it as is
                            msRetVal.WriteByte((byte)'=');
                            msRetVal.Write(buffer, 0, 2);
                        }
                    }
                }
                // Illegal =, just leave as it is
                else
                {
                    msRetVal.Write(buffer, 0, nCount);
                }
            }
            // Just write back all other bytes
            else
            {
                msRetVal.WriteByte((byte)b);
            }

            // Read next byte
            b = msSourceStream.ReadByte();
        }

        return msRetVal.ToArray();
    }
2
ответ дан Gonzalo Gallotti 14 October 2019 в 21:49
поделиться

Если вы декодируете печатаемую в кавычки с помощью кодировки UTF-8, вам нужно знать, что вы не можете декодировать каждую печатаемую в кавычки последовательность по одному, как другие показали, если есть серии печатных символов в кавычках вместе.

Например - если у вас есть следующая последовательность = E2 = 80 = 99 и декодируете ее, используя UTF8 по одному, вы получите три «странных» символа - если вместо этого вы создадите массив из трех байтов и преобразуете три байта с кодировкой UTF8 дают один апостроп.

Очевидно, что если вы используете кодировку ASCII, то поочередно проблем не возникает, однако выполнение декодирования означает, что ваш код будет работать независимо от используемого кодировщика текста.

Да, и не забывайте = 3D - это особый случай, который означает, что вам нужно декодировать все, что у вас есть еще раз ... Это сумасшедшая ошибка!

Надежда, которая помогает

5
ответ дан Demented Devil 14 October 2019 в 21:49
поделиться

Я написал это очень быстро.

    public static string DecodeQuotedPrintables(string input)
    {
        var occurences = new Regex(@"=[0-9A-H]{2}", RegexOptions.Multiline);
        var matches = occurences.Matches(input);
        var uniqueMatches = new HashSet<string>(matches);
        foreach (string match in uniqueMatches)
        {
            char hexChar= (char) Convert.ToInt32(match.Substring(1), 16);
            input =input.Replace(match, hexChar.ToString());
        }
        return input.Replace("=\r\n", "");
    }       
7
ответ дан Boluc Papuccuoglu 14 October 2019 в 21:49
поделиться

Я расширил решение Мартина Мерфи и надеюсь, что оно сработает в каждом случае.

private static string DecodeQuotedPrintables(string input, string charSet)
{           
    if (string.IsNullOrEmpty(charSet))
    {
        var charSetOccurences = new Regex(@"=\?.*\?Q\?", RegexOptions.IgnoreCase);
        var charSetMatches = charSetOccurences.Matches(input);
        foreach (Match match in charSetMatches)
        {
            charSet = match.Groups[0].Value.Replace("=?", "").Replace("?Q?", "");
            input = input.Replace(match.Groups[0].Value, "").Replace("?=", "");
        }
    }

    Encoding enc = new ASCIIEncoding();
    if (!string.IsNullOrEmpty(charSet))
    {
        try
        {
            enc = Encoding.GetEncoding(charSet);
        }
        catch
        {
            enc = new ASCIIEncoding();
        }
    }

    //decode iso-8859-[0-9]
    var occurences = new Regex(@"=[0-9A-Z]{2}", RegexOptions.Multiline);
    var matches = occurences.Matches(input);
    foreach (Match match in matches)
    {
        try
        {
            byte[] b = new byte[] { byte.Parse(match.Groups[0].Value.Substring(1), System.Globalization.NumberStyles.AllowHexSpecifier) };
            char[] hexChar = enc.GetChars(b);
            input = input.Replace(match.Groups[0].Value, hexChar[0].ToString());
        }
        catch { }
    }

    //decode base64String (utf-8?B?)
    occurences = new Regex(@"\?utf-8\?B\?.*\?", RegexOptions.IgnoreCase);
    matches = occurences.Matches(input);
    foreach (Match match in matches)
    {
        byte[] b = Convert.FromBase64String(match.Groups[0].Value.Replace("?utf-8?B?", "").Replace("?UTF-8?B?", "").Replace("?", ""));
        string temp = Encoding.UTF8.GetString(b);
        input = input.Replace(match.Groups[0].Value, temp);
    }

    input = input.Replace("=\r\n", "");
    return input;
}
17
ответ дан shA.t 14 October 2019 в 21:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: