请教高手:UUencode/decode中文问题

sbknow 2005-03-18 10:05:06
我用下面函数来编码/解码邮件附件,为什么一遇到中文,文件就不能还原??????

Public Function UUEncodeFile(strFilePath As String) As String

Dim intFile As Integer 'file handler
Dim intTempFile As Integer 'temp file
Dim lFileSize As Long 'size of the file
Dim strFileName As String 'name of the file
Dim strFileData As String 'file data chunk
Dim lEncodedLines As Long 'number of encoded lines
Dim strTempLine As String 'temporary string
Dim i As Long 'loop counter
Dim j As Integer 'loop counter

Dim strResult As String
'
'Get file name
strFileName = Mid$(strFilePath, InStrRev(strFilePath, "\") + 1)
'
'Insert first marker: "begin 664 ..."
strResult = "begin 664 " + strFileName + vbCrLf
'
'Get file size
lFileSize = FileLen(strFilePath)
lEncodedLines = lFileSize \ 45 + 1
'
'Prepare buffer to retrieve data from
'the file by 45 symbols chunks
strFileData = Space(45)
'
intFile = FreeFile
'
Open strFilePath For Binary As intFile
For i = 1 To lEncodedLines
'Read file data by 45-bytes cnunks
'
If i = lEncodedLines Then
'Last line of encoded data often is not
'equal to 45, therefore we need to change
'size of the buffer
strFileData = Space(lFileSize Mod 45)
End If
'Retrieve data chunk from file to the buffer
Get intFile, , strFileData
'Add first symbol to encoded string that informs
'about quantity of symbols in encoded string.
'More often "M" symbol is used.
strTempLine = Chr(Len(strFileData) + 32)
'
If i = lEncodedLines And (Len(strFileData) Mod 3) Then
'If the last line is processed and length of
'source data is not a number divisible by 3, add one or two
'blankspace symbols
strFileData = strFileData + Space(3 - (Len(strFileData) Mod 3))
End If

For j = 1 To Len(strFileData) Step 3
'Breake each 3 (8-bits) bytes to 4 (6-bits) bytes
'
'1 byte
strTempLine = strTempLine + Chr(Asc(Mid(strFileData, j, 1)) \ 4 + 32)
'2 byte
strTempLine = strTempLine + Chr((Asc(Mid(strFileData, j, 1)) Mod 4) * 16 _
+ Asc(Mid(strFileData, j + 1, 1)) \ 16 + 32)
'3 byte
strTempLine = strTempLine + Chr((Asc(Mid(strFileData, j + 1, 1)) Mod 16) * 4 _
+ Asc(Mid(strFileData, j + 2, 1)) \ 64 + 32)
'4 byte
strTempLine = strTempLine + Chr(Asc(Mid(strFileData, j + 2, 1)) Mod 64 + 32)
Next j
'replace " " with "`"
strTempLine = Replace(strTempLine, " ", "`")
'add encoded line to result buffer
strResult = strResult + strTempLine + vbCrLf
'reset line buffer
strTempLine = ""
Next i
Close intFile

'add the end marker
strResult = strResult & "`" & vbCrLf + "end" + vbCrLf
'asign return value
UUEncodeFile = strResult

End Function



Public Function UUDecodeToFile(strUUCodeData As String, strFilePath As String)

Dim vDataLine As Variant
Dim vDataLines As Variant
Dim strDataLine As String
Dim intSymbols As Integer
Dim intFile As Integer
Dim strTemp As String
'
'remove begin marker
If Left$(strUUCodeData, 6) = "begin " Then
strUUCodeData = Mid$(strUUCodeData, InStr(1, strUUCodeData, vbLf) + 1)
End If
'
'remove end marker
If Right$(strUUCodeData, 5) = "end" + vbCrLf Then
strUUCodeData = Left$(strUUCodeData, Len(strUUCodeData) - 10)
End If

intFile = FreeFile
Open strFilePath For Binary As intFile
'Split encoded data to vDataLines array.
'Now each array member contains a line of encoded data
vDataLines = Split(strUUCodeData, vbCrLf)

For Each vDataLine In vDataLines
'Decode data line by line
'
strDataLine = CStr(vDataLine)
'Get quantity of symbols in a line
intSymbols = Asc(Left$(strDataLine, 1)) - 32
'remove first symbol that just informs
'about quantity of symbols
strDataLine = Mid$(strDataLine, 2)
'replace "`" with " "
strDataLine = Replace(strDataLine, "`", " ")
'Convert every 4-byte chunk to 3-byte chunk by
For i = 1 To Len(strDataLine) Step 4
'1 byte
strTemp = strTemp + Chr((Asc(Mid(strDataLine, i, 1)) - 32) * 4 + _
(Asc(Mid(strDataLine, i + 1, 1)) - 32) \ 16)
'2 byte
strTemp = strTemp + Chr((Asc(Mid(strDataLine, i + 1, 1)) Mod 16) * 16 + _
(Asc(Mid(strDataLine, i + 2, 1)) - 32) \ 4)
'3 byte
strTemp = strTemp + Chr((Asc(Mid(strDataLine, i + 2, 1)) Mod 4) * 64 + _
Asc(Mid(strDataLine, i + 3, 1)) - 32)
Next i
'
strTemp = Left(strTemp, intSymbols)
'write decoded line to the file
Put intFile, , strTemp
'clear buffer for next line
strTemp = ""
Next

Close intFile

End Function
原帖来自于网易社区:http://p5.club.163.com/viewArticleByWWW.m?boardId=vbnbasic&articleId=vbnbasic_102b0c440c25109
...全文
108 点赞 收藏 9
写回复
9 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
qiqi5521 2005-03-23
呵呵,不必客气。我们可以交个朋友吧。以前一直不知道UUEncode是做什么用的,后来查了一下,原来是在早期的纯文字的BBS上网友们交流二进制文件用的,看来这UUEncode还挺有用的,不说别的,在CSDN论坛上就有用武之地,省去了用邮箱交流的麻烦,编解码工具也很好找,WinZip 、中华压缩等都行。
回复
sbknow 2005-03-21
qiqi5521() 兄弟真了不起,几乎网上所有的UUCode 方面VB代码都没有考虑到这个问题,都是字符串做缓冲。太感谢了!!!如果我是美女一定以身相许了。
回复
qiqi5521 2005-03-19
刚才的代码有一个bug, 不能处理0字节文件,用下面的新的:
Option Explicit
Public Function UUEncodeFile(strFilePath As String) As String

Dim intFile As Integer 'file handler 文件号
Dim intTempFile As Integer 'temp file 临时文件的文件号
Dim lFileSize As Long 'size of the file 文件大小
Dim strFileName As String 'name of the file 文件名
Dim aFileData() As Byte 'file data chunk 文件数据块
Dim lEncodedLines As Long 'number of encoded lines 编码后的总行数
Dim strTempLine As String 'temporary string 临时字符串
Dim i As Long 'loop counter 循环变量
Dim j As Integer 'loop counter

Dim strResult As String '结果字符串


'
'Get file name 取出文件名
strFileName = Mid$(strFilePath, InStrRev(strFilePath, "\") + 1)
'
'Insert first marker: "begin 664 ..." 插入初始的标志
strResult = "begin 664 " + strFileName + vbCrLf
'
'Get file size 取出文件的大小
lFileSize = FileLen(strFilePath)
lEncodedLines = lFileSize \ 45 + 1 '编码后的总行数等于lFileSize \ 45 + 1

'准备缓冲区,以从文件中取出45个字符的块
'Prepare buffer to retrieve data from
'the file by 45 symbols chunks
ReDim aFileData(1 To 45)
'
intFile = FreeFile '得到一个空闲的文件号
'
Open strFilePath For Binary As intFile '打开文件

For i = 1 To lEncodedLines
'Read file data by 45-bytes cnunks 读文件,一次45个字节的块
'
If i = lEncodedLines Then

'最后一行编码数据通常不会等于45,因此我们需要改变缓冲区的大小

If (lFileSize Mod 45) > 0 Then
ReDim aFileData(1 To lFileSize Mod 45)
Else
ReDim aFileData(0)
End If
End If

'If UBound(aFileData) > 0 Then

'从文件中读取一个数据块到缓冲区中。
'Retrieve data chunk from file to the buffer

Get intFile, , aFileData()

'添加一个字符,这个字符指明编码的行有多少个字符。

strTempLine = Chr(UBound(aFileData) + 32)
'
If i = lEncodedLines And (UBound(aFileData) Mod 3) Then
'If the last line is processed and length of
'source data is not a number divisible by 3, add one or two
'blankspace symbols
ReDim Preserve aFileData _
(1 To UBound(aFileData) + (3 - (UBound(aFileData) Mod 3)))
End If

For j = 1 To UBound(aFileData) Step 3
'Breake each 3 (8-bits) bytes to 4 (6-bits) bytes
'
'1 byte
strTempLine = strTempLine + ChrW(aFileData(j) \ 4 + 32)
'2 byte
strTempLine = strTempLine + ChrW((aFileData(j) Mod 4) * 16 _
+ aFileData(j + 1) \ 16 + 32)
'3 byte
strTempLine = strTempLine + Chr((aFileData(j + 1) Mod 16) * 4 _
+ aFileData(j + 2) \ 64 + 32)
'4 byte
strTempLine = strTempLine + Chr(aFileData(j + 2) Mod 64 + 32)
Next j
'replace " " with "`"
strTempLine = Replace(strTempLine, " ", "`")
'add encoded line to result buffer
strResult = strResult + strTempLine + vbCrLf
'reset line buffer
strTempLine = ""

'End If
Next i
Close intFile

'add the end marker
strResult = strResult & "`" & vbCrLf + "end" + vbCrLf
'asign return value
UUEncodeFile = strResult

End Function



Public Function UUDecodeToFile(strUUCodeData As String, strFilePath As String)

Dim vDataLine As Variant
Dim vDataLines As Variant
Dim strDataLine As String
Dim intSymbols As Integer
Dim intFile As Integer
Dim aTempData() As Byte '输出缓冲区
Dim aOutputData() As Byte
Dim i As Long 'loop counter 循环变量
Dim j As Integer 'loop counter
Dim k As Long

ReDim aTempData(0)
'
'remove begin marker
If Left$(strUUCodeData, 6) = "begin " Then
strUUCodeData = Mid$(strUUCodeData, InStr(1, strUUCodeData, vbLf) + 1)
End If
'
'remove end marker
If Right$(strUUCodeData, 5) = "end" + vbCrLf Then
strUUCodeData = Left$(strUUCodeData, Len(strUUCodeData) - 10)
End If

intFile = FreeFile
Open strFilePath For Binary As intFile
'Split encoded data to vDataLines array.
'Now each array member contains a line of encoded data
vDataLines = Split(strUUCodeData, vbCrLf)

For Each vDataLine In vDataLines
'Decode data line by line
'
strDataLine = CStr(vDataLine)
'Get quantity of symbols in a line
intSymbols = Asc(Left$(strDataLine, 1)) - 32
'remove first symbol that just informs
'about quantity of symbols
strDataLine = Mid$(strDataLine, 2)
'replace "`" with " "
strDataLine = Replace(strDataLine, "`", " ")
'Convert every 4-byte chunk to 3-byte chunk by
For i = 1 To Len(strDataLine) Step 4
'1 byte
ReDim Preserve aTempData(UBound(aTempData) + 1)
aTempData(UBound(aTempData)) = (Asc(Mid(strDataLine, i, 1)) - 32) * 4 + _
(Asc(Mid(strDataLine, i + 1, 1)) - 32) \ 16

'strTemp = strTemp + Chr((Asc(Mid(strDataLine, i, 1)) - 32) * 4 + _
' (Asc(Mid(strDataLine, i + 1, 1)) - 32) \ 16)

'2 byte
ReDim Preserve aTempData(UBound(aTempData) + 1)
aTempData(UBound(aTempData)) = (Asc(Mid(strDataLine, i + 1, 1)) Mod 16) * 16 + _
(Asc(Mid(strDataLine, i + 2, 1)) - 32) \ 4

'strTemp = strTemp + Chr((Asc(Mid(strDataLine, i + 1, 1)) Mod 16) * 16 + _
' (Asc(Mid(strDataLine, i + 2, 1)) - 32) \ 4)

'3 byte
ReDim Preserve aTempData(UBound(aTempData) + 1)
aTempData(UBound(aTempData)) = (Asc(Mid(strDataLine, i + 2, 1)) Mod 4) * 64 + _
Asc(Mid(strDataLine, i + 3, 1)) - 32

'strTemp = strTemp + Chr((Asc(Mid(strDataLine, i + 2, 1)) Mod 4) * 64 + _
' Asc(Mid(strDataLine, i + 3, 1)) - 32)
Next i
'
'ReDim Preserve aTempData(intSymbols)
If UBound(aTempData) > intSymbols Then ReDim Preserve aTempData(intSymbols)
'strTemp = Left(strTemp, intSymbols)

'write decoded line to the file
If UBound(aTempData) > 0 Then
ReDim aOutputData(1 To UBound(aTempData))
For k = 1 To UBound(aTempData)
aOutputData(k) = aTempData(k)
Next k
Put intFile, , aOutputData()
End If
'clear buffer for next line
ReDim aTempData(0)
Next

Close intFile

End Function
回复
qiqi5521 2005-03-19
凑合着能用了.还有些问题,比如效率问题,以后慢慢搞定吧.
回复
qiqi5521 2005-03-19
Attribute VB_Name = "Module1"
Option Explicit

Public Function UUEncodeFile(strFilePath As String) As String

Dim intFile As Integer 'file handler 文件号
Dim intTempFile As Integer 'temp file 临时文件的文件号
Dim lFileSize As Long 'size of the file 文件大小
Dim strFileName As String 'name of the file 文件名
Dim aFileData() As Byte 'file data chunk 文件数据块
Dim lEncodedLines As Long 'number of encoded lines 编码后的总行数
Dim strTempLine As String 'temporary string 临时字符串
Dim i As Long 'loop counter 循环变量
Dim j As Integer 'loop counter

Dim strResult As String '结果字符串


'
'Get file name 取出文件名
strFileName = Mid$(strFilePath, InStrRev(strFilePath, "\") + 1)
'
'Insert first marker: "begin 664 ..." 插入初始的标志
strResult = "begin 664 " + strFileName + vbCrLf
'
'Get file size 取出文件的大小
lFileSize = FileLen(strFilePath)
lEncodedLines = lFileSize \ 45 + 1 '编码后的总行数等于lFileSize \ 45 + 1

'准备缓冲区,以从文件中取出45个字符的块
'Prepare buffer to retrieve data from
'the file by 45 symbols chunks
ReDim aFileData(1 To 45)
'
intFile = FreeFile '得到一个空闲的文件号
'
Open strFilePath For Binary As intFile '打开文件

For i = 1 To lEncodedLines
'Read file data by 45-bytes cnunks 读文件,一次45个字节的块
'
If i = lEncodedLines Then

'最后一行编码数据通常不会等于45,因此我们需要改变缓冲区的大小
'Last line of encoded data often is not
'equal to 45, therefore we need to change
'size of the buffer
If (lFileSize Mod 45) > 0 Then
ReDim aFileData(1 To lFileSize Mod 45)
Else
ReDim aFileData(0)
End If
End If
'从文件中读取一个数据块到缓冲区中。
'Retrieve data chunk from file to the buffer
Get intFile, , aFileData()

'添加一个字符,这个字符指明编码的行有多少个字符。
'Add first symbol to encoded string that informs
'about quantity of symbols in encoded string.
'More often "M" symbol is used.
strTempLine = Chr(UBound(aFileData) + 32)
'
If i = lEncodedLines And (UBound(aFileData) Mod 3) Then
'If the last line is processed and length of
'source data is not a number divisible by 3, add one or two
'blankspace symbols
ReDim Preserve aFileData _
(1 To UBound(aFileData) + (3 - (UBound(aFileData) Mod 3)))
End If

For j = 1 To UBound(aFileData) Step 3
'Breake each 3 (8-bits) bytes to 4 (6-bits) bytes
'
'1 byte
strTempLine = strTempLine + ChrW(aFileData(j) \ 4 + 32)
'2 byte
strTempLine = strTempLine + ChrW((aFileData(j) Mod 4) * 16 _
+ aFileData(j + 1) \ 16 + 32)
'3 byte
strTempLine = strTempLine + Chr((aFileData(j + 1) Mod 16) * 4 _
+ aFileData(j + 2) \ 64 + 32)
'4 byte
strTempLine = strTempLine + Chr(aFileData(j + 2) Mod 64 + 32)
Next j
'replace " " with "`"
strTempLine = Replace(strTempLine, " ", "`")
'add encoded line to result buffer
strResult = strResult + strTempLine + vbCrLf
'reset line buffer
strTempLine = ""
Next i
Close intFile

'add the end marker
strResult = strResult & "`" & vbCrLf + "end" + vbCrLf
'asign return value
UUEncodeFile = strResult

End Function



Public Function UUDecodeToFile(strUUCodeData As String, strFilePath As String)

Dim vDataLine As Variant
Dim vDataLines As Variant
Dim strDataLine As String
Dim intSymbols As Integer
Dim intFile As Integer
Dim aTempData() As Byte '输出缓冲区
Dim aOutputData() As Byte
Dim i As Long 'loop counter 循环变量
Dim j As Integer 'loop counter
Dim k As Long

ReDim aTempData(0)
'
'remove begin marker
If Left$(strUUCodeData, 6) = "begin " Then
strUUCodeData = Mid$(strUUCodeData, InStr(1, strUUCodeData, vbLf) + 1)
End If
'
'remove end marker
If Right$(strUUCodeData, 5) = "end" + vbCrLf Then
strUUCodeData = Left$(strUUCodeData, Len(strUUCodeData) - 10)
End If

intFile = FreeFile
Open strFilePath For Binary As intFile
'Split encoded data to vDataLines array.
'Now each array member contains a line of encoded data
vDataLines = Split(strUUCodeData, vbCrLf)

For Each vDataLine In vDataLines
'Decode data line by line
'
strDataLine = CStr(vDataLine)
'Get quantity of symbols in a line
intSymbols = Asc(Left$(strDataLine, 1)) - 32
'remove first symbol that just informs
'about quantity of symbols
strDataLine = Mid$(strDataLine, 2)
'replace "`" with " "
strDataLine = Replace(strDataLine, "`", " ")
'Convert every 4-byte chunk to 3-byte chunk by
For i = 1 To Len(strDataLine) Step 4
'1 byte
ReDim Preserve aTempData(UBound(aTempData) + 1)
aTempData(UBound(aTempData)) = (Asc(Mid(strDataLine, i, 1)) - 32) * 4 + _
(Asc(Mid(strDataLine, i + 1, 1)) - 32) \ 16

'strTemp = strTemp + Chr((Asc(Mid(strDataLine, i, 1)) - 32) * 4 + _
' (Asc(Mid(strDataLine, i + 1, 1)) - 32) \ 16)

'2 byte
ReDim Preserve aTempData(UBound(aTempData) + 1)
aTempData(UBound(aTempData)) = (Asc(Mid(strDataLine, i + 1, 1)) Mod 16) * 16 + _
(Asc(Mid(strDataLine, i + 2, 1)) - 32) \ 4

'strTemp = strTemp + Chr((Asc(Mid(strDataLine, i + 1, 1)) Mod 16) * 16 + _
' (Asc(Mid(strDataLine, i + 2, 1)) - 32) \ 4)

'3 byte
ReDim Preserve aTempData(UBound(aTempData) + 1)
aTempData(UBound(aTempData)) = (Asc(Mid(strDataLine, i + 2, 1)) Mod 4) * 64 + _
Asc(Mid(strDataLine, i + 3, 1)) - 32

'strTemp = strTemp + Chr((Asc(Mid(strDataLine, i + 2, 1)) Mod 4) * 64 + _
' Asc(Mid(strDataLine, i + 3, 1)) - 32)
Next i
'
ReDim Preserve aTempData(intSymbols)
'strTemp = Left(strTemp, intSymbols)

'write decoded line to the file
ReDim aOutputData(1 To UBound(aTempData))
For k = 1 To UBound(aTempData)
aOutputData(k) = aTempData(k)
Next k
Put intFile, , aOutputData()
'clear buffer for next line
ReDim aTempData(0)
Next

Close intFile

End Function


回复
qiqi5521 2005-03-18
关注。正调试
回复
是是非非 2005-03-18
关注
回复
qiqi5521 2005-03-18
问题在哪里我倒是看出来了,今晚抽空改改这个代码,也许能改好。

这个代码问题可能就是它竟然用字符串做缓冲区来读取二进制文件,很可能问题就出在这里。用字节数组做缓冲区应该能解决问题。
回复
sbknow 2005-03-18
谢谢了。我都弄了2天了,一直找不到问题所在,程序是网上找的
回复
相关推荐
发帖
网络编程
创建于2007-09-28

1480

社区成员

VB 网络编程
申请成为版主
帖子事件
创建了帖子
2005-03-18 10:05
社区公告
暂无公告