首先非常感谢大家的关注。浪费了大家的时间,我也感到很抱歉。只是这个问题已经很久了,而我自己又不知道问题的原因,所以才来麻烦大家。具体代码是这样的:Public Function LoadFile(Optional ByVal FileName As String) '载入文件 Dim TmpStr As String Dim tmpNum1 As Long, tmpNum2 As Long, tmpNum3 As Long Dim i As Long Dim hIcon As Long Dim cDlg As New ClsComdlg On Error GoTo Err
If Changed = True Then If MsgBox("当前文件已经改变,是否保存?", vbYesNo) = vbYes Then Call SaveFile Exit Function End If End If
If Len(FileName) < 5 Then With cDlg .FileTitle = "打开文件" .Filter = "数据文件(*.DAT)|*.DAT|所有文件(*.*)|*.*" .ShowOpen FileName = .FileName End With
If Len(FileName) < 6 Then Exit Function End If
If FileExist(FileName) <> 1 Then bMsg.bMsgBox "加载数据文件失败!", "严重" Exit Function Else Call ClsArray Open FileName For Input As #1 Do While Not EOF(1)
If TmpStr = "" Then '读入兼容模式 RunMode(UBound(RunMode)) = -1 Else RunMode(UBound(RunMode)) = CInt(TmpStr) End If Else GoTo Err End If ElseIf Mid(TmpStr, 1, 3) = "#@#" Then TmpStr = Right(TmpStr, Len(TmpStr) - 3) tmpNum1 = InStr(TmpStr, ",")
cUser = Mid(TmpStr, 1, tmpNum1 - 1) '读入用户名
TmpStr = Right(TmpStr, Len(TmpStr) - tmpNum1)
cPassWD = TmpStr '读入密码 End If End If Loop Close #1
Changed = False
Exit Function End If
Err: bMsg.bMsgBox "读取数据时出现错误!", "严重" Close #1 Exit FunctionEnd Function
这个过程是我程序的主类里的一个方法,用于读入数据文件到类中一组动态数组内。其实它现在也工作很长一段时间了,只是这几天发现读入的文件中有一些中文不对头。由于并不是全部不对,所以也觉得有点晕晕的(数据文件是用记事本手工编辑后保存为Dat文件的)。另外,对于注册表的读入,就完全不对了,没有一个汉字是正常的,读注册表过程如下:Public Sub OpenRegFile(ByVal RegFileName As String) Dim RegStr() As String, tmpValue(5) As Long Dim i As Long Dim MainKeyName As String, SubKeyName As String, KeyValue As String
ReDim RegStr(0)
Open RegFileName For Input As #1 Do While EOF(1) = False ReDim Preserve RegStr(UBound(RegStr) + 1) Line Input #1, RegStr(UBound(RegStr)) RegStr(UBound(RegStr)) = UCase(RegStr(UBound(RegStr))) Loop Close #1
If tmpValue(1) > 0 And tmpValue(2) > 0 Then MainKeyName = Mid(RegStr(i), tmpValue(1) + 1, tmpValue(2) - tmpValue(1) - 1) End If
If tmpValue(0) = 0 Then If tmpValue(3) > 0 Then '二进制值 If GetKeyValue(RegStr(i), REGS_HEX, SubKeyName, KeyValue) = 1 Then SetBinaryValue MainKeyName, SubKeyName, Hex(KeyValue) End If ElseIf tmpValue(4) > 0 Then '十六进制值 If GetKeyValue(RegStr(i), REGS_DWORD, SubKeyName, KeyValue) = 1 Then SetDWORDValue MainKeyName, SubKeyName, "&H" & KeyValue End If ElseIf tmpValue(5) > 0 Then '字符串值 If GetKeyValue(RegStr(i), REGS_STRING, SubKeyName, KeyValue) = 1 Then SetStringValue MainKeyName, SubKeyName, KeyValue End If End If
End If Next i End Sub由于某些程序的注册表字符串中含有中文,导致这个过程根本无法使用,以致于现在我都还是调用的regedit.exe来导入,真的很不爽。现在我希望各位能把造成此问题的原因讲讲,好让我以后遇到此类问题后也可以自己分析并解决。当然,能同时给出解决方案就更好了,呵呵~~还有就是,我没有看过VB编程方面的书,学VB基本是看别人代码以及写代码学来的,所以在基础方面非常的差,因此在某些基础知识上还希望各位不嫌麻烦,讲明白一些~~:D辛苦大家了!!
注册表的: 'This program needs 3 buttons Const REG_SZ = 1 ' Unicode nul terminated string Const REG_BINARY = 3 ' Free form binary Const HKEY_CURRENT_USER = &H80000001 Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long Private Declare Function RegCreateKey Lib "advapi32.dll" Alias "RegCreateKeyA" (ByVal hKey As Long, ByVal lpSubKey As String, phkResult As Long) As Long Private Declare Function RegDeleteValue Lib "advapi32.dll" Alias "RegDeleteValueA" (ByVal hKey As Long, ByVal lpValueName As String) As Long Private Declare Function RegOpenKey Lib "advapi32.dll" Alias "RegOpenKeyA" (ByVal hKey As Long, ByVal lpSubKey As String, phkResult As Long) As Long Private Declare Function RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, lpData As Any, lpcbData As Long) As Long Private Declare Function RegSetValueEx Lib "advapi32.dll" Alias "RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal Reserved As Long, ByVal dwType As Long, lpData As Any, ByVal cbData As Long) As Long Function RegQueryStringValue(ByVal hKey As Long, ByVal strValueName As String) As String Dim lResult As Long, lValueType As Long, strBuf As String, lDataBufSize As Long 'retrieve nformation about the key lResult = RegQueryValueEx(hKey, strValueName, 0, lValueType, ByVal 0, lDataBufSize) If lResult = 0 Then If lValueType = REG_SZ Then 'Create a buffer strBuf = String(lDataBufSize, Chr$(0)) 'retrieve the key's content lResult = RegQueryValueEx(hKey, strValueName, 0, 0, ByVal strBuf, lDataBufSize) If lResult = 0 Then 'Remove the unnecessary chr$(0)'s RegQueryStringValue = Left$(strBuf, InStr(1, strBuf, Chr$(0)) - 1) End If ElseIf lValueType = REG_BINARY Then Dim strData As Integer 'retrieve the key's value lResult = RegQueryValueEx(hKey, strValueName, 0, 0, strData, lDataBufSize) If lResult = 0 Then RegQueryStringValue = strData End If End If End If End Function Function GetString(hKey As Long, strPath As String, strValue As String) Dim Ret 'Open the key RegOpenKey hKey, strPath, Ret 'Get the key's content GetString = RegQueryStringValue(Ret, strValue) 'Close the key RegCloseKey Ret End Function调用的时候用GetString这个函数即可
End Enum'ANSI+DBCS方式的文本所使用的代码页。默认为0,表示使用系统当前代码页。可以利用该参数实现读取其他代码编码的文本,比如想在 简体中文平台下 读取 繁体中文平台生成的txt,就将它设为950 Public UEFCodePage As Long'判断BOM '返回值:BOM所占字节 'dwFirst:[in]文件最开始的4个字节 'fmt:[out]返回编码类型 Public Function UEFCheckBOM(ByVal dwFirst As Long, ByRef fmt As UnicodeEncodeFormat) As Long If dwFirst = &HFEFF& Then fmt = UEF_UTF32LE UEFCheckBOM = 4 ElseIf dwFirst = &HFFFE0000 Then fmt = UEF_UTF32BE UEFCheckBOM = 4 ElseIf (dwFirst And &HFFFF&) = &HFEFF& Then fmt = UEF_UTF16LE UEFCheckBOM = 2 ElseIf (dwFirst And &HFFFF&) = &HFFFE& Then fmt = UEF_UTF16BE UEFCheckBOM = 2 ElseIf (dwFirst And &HFFFFFF) = &HBFBBEF Then fmt = UEF_UTF8 UEFCheckBOM = 3 Else fmt = UEF_ANSI UEFCheckBOM = 0 End If End Function'生成BOM '返回值:BOM所占字节 'fmt:[in]编码类型 'dwFirst:[out]文件最开始的4个字节 Public Function UEFMakeBOM(ByVal fmt As UnicodeEncodeFormat, ByRef dwFirst As Long) As Long Select Case fmt Case UEF_UTF8 dwFirst = &HBFBBEF UEFMakeBOM = 3 Case UEF_UTF16LE dwFirst = &HFEFF& UEFMakeBOM = 2 Case UEF_UTF16BE dwFirst = &HFFFE& UEFMakeBOM = 2 Case UEF_UTF32LE dwFirst = &HFEFF& UEFMakeBOM = 4 Case UEF_UTF32BE dwFirst = &HFFFE0000 UEFMakeBOM = 4 Case Else dwFirst = 0 UEFMakeBOM = 0 End Select End Function'判断文本文件的编码类型 '返回值:编码类型。文件无法打开时,返回UEF_Auto 'FileName:文件名 Public Function UEFCheckTextFileFormat(ByVal FileName As String) As UnicodeEncodeFormat Dim hFile As Long Dim dwFirst As Long Dim nNumRead As Long
'打开文件 hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, ByVal 0&) If INVALID_HANDLE_VALUE = hFile Then '文件无法打开 UEFCheckTextFileFormat = UEF_Auto Exit Function End If
'读取文本文件 '返回值:读取的文本。返回vbNullString表示文件无法打开 'FileName:[in]文件名 'fmt:[in,out]使用何种文本编码格式来读取文本。为UEF_Auto时表示自动判断,且在fmt参数返回文本所用编码格式 Public Function UEFLoadTextFile(ByVal FileName As String, Optional ByRef fmt As UnicodeEncodeFormat = UEF_Auto) As String Dim hFile As Long Dim nFileSize As Long Dim nNumRead As Long Dim dwFirst As Long Dim CurFmt As UnicodeEncodeFormat Dim cbBOM As Long Dim cbTextData As Long Dim CurCP As Long Dim byBuf() As Byte Dim cchStr As Long Dim I As Long Dim byTemp As Byte
'判断fmt范围 If fmt <> UEF_Auto Then If fmt < [_UEF_Min] Or fmt > [_UEF_Max] Then GoTo FunEnd End If End If
'打开文件 hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, ByVal 0&) If INVALID_HANDLE_VALUE = hFile Then '文件无法打开 GoTo FunEnd End If
'判断文件大小 nFileSize = GetFileSize(hFile, nNumRead) If nNumRead <> 0 Then '超过4GB GoTo FreeHandle End If If nFileSize < 0 Then '超过2GB GoTo FreeHandle End If
'修正文本长度 cchStr = (nNumRead + 1) \ 2 If cchStr > 0 Then If Len(UEFLoadTextFile) > cchStr Then UEFLoadTextFile = Left$(UEFLoadTextFile, cchStr) End If Else UEFLoadTextFile = "" End If
Case UEF_UTF16BE '分配缓冲区 On Error GoTo FreeHandle ReDim byBuf(0 To cbTextData - 1) On Error GoTo 0
If nNumRead > 0 Then '隔两字节翻转相邻字节 For I = 0 To nNumRead - 1 - 1 Step 2 '再-1是为了避免最后多出的那个字节 byTemp = byBuf(I) byBuf(I) = byBuf(I + 1) byBuf(I + 1) = byTemp Next I
Case UEF_UTF32LE UEFLoadTextFile = vbNullString '暂时不支持 Case UEF_UTF32BE UEFLoadTextFile = vbNullString '暂时不支持 Case Else Debug.Assert False End Select
FreeHandle: '关闭文件 Call CloseHandle(hFile)
FunEnd: End Function
'保存文本文件 '返回值:是否成功 'FileName:[in]文件名 'sText:[in]欲输出的文本 'IsAppend:[in]是否是添加方式 'fmt:[in,out]使用何种文本编码格式来存储文本。当IsAppend=True时允许UEF_Auto自动判断,且在fmt参数返回文本所用编码格式 'DefFmt:[in]当使用添加模式时,若文件不存在且fmt = UEF_Auto时应使用的编码格式 Public Function UEFSaveTextFile(ByVal FileName As String, _ ByRef sText As String, Optional ByVal IsAppend As Boolean = False, _ Optional ByRef fmt As UnicodeEncodeFormat = UEF_Auto, Optional ByVal DefFmt As UnicodeEncodeFormat = UEF_ANSI) As Boolean Dim hFile As Long Dim nFileSize As Long Dim nNumRead As Long Dim dwFirst As Long Dim cbBOM As Long Dim CurCP As Long Dim byBuf() As Byte Dim cbBuf As Long Dim I As Long Dim byTemp As Byte
'判断fmt范围 If IsAppend And (fmt = UEF_Auto) Then Else If fmt < [_UEF_Min] Or fmt > [_UEF_Max] Then GoTo FunEnd End If End If
'打开文件 hFile = CreateFile(FileName, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, IIf(IsAppend, OPEN_ALWAYS, CREATE_ALWAYS), FILE_ATTRIBUTE_NORMAL, ByVal 0&) If INVALID_HANDLE_VALUE = hFile Then '文件无法打开 GoTo FunEnd End If
'判断文件大小 nFileSize = GetFileSize(hFile, nNumRead) If nFileSize = 0 And nNumRead = 0 Then '文件大小为0字节 IsAppend = False '此时需要写BOM标志 If fmt = UEF_Auto Then fmt = DefFmt End If
'判断BOM If IsAppend And (fmt = UEF_Auto) Then dwFirst = 0 Call ReadFile(hFile, dwFirst, 4, nNumRead, ByVal 0&) cbBOM = UEFCheckBOM(dwFirst, fmt) ElseIf IsAppend = False Then cbBOM = UEFMakeBOM(fmt, dwFirst) End If
Case UEF_UTF32LE UEFSaveTextFile = False '暂时不支持 Case UEF_UTF32BE UEFSaveTextFile = False '暂时不支持 Case Else Debug.Assert False End Select Else UEFSaveTextFile = True End If
'载入文件
Dim TmpStr As String
Dim tmpNum1 As Long, tmpNum2 As Long, tmpNum3 As Long
Dim i As Long
Dim hIcon As Long
Dim cDlg As New ClsComdlg On Error GoTo Err
If Changed = True Then
If MsgBox("当前文件已经改变,是否保存?", vbYesNo) = vbYes Then
Call SaveFile
Exit Function
End If
End If
If Len(FileName) < 5 Then
With cDlg
.FileTitle = "打开文件"
.Filter = "数据文件(*.DAT)|*.DAT|所有文件(*.*)|*.*"
.ShowOpen
FileName = .FileName
End With
If Len(FileName) < 6 Then Exit Function
End If
If FileExist(FileName) <> 1 Then
bMsg.bMsgBox "加载数据文件失败!", "严重"
Exit Function
Else
Call ClsArray Open FileName For Input As #1
Do While Not EOF(1)
Line Input #1, TmpStr
TmpStr = Mid(TmpStr, 2, Len(TmpStr) - 2)
If Len(TmpStr) > 1 Then
' TmpStr = DeCode(TmpStr, PassWD)
If Mid(TmpStr, 1, 3) = "###" Then '读入分类列表
ReDim Preserve ProgTypeList(UBound(ProgTypeList) + 1)
ReDim Preserve ProgTL_Num(UBound(ProgTL_Num) + 1)
TmpStr = Right(TmpStr, Len(TmpStr) - 3)
tmpNum1 = InStr(TmpStr, ",")
ProgTypeList(UBound(ProgTypeList)) = Mid(TmpStr, 1, tmpNum1 - 1)
TmpStr = Right(TmpStr, Len(TmpStr) - tmpNum1)
If tmpNum1 > 0 Then ProgTL_Num(UBound(ProgTL_Num)) = CInt(TmpStr)
ElseIf Mid(TmpStr, 1, 3) = "#$#" Then
ReDim Preserve ProgTitle(UBound(ProgTitle) + 1)
ReDim Preserve ProgExeName(UBound(ProgExeName) + 1)
ReDim Preserve ProgCmd(UBound(ProgCmd) + 1)
ReDim Preserve ProgType(UBound(ProgType) + 1)
ReDim Preserve ProgIco(UBound(ProgIco) + 1)
ReDim Preserve RunBefore(UBound(RunBefore) + 1)
ReDim Preserve RunBCmd(UBound(RunBCmd) + 1)
ReDim Preserve RunMode(UBound(RunMode) + 1)
ReDim Preserve RunInHDD(UBound(RunInHDD) + 1)
TmpStr = Right(TmpStr, Len(TmpStr) - 3)
tmpNum1 = InStr(TmpStr, ",")
If tmpNum1 > 0 Then
ProgTitle(UBound(ProgTitle)) = Mid(TmpStr, 1, tmpNum1 - 1) '读入标题
TmpStr = Right(TmpStr, Len(TmpStr) - tmpNum1) '切割
tmpNum2 = InStr(TmpStr, ",")
ProgExeName(UBound(ProgExeName)) = Mid(TmpStr, 1, tmpNum2 - 1) '读入文件名
Debug.Print ProgExeName(UBound(ProgExeName))
TmpStr = Right(TmpStr, Len(TmpStr) - tmpNum2) '再切割
tmpNum1 = InStr(TmpStr, ",")
ProgCmd(UBound(ProgCmd)) = Mid(TmpStr, 1, tmpNum1 - 1) '读入运行参数
TmpStr = Right(TmpStr, Len(TmpStr) - tmpNum1) '再切割
tmpNum2 = InStr(TmpStr, ",")
ProgType(UBound(ProgType)) = CInt(Mid(TmpStr, 1, tmpNum2 - 1)) '读入分类
TmpStr = Right(TmpStr, Len(TmpStr) - tmpNum2) '再切割
tmpNum1 = InStr(TmpStr, ",")
ProgIco(UBound(ProgIco)) = Mid(TmpStr, 1, tmpNum1 - 1) '读入图标
TmpStr = Right(TmpStr, Len(TmpStr) - tmpNum1) '再切割
tmpNum2 = InStr(TmpStr, ",")
RunBefore(UBound(RunBefore)) = Mid(TmpStr, 1, tmpNum2 - 1) '读入"运行前执行"
TmpStr = Right(TmpStr, Len(TmpStr) - tmpNum2) '再切割
tmpNum1 = InStr(TmpStr, ",")
RunBCmd(UBound(RunBCmd)) = Mid(TmpStr, 1, tmpNum1 - 1) '读入"运行前执行"的参数
TmpStr = Right(TmpStr, Len(TmpStr) - tmpNum1) '再切割
tmpNum2 = InStr(TmpStr, ",")
If Mid(TmpStr, 1, tmpNum2 - 1) = "" Then '读入"是否在本地运行"
RunInHDD(UBound(RunInHDD)) = 0
Else
RunInHDD(UBound(RunInHDD)) = CInt(Mid(TmpStr, 1, tmpNum2 - 1))
End If
TmpStr = Right(TmpStr, Len(TmpStr) - tmpNum2) '再切割
tmpNum1 = InStr(TmpStr, ",")
If TmpStr = "" Then '读入兼容模式
RunMode(UBound(RunMode)) = -1
Else
RunMode(UBound(RunMode)) = CInt(TmpStr)
End If
Else
GoTo Err
End If
ElseIf Mid(TmpStr, 1, 3) = "#@#" Then
TmpStr = Right(TmpStr, Len(TmpStr) - 3)
tmpNum1 = InStr(TmpStr, ",")
cUser = Mid(TmpStr, 1, tmpNum1 - 1) '读入用户名
TmpStr = Right(TmpStr, Len(TmpStr) - tmpNum1)
cPassWD = TmpStr '读入密码
End If
End If
Loop
Close #1
Changed = False
Exit Function
End If
Err: bMsg.bMsgBox "读取数据时出现错误!", "严重"
Close #1
Exit FunctionEnd Function
Dim RegStr() As String, tmpValue(5) As Long
Dim i As Long
Dim MainKeyName As String, SubKeyName As String, KeyValue As String
ReDim RegStr(0)
Open RegFileName For Input As #1
Do While EOF(1) = False
ReDim Preserve RegStr(UBound(RegStr) + 1)
Line Input #1, RegStr(UBound(RegStr))
RegStr(UBound(RegStr)) = UCase(RegStr(UBound(RegStr)))
Loop
Close #1
For i = 1 To UBound(RegStr)
tmpValue(0) = InStr(RegStr(i), "@")
tmpValue(1) = InStr(RegStr(i), "[")
tmpValue(2) = InStr(RegStr(i), "]")
tmpValue(3) = InStr(RegStr(i), """=HEX:")
tmpValue(4) = InStr(RegStr(i), """=DWORD:")
tmpValue(5) = InStr(RegStr(i), """=""")
SubKeyName = ""
KeyValue = ""
If tmpValue(1) > 0 And tmpValue(2) > 0 Then
MainKeyName = Mid(RegStr(i), tmpValue(1) + 1, tmpValue(2) - tmpValue(1) - 1)
End If
If tmpValue(0) = 0 Then
If tmpValue(3) > 0 Then
'二进制值
If GetKeyValue(RegStr(i), REGS_HEX, SubKeyName, KeyValue) = 1 Then
SetBinaryValue MainKeyName, SubKeyName, Hex(KeyValue)
End If
ElseIf tmpValue(4) > 0 Then
'十六进制值
If GetKeyValue(RegStr(i), REGS_DWORD, SubKeyName, KeyValue) = 1 Then
SetDWORDValue MainKeyName, SubKeyName, "&H" & KeyValue
End If
ElseIf tmpValue(5) > 0 Then
'字符串值
If GetKeyValue(RegStr(i), REGS_STRING, SubKeyName, KeyValue) = 1 Then
SetStringValue MainKeyName, SubKeyName, KeyValue
End If
End If
End If
Next i
End Sub由于某些程序的注册表字符串中含有中文,导致这个过程根本无法使用,以致于现在我都还是调用的regedit.exe来导入,真的很不爽。现在我希望各位能把造成此问题的原因讲讲,好让我以后遇到此类问题后也可以自己分析并解决。当然,能同时给出解决方案就更好了,呵呵~~还有就是,我没有看过VB编程方面的书,学VB基本是看别人代码以及写代码学来的,所以在基础方面非常的差,因此在某些基础知识上还希望各位不嫌麻烦,讲明白一些~~:D辛苦大家了!!
'This program needs 3 buttons
Const REG_SZ = 1 ' Unicode nul terminated string
Const REG_BINARY = 3 ' Free form binary
Const HKEY_CURRENT_USER = &H80000001
Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long
Private Declare Function RegCreateKey Lib "advapi32.dll" Alias "RegCreateKeyA" (ByVal hKey As Long, ByVal lpSubKey As String, phkResult As Long) As Long
Private Declare Function RegDeleteValue Lib "advapi32.dll" Alias "RegDeleteValueA" (ByVal hKey As Long, ByVal lpValueName As String) As Long
Private Declare Function RegOpenKey Lib "advapi32.dll" Alias "RegOpenKeyA" (ByVal hKey As Long, ByVal lpSubKey As String, phkResult As Long) As Long
Private Declare Function RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, lpData As Any, lpcbData As Long) As Long
Private Declare Function RegSetValueEx Lib "advapi32.dll" Alias "RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal Reserved As Long, ByVal dwType As Long, lpData As Any, ByVal cbData As Long) As Long
Function RegQueryStringValue(ByVal hKey As Long, ByVal strValueName As String) As String
Dim lResult As Long, lValueType As Long, strBuf As String, lDataBufSize As Long
'retrieve nformation about the key
lResult = RegQueryValueEx(hKey, strValueName, 0, lValueType, ByVal 0, lDataBufSize)
If lResult = 0 Then
If lValueType = REG_SZ Then
'Create a buffer
strBuf = String(lDataBufSize, Chr$(0))
'retrieve the key's content
lResult = RegQueryValueEx(hKey, strValueName, 0, 0, ByVal strBuf, lDataBufSize)
If lResult = 0 Then
'Remove the unnecessary chr$(0)'s
RegQueryStringValue = Left$(strBuf, InStr(1, strBuf, Chr$(0)) - 1)
End If
ElseIf lValueType = REG_BINARY Then
Dim strData As Integer
'retrieve the key's value
lResult = RegQueryValueEx(hKey, strValueName, 0, 0, strData, lDataBufSize)
If lResult = 0 Then
RegQueryStringValue = strData
End If
End If
End If
End Function
Function GetString(hKey As Long, strPath As String, strValue As String)
Dim Ret
'Open the key
RegOpenKey hKey, strPath, Ret
'Get the key's content
GetString = RegQueryStringValue(Ret, strValue)
'Close the key
RegCloseKey Ret
End Function调用的时候用GetString这个函数即可
你的文本文件肯定不是本地编码(比如gb2312), 说不定是unicode编码的。
你在2000下用notepad打开, 另存为一下就行了。
可以以用MultiByteToWideChar将其转为Unicode格式,使用Windows2000新增代码页65001对于UTF-16LE
VB的String用的就是UTF-16LE格式,先用字节数组读取文件内容,再直接给字符串变量赋值(sText = byBuf)对于UTF-16BE
这是大端方式的UTF-16,先还是用字节数组读取文件内容,然后在字节数组中两个两个地交换相邻字节,再直接给字符串变量赋值对于UTF-32
UTF-32采用的是4字节编码,只能手动转换,幸亏其不多见。
a=len("你好")
b=len("abcd")
c=lenb("你好")
d=lenb("abcd")
如果你认为a=b,那问题就出在这里了,实际结果是a=2,b=4,也就是说一个汉字占二个字符位(双字节表示),但c=d且都等于4,这说明它们占的字节数相同。这样问题也同样存在于mid这种字符串截取函数中,这里还有几个表达式:
str1=mid("你好吗",2)
str2=midb("你好吗",2)
str3=mid("abcdef",2)
str4=midb("abcdef",2)
str5=midb("abcdef",3)
对比一下它们的值,再注意一下它们的实际截取位置就可以了,祝你好运了!
支持常见的ANSI、UTF-8、UTF-16LE、UTF-16BE这几种编码文本Option Explicit'mTextUTF.bas
'模块:UTF文本文件访问
'作者:zyl910
'版本:1.0
'日期:2006-1-23
'== 说明 ===================================================
'支持Unicode编码的文本文件读写。暂时支持ANSI、UTF-8、UTF-16LE、UTF-16BE这几种编码文本
'== 更新记录 ===============================================
'[V1.0] 2006-1-23
'1.支持最常见的ANSI、UTF-8、UTF-16LE、UTF-16BE这几种编码文本'## 编译预处理常数 #########################################
'== 全局常数 ===============================================
'IncludeAPILib:引用了API库,此时不需要手动写API声明'## API ####################################################
#If IncludeAPILib = 0 Then
'== File ===================================================
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Long) As Long
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Long) As Long
Private Declare Function GetFileSize Lib "kernel32" (ByVal hFile As Long, lpFileSizeHigh As Long) As Long
Private Declare Function SetFilePointer Lib "kernel32" (ByVal hFile As Long, ByVal lDistanceToMove As Long, lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As LongPrivate Const INVALID_HANDLE_VALUE = -1Private Const GENERIC_READ = &H80000000
Private Const GENERIC_WRITE = &H40000000Private Const FILE_SHARE_READ = &H1
Private Const FILE_SHARE_WRITE = &H2Private Const CREATE_NEW = 1
Private Const CREATE_ALWAYS = 2
Private Const OPEN_EXISTING = 3
Private Const OPEN_ALWAYS = 4
Private Const TRUNCATE_EXISTING = 5Private Const FILE_ATTRIBUTE_NORMAL = &H80Private Const FILE_BEGIN = 0
Private Const FILE_CURRENT = 1
Private Const FILE_END = 2
'== Unicode ================================================Private Declare Function MultiByteToWideChar Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, ByRef lpMultiByteStr As Any, ByVal cchMultiByte As Long, ByRef lpWideCharStr As Any, ByVal cchWideChar As Long) As Long
Private Declare Function WideCharToMultiByte Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, ByRef lpWideCharStr As Any, ByVal cchWideChar As Long, ByRef lpMultiByteStr As Any, ByVal cchMultiByte As Long, ByRef lpDefaultChar As Any, ByVal lpUsedDefaultChar As Long) As LongPrivate Const CP_UTF8 As Long = 65001#End If'###########################################################'Unicode编码格式
Public Enum UnicodeEncodeFormat
UEF_ANSI = 0 'ANSI+DBCS
UEF_UTF8 'UTF-8
UEF_UTF16LE 'UTF-16LE
UEF_UTF16BE 'UTF-16BE
UEF_UTF32LE 'UTF-32LE
UEF_UTF32BE 'UTF-32BE
UEF_Auto = -1 '自动识别编码
'隐藏项目
[_UEF_Min] = UEF_ANSI
[_UEF_Max] = UEF_UTF32BE
End Enum'ANSI+DBCS方式的文本所使用的代码页。默认为0,表示使用系统当前代码页。可以利用该参数实现读取其他代码编码的文本,比如想在 简体中文平台下 读取 繁体中文平台生成的txt,就将它设为950
Public UEFCodePage As Long'判断BOM
'返回值:BOM所占字节
'dwFirst:[in]文件最开始的4个字节
'fmt:[out]返回编码类型
Public Function UEFCheckBOM(ByVal dwFirst As Long, ByRef fmt As UnicodeEncodeFormat) As Long
If dwFirst = &HFEFF& Then
fmt = UEF_UTF32LE
UEFCheckBOM = 4
ElseIf dwFirst = &HFFFE0000 Then
fmt = UEF_UTF32BE
UEFCheckBOM = 4
ElseIf (dwFirst And &HFFFF&) = &HFEFF& Then
fmt = UEF_UTF16LE
UEFCheckBOM = 2
ElseIf (dwFirst And &HFFFF&) = &HFFFE& Then
fmt = UEF_UTF16BE
UEFCheckBOM = 2
ElseIf (dwFirst And &HFFFFFF) = &HBFBBEF Then
fmt = UEF_UTF8
UEFCheckBOM = 3
Else
fmt = UEF_ANSI
UEFCheckBOM = 0
End If
End Function'生成BOM
'返回值:BOM所占字节
'fmt:[in]编码类型
'dwFirst:[out]文件最开始的4个字节
Public Function UEFMakeBOM(ByVal fmt As UnicodeEncodeFormat, ByRef dwFirst As Long) As Long
Select Case fmt
Case UEF_UTF8
dwFirst = &HBFBBEF
UEFMakeBOM = 3
Case UEF_UTF16LE
dwFirst = &HFEFF&
UEFMakeBOM = 2
Case UEF_UTF16BE
dwFirst = &HFFFE&
UEFMakeBOM = 2
Case UEF_UTF32LE
dwFirst = &HFEFF&
UEFMakeBOM = 4
Case UEF_UTF32BE
dwFirst = &HFFFE0000
UEFMakeBOM = 4
Case Else
dwFirst = 0
UEFMakeBOM = 0
End Select
End Function'判断文本文件的编码类型
'返回值:编码类型。文件无法打开时,返回UEF_Auto
'FileName:文件名
Public Function UEFCheckTextFileFormat(ByVal FileName As String) As UnicodeEncodeFormat
Dim hFile As Long
Dim dwFirst As Long
Dim nNumRead As Long
'打开文件
hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, ByVal 0&)
If INVALID_HANDLE_VALUE = hFile Then '文件无法打开
UEFCheckTextFileFormat = UEF_Auto
Exit Function
End If
'判断BOM
dwFirst = 0
Call ReadFile(hFile, dwFirst, 4, nNumRead, ByVal 0&)
nNumRead = UEFCheckBOM(dwFirst, UEFCheckTextFileFormat)
'Debug.Print nNumRead
'关闭文件
Call CloseHandle(hFile)
End Function
'读取文本文件
'返回值:读取的文本。返回vbNullString表示文件无法打开
'FileName:[in]文件名
'fmt:[in,out]使用何种文本编码格式来读取文本。为UEF_Auto时表示自动判断,且在fmt参数返回文本所用编码格式
Public Function UEFLoadTextFile(ByVal FileName As String, Optional ByRef fmt As UnicodeEncodeFormat = UEF_Auto) As String
Dim hFile As Long
Dim nFileSize As Long
Dim nNumRead As Long
Dim dwFirst As Long
Dim CurFmt As UnicodeEncodeFormat
Dim cbBOM As Long
Dim cbTextData As Long
Dim CurCP As Long
Dim byBuf() As Byte
Dim cchStr As Long
Dim I As Long
Dim byTemp As Byte
'判断fmt范围
If fmt <> UEF_Auto Then
If fmt < [_UEF_Min] Or fmt > [_UEF_Max] Then
GoTo FunEnd
End If
End If
'打开文件
hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, ByVal 0&)
If INVALID_HANDLE_VALUE = hFile Then '文件无法打开
GoTo FunEnd
End If
'判断文件大小
nFileSize = GetFileSize(hFile, nNumRead)
If nNumRead <> 0 Then '超过4GB
GoTo FreeHandle
End If
If nFileSize < 0 Then '超过2GB
GoTo FreeHandle
End If
'判断BOM
dwFirst = 0
Call ReadFile(hFile, dwFirst, 4, nNumRead, ByVal 0&)
cbBOM = UEFCheckBOM(dwFirst, CurFmt)
'恢复文件指针
If fmt = UEF_Auto Then '自动判断
fmt = CurFmt
'cbBOM = cbBOM
Else '手动设置编码
If fmt = CurFmt Then '若编码相同,则忽略BOM标记
'cbBOM = cbBOM
Else '编码不同,那么都是数据
cbBOM = 0
End If
End If
Call SetFilePointer(hFile, cbBOM, ByVal 0&, FILE_BEGIN)
cbTextData = nFileSize - cbBOM
'读取数据
UEFLoadTextFile = ""
Select Case fmt
Case UEF_ANSI, UEF_UTF8
'判断应使用的CodePage
CurCP = IIf(fmt = UEF_UTF8, CP_UTF8, UEFCodePage)
'分配缓冲区
On Error GoTo FreeHandle
ReDim byBuf(0 To cbTextData - 1)
On Error GoTo 0
'读取数据
nNumRead = 0
Call ReadFile(hFile, byBuf(0), cbTextData, nNumRead, ByVal 0&)
'取得Unicode文本长度
cchStr = MultiByteToWideChar(CurCP, 0, byBuf(0), nNumRead, ByVal 0&, ByVal 0&)
If cchStr > 0 Then
'分配字符串空间
On Error GoTo FreeHandle
UEFLoadTextFile = String$(cchStr, 0)
On Error GoTo 0
'取得文本
cchStr = MultiByteToWideChar(CurCP, 0, byBuf(0), nNumRead, ByVal StrPtr(UEFLoadTextFile), cchStr + 1)
End If
Case UEF_UTF16LE
cchStr = (cbTextData + 1) \ 2
'分配字符串空间
On Error GoTo FreeHandle
UEFLoadTextFile = String$(cchStr, 0)
On Error GoTo 0
'取得文本
nNumRead = 0
Call ReadFile(hFile, ByVal StrPtr(UEFLoadTextFile), cbTextData, nNumRead, ByVal 0&)
'修正文本长度
cchStr = (nNumRead + 1) \ 2
If cchStr > 0 Then
If Len(UEFLoadTextFile) > cchStr Then
UEFLoadTextFile = Left$(UEFLoadTextFile, cchStr)
End If
Else
UEFLoadTextFile = ""
End If
Case UEF_UTF16BE
'分配缓冲区
On Error GoTo FreeHandle
ReDim byBuf(0 To cbTextData - 1)
On Error GoTo 0
'读取数据
nNumRead = 0
Call ReadFile(hFile, byBuf(0), cbTextData, nNumRead, ByVal 0&)
If nNumRead > 0 Then
'隔两字节翻转相邻字节
For I = 0 To nNumRead - 1 - 1 Step 2 '再-1是为了避免最后多出的那个字节
byTemp = byBuf(I)
byBuf(I) = byBuf(I + 1)
byBuf(I + 1) = byTemp
Next I
'取得文本
UEFLoadTextFile = byBuf 'VB允许String中的字符串数据与Byte数组直接转换
End If
Case UEF_UTF32LE
UEFLoadTextFile = vbNullString '暂时不支持
Case UEF_UTF32BE
UEFLoadTextFile = vbNullString '暂时不支持
Case Else
Debug.Assert False
End Select
FreeHandle:
'关闭文件
Call CloseHandle(hFile)
FunEnd:
End Function
'保存文本文件
'返回值:是否成功
'FileName:[in]文件名
'sText:[in]欲输出的文本
'IsAppend:[in]是否是添加方式
'fmt:[in,out]使用何种文本编码格式来存储文本。当IsAppend=True时允许UEF_Auto自动判断,且在fmt参数返回文本所用编码格式
'DefFmt:[in]当使用添加模式时,若文件不存在且fmt = UEF_Auto时应使用的编码格式
Public Function UEFSaveTextFile(ByVal FileName As String, _
ByRef sText As String, Optional ByVal IsAppend As Boolean = False, _
Optional ByRef fmt As UnicodeEncodeFormat = UEF_Auto, Optional ByVal DefFmt As UnicodeEncodeFormat = UEF_ANSI) As Boolean
Dim hFile As Long
Dim nFileSize As Long
Dim nNumRead As Long
Dim dwFirst As Long
Dim cbBOM As Long
Dim CurCP As Long
Dim byBuf() As Byte
Dim cbBuf As Long
Dim I As Long
Dim byTemp As Byte
'判断fmt范围
If IsAppend And (fmt = UEF_Auto) Then
Else
If fmt < [_UEF_Min] Or fmt > [_UEF_Max] Then
GoTo FunEnd
End If
End If
'打开文件
hFile = CreateFile(FileName, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, IIf(IsAppend, OPEN_ALWAYS, CREATE_ALWAYS), FILE_ATTRIBUTE_NORMAL, ByVal 0&)
If INVALID_HANDLE_VALUE = hFile Then '文件无法打开
GoTo FunEnd
End If
'判断文件大小
nFileSize = GetFileSize(hFile, nNumRead)
If nFileSize = 0 And nNumRead = 0 Then '文件大小为0字节
IsAppend = False '此时需要写BOM标志
If fmt = UEF_Auto Then fmt = DefFmt
End If
'判断BOM
If IsAppend And (fmt = UEF_Auto) Then
dwFirst = 0
Call ReadFile(hFile, dwFirst, 4, nNumRead, ByVal 0&)
cbBOM = UEFCheckBOM(dwFirst, fmt)
ElseIf IsAppend = False Then
cbBOM = UEFMakeBOM(fmt, dwFirst)
End If
'文件指针定位
Call SetFilePointer(hFile, 0, ByVal 0&, IIf(IsAppend, FILE_END, FILE_BEGIN))
'写BOM
If IsAppend = False Then
If cbBOM > 0 Then
Call WriteFile(hFile, dwFirst, cbBOM, nNumRead, ByVal 0&)
End If
End If
'写文本数据
If Len(sText) > 0 Then
Select Case fmt
Case UEF_ANSI, UEF_UTF8
'判断应使用的CodePage
CurCP = IIf(fmt = UEF_UTF8, CP_UTF8, UEFCodePage)
'取得缓冲区大小
cbBuf = WideCharToMultiByte(CurCP, 0, ByVal StrPtr(sText), Len(sText), ByVal 0&, 0, ByVal 0&, ByVal 0&)
If cbBuf > 0 Then
'分配缓冲区
On Error GoTo FreeHandle
ReDim byBuf(0 To cbBuf)
On Error GoTo 0
'转换文本
cbBuf = WideCharToMultiByte(CurCP, 0, ByVal StrPtr(sText), Len(sText), byBuf(0), cbBuf + 1, ByVal 0&, ByVal 0&)
'写文件
Call WriteFile(hFile, byBuf(0), cbBuf, nNumRead, ByVal 0&)
UEFSaveTextFile = True
End If
Case UEF_UTF16LE
'写文件
Call WriteFile(hFile, ByVal StrPtr(sText), LenB(sText), nNumRead, ByVal 0&)
UEFSaveTextFile = True
Case UEF_UTF16BE
'将字符串中的数据复制到byBuf
On Error GoTo FreeHandle
byBuf = sText
On Error GoTo 0
cbBuf = UBound(byBuf) - LBound(byBuf) + 1
'隔两字节翻转相邻字节
For I = 0 To cbBuf - 1 - 1 Step 2 '再-1是为了避免最后多出的那个字节
byTemp = byBuf(I)
byBuf(I) = byBuf(I + 1)
byBuf(I + 1) = byTemp
Next I
'写文件
Call WriteFile(hFile, byBuf(0), cbBuf, nNumRead, ByVal 0&)
UEFSaveTextFile = True
Case UEF_UTF32LE
UEFSaveTextFile = False '暂时不支持
Case UEF_UTF32BE
UEFSaveTextFile = False '暂时不支持
Case Else
Debug.Assert False
End Select
Else
UEFSaveTextFile = True
End If
FreeHandle:
'关闭文件
Call CloseHandle(hFile)
FunEnd:
End Function
现在本文编码技术发展飞快GB2312-1980标准在1993年被GB13000-1993代替
GB13000-1993也在2000年被GB18030-2000代替
ASCII?!已经在坟墓里不知道烂了多久了
中国80年代的老教材早该改版了从VB4开始
VB的String就是Unicode格式了
准确点来说是UTF-16LE编码
很是还有很多人受老教材的影响,还是以为英文1字节、中文2字节,这是根本错误的