公  告
 
  站点日历
 
  日志分类
 
  最新日志
 
  最新评论
 
  最新留言
 
  用户登陆
 
  日志搜索
 
  统计信息
 

  友情连接
 
  VB QP编码
[ 2008-4-1 14:01:39 | By: myfamily ]
 
 

'转载http://cyinger-smiling.blogbus.com/logs/5672032.html

Private Function QpDecode(inString As String) As String  

  Dim myB     As Byte
  Dim myByte1     As Byte, myByte2       As Byte
  Dim convStr()     As Byte
  Dim mOutByte     As Byte
  Dim FinishPercent     As Long
  Dim TotalB, k       As Long
  Dim tmpByte     As Byte
   
  convStr = StrConv(inString, vbFromUnicode)
   
  TotalB = UBound(convStr)
  For k = 0 To TotalB
        myB = convStr(k)
        If myB = Asc("=") Then
              k = k + 1
              myByte1 = convStr(k)
              If myByte1 = &HA Then
                          '如果是回车,继续
              Else
                          '取第二个字节
                    k = k + 1
                    myByte2 = convStr(k)
                    Call DecodeByte(myByte1, myByte2, mOutByte)
                    If mOutByte >= 127 Then
                          If tmpByte <> 0 Then
                                QpDecode = QpDecode & Chr(Val("&H" & Hex(tmpByte) & Hex(mOutByte)))
                                tmpByte = 0
                          Else
                                tmpByte = mOutByte
                          End If
                    Else
                          QpDecode = QpDecode & Chr(mOutByte)
                          tmpByte = 0
                    End If
              End If
          Else
                  mOutByte = myB
                  QpDecode = QpDecode & Chr(mOutByte)
          End If
  Next
  End Function
  Private Sub DecodeByte(mInByte1 As Byte, mInByte2 As Byte, mOutByte As Byte)
  Dim tbyte1     As Integer, tbyte2       As Integer
  If mInByte1 > Asc("9") Then
          tbyte1 = mInByte1 - Asc("A") + 10
  Else
          tbyte1 = mInByte1 - Asc("0")
  End If
  If mInByte2 > Asc("9") Then
          tbyte2 = mInByte2 - Asc("A") + 10
  Else
          tbyte2 = mInByte2 - Asc("0")
  End If
  mOutByte = tbyte1 * 16 + tbyte2
  End Sub
   
  Private Sub EncodeByte(mInByte As Byte, mOutStr As String)
  If (mInByte >= 33 And mInByte <= 60) Or (mInByte >= 62 And mInByte <= 126) Then
          mOutStr = Chr(mInByte)
  Else
          If mInByte <= &HF Then
                  mOutStr = "=0" & Hex(mInByte)
          Else
                  mOutStr = "=" & Hex(mInByte)
          End If
  End If
End Sub

     QP编码的规则是,对于信息中的7位字符不作重新编码,而是仅将8位的数据转成7位即可。我们可以看到,QP编码是字符对应的编码,每个未编码的二进制字符都会被编码成3个字符,即一个等号加上两个该字符的16进制值,如“=A8”,但这样的编码数为1:3,所以编码效率相对于其它编码方式而言相当低。但不可否认的是,这种编码方法非常简单,特别适合那些数据大多数是7位的ASCII码文本、偶尔插入8位字符的情况,但遗憾的是对汉字编码效果不够好,因为每个双字节汉字经过编码后会变成6个字节。具体规则如下:

    将一个字元用两个十六进制数表示,然后前面再加上一个「=」(等号)字元;除非这个字元符合下面其他的规则。比如原先 ASCII 的「=」(等号)字元,其十进制数值是 61,十六进制数值为 3D,所以经过 QP 编码后,变成了「=3D」。

    字元的数值(十进制数)介于 33 60、及 62 126 者不必经过编码。(61 是「等号」)

    字元 TAB SPACE 可以不经编码,但是不经编码的 TAB SPACE 不可以放在编码后每行字串的末尾;也就是說编码后的內容,一行字串中如果有 TAB SPACE 的話,其后面一定还有其它的字元。

QP解码只是编码的逆过程,计算出每个等号后的两个十六进制字符所代表的数值进行解码,对于码值小于128的,单字节表示一个字符;大于128的,双字节表示一个字符。下面举例分析。例如:编码后的字符串为=C4=E3=BA=C3,解码后对应字符串为“你好”。3.3.3-2: QP解码示例

十六进制值

= C 4 = E 3 = B A = C 3
解码(十进制值) 196 227 186 195
解码(二进制值) 11000100 11100011 10111010 11000011
原字符

 

  以上两个函数分析如下:

  DecodeByte()函数是私有函数,对QP编码后的每组(以等号分割的每两个字节一组)信息进行QP解码,即计算这两个十六进制字符所代表的数值。当ASCII码小于“9”的ASCII码时,则减去“0”的ASCII码值(这是因为,当字符小于9时为了使编码位数一致,除在其前加“=”外还加了“0”);如果大于则减去“A”的ASCII码值再加10,即得到此位对应的十进制值,如“B”对应十进制值11。然后通过高字节*16+低字节得到解码数值。

  QpDecode()函数是私有函数,先用StrConv函数将QP编码后的字符串信息由Unicode转成系统的缺省码,然后将其分组(以等号分割,每两个字节一组)后调用DecodeByte()函数进行QP解码。第一个等号前及最后一个等号后三位起的字符不作QP解码(直接是ASCII编码)。对于DecodeByte()返回值小于128的(单字节字符)单字节表示一个字符,大于128(双字节字符)的两个字节表示一个字符。

 

上面的解码是有问题的,对于一个扩展ASCII码,其值是大于127的,但它不是双字节,依然是一个字节,上面的解码函数不够全面!
 

发表评论:

    昵称:
    密码: (游客无须输入密码)
    主页:
    标题:
 
 
 
Powered by Oblog.