Frage

Gibt es eine vorhandene Klasse in C #, die Quoted-Printable Codierung umwandeln kann String ? Klicken Sie auf den Link oben, um mehr Informationen über die Codierung zu erhalten.

Das folgende ist aus dem obigen Link für Ihre Bequemlichkeit angegeben.

  

Jede 8-Bit-Byte-Wert codiert werden   mit 3 Zeichen ein „=“, gefolgt von   zwei Hexadezimalziffern (0-9 oder A-F)   repräsentiert den numerischen Wert des Byte.   Zum Beispiel kann ein Feed US-ASCII-Form   Zeichen (Dezimalwert 12) sein kann,   durch "= 0C" repräsentiert, und einem US-ASCII   Gleichheitszeichen (Dezimalwert 61)   durch "= 3D" dargestellt. Alle Zeichen   außer druckbaren ASCII-Zeichen oder   Zeilenende-Zeichen muß codiert werden,   auf diese Weise.

     

Alle druckbaren ASCII-Zeichen   (Dezimalwerte zwischen 33 und 126)   kann selbst dargestellt werden,   Ausnahme "=" (dezimal 61).

     

ASCII Tabulatoren und Leerzeichen,   Dezimalwerten 9 und 32, kann sein   selbst vertreten, es sei denn,   diese Zeichen erscheinen am Ende   eine Linie. Wenn eines dieser Zeichen   erscheint am Ende einer Zeile für muss   codiert werden als "= 09" (TAB) oder "= 20"   (Raum).

     

Wenn die Daten codiert werden, enthält   sinnvolle Zeilenumbrüche müssen sie sein   codiert als ASCII-CR LF-Sequenz,   nicht als ihre ursprünglichen Byte-Werte.   Umgekehrt, wenn Byte-Werte 13 und 10   haben andere Bedeutungen als Zeilenende   dann müssen sie als = 0D codiert werden und   = 0A.

     

Die Linien von quoted-printable kodierten Daten   darf nicht als 76 Zeichen lang sein.   Zur Erfüllung dieser Anforderung ohne   Ändern der codierten Text, weiche Linie   Brüche können wie gewünscht zugegeben werden. Ein weiches   Leitungsbruch besteht aus einem „=“ in der   Das Ende einer Leitung codierten und nicht   veranlassen, einen Zeilenumbruch in dem decodierten   Text.

War es hilfreich?

Lösung

Es gibt Funktionen in dem Rahmen Bibliotheken, dies zu tun, aber es scheint nicht sauber ausgesetzt werden. Die Umsetzung ist in der internen Klasse System.Net.Mime.QuotedPrintableStream. Diese Klasse definiert eine Methode namens DecodeBytes die das tut, was Sie wollen. Das Verfahren wird durch nur ein Verfahren verwendet werden, das verwendet wird, MIME-Header zu dekodieren. Dieses Verfahren ist auch intern, ist aber ziemlich direkt in ein paar Orten, zum Beispiel genannt, der Attachment.Name Setter. Eine Demonstration:

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

Erzeugt die Ausgabe:

  

¡Hola, _señor!

Sie haben einige Tests zu tun Wagenrücklauf zu gewährleisten, wird usw. behandelt korrekt, obwohl in einem Schnelltest Ich habe sie zu sein scheint. Es kann aber nicht klug sein, auf diese Funktion verlassen, es sei denn, Ihr Anwendungsfall nahe genug, um die Decodierung eines MIME-Header-Zeichenfolge, die Sie nicht denken, wird es durch Änderungen an der Bibliothek gemacht gebrochen werden. Vielleicht haben Sie besser Ihre eigenen quoted-printable Decoder zu schreiben.

Andere Tipps

I erweitert die Lösung von Martin Murphy und ich hoffe, dass es in jedem Fall funktionieren wird.

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

Ich schrieb diese bis ganz schnell.

    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", "");
    }       

Wenn Sie Decodierung quoted-printable mit UTF-8-Codierung Sie sich bewusst sein müssen, dass Sie nicht jede quoted-printable Sequenz dekodieren kann man-at-a-time als die anderen haben gezeigt, wenn es läuft von quoted-printable Zeichen zusammen.

Zum Beispiel - wenn Sie die folgende Sequenz = E2 = 80 = 99 und dekodieren diese unter Verwendung von UTF8 one-at-a-time Sie drei „weird“ Zeichen bekommen - wenn Sie stattdessen eine Reihe von drei Bytes bauen und wandeln die drei Bytes mit der UTF8-Codierung Sie eine einzelne aphostrope erhalten.

Natürlich, wenn Sie ASCII-Codierung verwenden, dann einer-at-a-time ist jedoch kein Problem, läuft Decodierung bedeutet, dass Ihr Code unabhängig von dem Text-Encoder verwendet, funktionieren wird.

Oh, und vergessen Sie nicht, = 3D ist ein Sonderfall, der bedeutet, dass Sie entschlüsseln müssen, was Sie haben ein weiteres Mal ... Das ist eine verrückte Gotcha!

Ich hoffe, das hilft

Dieses Zitat Druck Decoder funktioniert super!

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();
    }
    private string quotedprintable(string data, string encoding)
    {
        data = data.Replace("=\r\n", "");
        for (int position = -1; (position = data.IndexOf("=", position + 1)) != -1;)
        {
            string leftpart = data.Substring(0, position);
            System.Collections.ArrayList hex = new System.Collections.ArrayList();
            hex.Add(data.Substring(1 + position, 2));
            while (position + 3 < data.Length && data.Substring(position + 3, 1) == "=")
            {
                position = position + 3;
                hex.Add(data.Substring(1 + position, 2));
            }
            byte[] bytes = new byte[hex.Count];
            for (int i = 0; i < hex.Count; i++)
            {
                bytes[i] = System.Convert.ToByte(new string(((string)hex[i]).ToCharArray()), 16);
            }
            string equivalent = System.Text.Encoding.GetEncoding(encoding).GetString(bytes);
            string rightpart = data.Substring(position + 3);
            data = leftpart + equivalent + rightpart;
        }
        return data;
    }

Ich war auf der Suche nach einer dynamischen Lösung und verbrachten 2 Tage verschiedene Lösungen versucht. Diese Lösung wird japanische Schriftzeichen und andere Standard-Zeichensätze

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

    }

Dann können Sie die Funktion aufrufen mit

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

Dies war ursprünglich gefunden hier

Die einzige, die für mich gearbeitet.

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

Wenn Sie nur die QPs entschlüsseln müssen, ziehen Sie innerhalb des Codes dieser drei Funktionen aus dem obigen Link:

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

Und dann nur:

var humanReadable = Decode(myQPString);

Genießen

Bessere Lösung

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

Manchmal ist die Zeichenfolge in eine EML-Datei wird von mehreren codierten Teilen zusammengesetzt. Dies ist eine Funktion des Dave-Methode für diese Fälle zu verwenden:

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

Bitte beachten Sie: Lösungen mit „input.Replace“ sind alle über das Internet und sie sind immer noch nicht korrekt.

Sehen Sie, wenn Sie auf ONE decodierte Symbol und verwenden dann "ersetzen" , Alle Symbole in „Eingang“ ersetzt werden, und dann werden alle folgenden Decodierung gebrochen wird.

Weitere richtige Lösung:

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;
    }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top