none
QuotedPrintable解碼的問題 RRS feed

  • 問題

  • 我到網路上找了一個QP解碼的方法,試著解=BB=A8=C1=DA=A9b=B9=A3這一句文字,但解出來是下列»¨ÁÚ©b¹£的文字
    我找到一個網站(http://203.75.148.3/qp2big5.html)可以正確的解出中文字,不知道我下面這一個程式到底問題出在哪,請高手幫我解答一下。
           
    Code Snippet

    public static string Decode(string _ToDecode)
            {
                StringBuilder Decoded = new StringBuilder();

                //remove soft-linebreaks first
                _ToDecode = _ToDecode.Replace("=\r\n", "");

                char[] chars = _ToDecode.ToCharArray();

                for (int i = 0; i < chars.Length; i++)
                {
                    // if encoded character found decode it
                    if (chars[i] == '=')
                    {
                        Decoded.Append(System.Convert.ToChar(int.Parse(chars[i + 1].ToString() + chars[i + 2].ToString(), System.Globalization.NumberStyles.HexNumber)));
                        //jump ahead
                        i += 2;
                    }
                    else
                    {
                        Decoded.Append(System.Convert.ToChar(chars[i]));
                    }
                }

                return Decoded.ToString();
            }



    2008年2月13日 上午 06:49

解答

所有回覆

  • 我又找到另一個方法,這個方法功成的解出兩個中文字,結果為 豪邁?9=A3 ,提供大家參考

    Code Snippet

    public static string ConvertFromQPString(string quoted_printableString)
            {
                string InputString = quoted_printableString;
                StringBuilder builder1 = new StringBuilder();
                InputString = InputString.Replace("=\r\n", "");
                for (int num1 = 0; num1 < InputString.Length; num1++)
                {
                    if (InputString[num1] == '=')
                    {
                        try
                        {
                            if (HexToDec(InputString.Substring(num1 + 1, 2)) < 0x80)
                            {
                                if (HexToDec(InputString.Substring(num1 + 1, 2)) >= 0)
                                {
                                    byte[] buffer1 = new byte[1] { (byte)HexToDec(InputString.Substring(num1 + 1, 2)) };
                                    builder1.Append(Encoding.Default.GetString(buffer1));
                                    num1 += 2;
                                }
                            }
                            else if (InputString[num1 + 1] != '=')
                            {
                                byte[] buffer2 = new byte[2] { (byte)HexToDec(InputString.Substring(num1 + 1, 2)), (byte)HexToDec(InputString.Substring(num1 + 4, 2)) };
                                builder1.Append(Encoding.Default.GetString(buffer2));
                                num1 += 5;
                            }
                        }
                        catch
                        {
                            builder1.Append(InputString.Substring(num1, 1));
                        }
                    }
                    else
                    {
                        builder1.Append(InputString.Substring(num1, 1));
                    }
                }
                return builder1.ToString();
            }
            private static int HexToDec(string hex)
            {
                int num1 = 0;
                string text1 = "0123456789ABCDEF";
                for (int num2 = 0; num2 < hex.Length; num2++)
                {
                    if (text1.IndexOf(hex[num2]) == -1)
                    {
                        return -1;
                    }
                    num1 = (num1 * 0x10) + text1.IndexOf(hex[num2]);
                }
                return num1;
            }

     

     

    2008年2月13日 上午 07:01
  • 我了解了編碼如果「要」這個中文字要編成QP碼Encode時會先將要拆成兩個byte{173,110}Encoding時,會編成=ADn,樓上的程式只能解=BB=A8這種中文字,兩個byte都大於127的文字,因此我小改了一下解碼的程式,讓他可以判讀=ADn的編碼。
    Code Snippet

    public static string ConvertFromQPString(string quoted_printableString)
            {
                string InputString = quoted_printableString;
                StringBuilder builder1 = new StringBuilder();
                InputString = InputString.Replace("=\r\n", "");
                for (int num1 = 0; num1 < InputString.Length; num1++)
                {
                    if (InputString[num1] == '=')
                    {
                        try
                        {
                            if (HexToDec(InputString.Substring(num1 + 1, 2)) < 0x80)
                            {
                                if (HexToDec(InputString.Substring(num1 + 1, 2)) >= 0)
                                {
                                    byte[] buffer1 = new byte[1] { (byte)HexToDec(InputString.Substring(num1 + 1, 2)) };
                                    builder1.Append(Encoding.Default.GetString(buffer1));
                                    num1 += 2;
                                }
                            }
                            else if (InputString[num1 + 1] != '=')
                            {
                                byte first = (byte)HexToDec(InputString.Substring(num1 + 1, 2));
                                byte second = 0;
                                // 兩組正常的編碼=AD=A9
                                if (InputString.Substring(num1 + 3, 1).Equals("="))
                                {
                                    second = (byte)HexToDec(InputString.Substring(num1 + 4, 2));
                                    num1 += 5;
                                }
                                else// 一組正常的編碼加小於127的代碼=ADn
                                {
                                    char[] split = InputString.ToCharArray();
                                    second = System.Convert.ToByte(split[num1 + 3]);
                                    num1 += 3;
                                }
                                byte[] buffer2 = new byte[2] { first, second };
                                builder1.Append(Encoding.Default.GetString(buffer2));
                                
                            }
                        }
                        catch
                        {
                            builder1.Append(InputString.Substring(num1, 1));
                        }
                    }
                    else
                    {
                        builder1.Append(InputString.Substring(num1, 1));
                    }
                }
                return builder1.ToString();
            }

    2008年2月13日 上午 08:07
  • 試試看吧! 我改過的 Code:

     

    Code Snippet


        public static string Decode(string _ToDecode)
        {

            //remove soft-linebreaks first
            _ToDecode = _ToDecode.Replace("=\r\n", "");

            char[] chars = _ToDecode.ToCharArray();

            byte[] DecodedBytes = new byte[chars.Length];
           
            int bytesCount = 0;

            for (int i = 0; i < chars.Length; i++)
            {
                // if encoded character found decode it
                if (chars[i] == '=')
                {
                    DecodedBytes[bytesCount++] = System.Convert.ToByte(int.Parse(chars[i + 1].ToString() + chars[i + 2].ToString(), System.Globalization.NumberStyles.HexNumber));
                   
                    i += 2;
                }
                else
                {
                    DecodedBytes[bytesCount++] = System.Convert.ToByte(chars[i]);
                }
            }

            return System.Text.Encoding.Default.GetString(DecodedBytes, 0, bytesCount);
        }

     

     

    用 QuotedPrintable 其實很不安全,因為除非你知道你編碼的時候用的是什麼編碼(Encoding)否則很容易在 Decode 的時候出現亂碼!

     

    像我們用的是「繁體中文」的作業系統,其 System.Text.Encoding.Default 就是 BIG5,但如果你做 Encode 的時候的編碼跟 Decode 時候的編碼不一致時,那就會解碼失敗了。

     

    ----
    From: Will
    Blog: http://blog.miniasp.com/
    記載著 Will 在網路世界的學習心得與技術分享

    2008年2月13日 下午 12:07