VB6:我能';我不明白这段代码为什么有效
我为这个愚蠢的问题道歉。我正在维护旧的遗留VB6代码,我有一个实际工作的函数,但我无法理解为什么它可以工作,或者为什么没有它代码就不能工作 基本上,此函数读取UTF-8文本文件并在DHTMLEdit组件中显示其内容。它的工作方式是,将整个文件读入字符串,然后使用ANSI代码页将其从双字节转换为多字节字符串,然后将其转换回双字节 使用这个复杂的机制可以使组件同时正确显示包含希伯来语、阿拉伯语、泰语和汉语的页面。不使用此代码会使文本看起来像是向下转换为ASCII码,显示字母所在的各种标点符号 我不明白的是:VB6:我能';我不明白这段代码为什么有效,vb6,Vb6,我为这个愚蠢的问题道歉。我正在维护旧的遗留VB6代码,我有一个实际工作的函数,但我无法理解为什么它可以工作,或者为什么没有它代码就不能工作 基本上,此函数读取UTF-8文本文件并在DHTMLEdit组件中显示其内容。它的工作方式是,将整个文件读入字符串,然后使用ANSI代码页将其从双字节转换为多字节字符串,然后将其转换回双字节 使用这个复杂的机制可以使组件同时正确显示包含希伯来语、阿拉伯语、泰语和汉语的页面。不使用此代码会使文本看起来像是向下转换为ASCII码,显示字母所在的各种标点符号 我不明
Private Declare Function MultiByteToWideChar Lib "kernel32" (ByVal codePage As Long, ByVal dwFlags As Long, ByVal lpMultiByteStr As Long, ByVal cchMultiByte As Long, ByVal lpWideCharStr As Long, ByVal cchWideChar As Long) As Long
Private Declare Function WideCharToMultiByte Lib "kernel32" (ByVal codePage As Long, ByVal dwFlags As Long, ByVal lpWideCharStr As Long, ByVal cchWideChar As Long, ByVal lpMultiByteStr As Long, ByVal cchMultiByte As Long, ByVal lpDefaultChar As Long, lpUsedDefaultChar As Long) As Long
Private Declare Function GetACP Lib "kernel32" () As Long
...
Open filePath For Input As #lFilePtr
Dim sInput as String
dim sResult as string
Do While Not EOF(lFilePtr)
Line Input #lFilePtr, sInput
sResult = sResult + sInput;
Loop
txtBody.DOM.Body.innerText = DecodeString(sResult, CP_UTF8);
Public Function DecodeString(ByVal strSource As String, Optional FromCodePage As Long = -1) As String
Dim strTemp As String
If strSource = vbNullString Then Exit Function
strTemp = UnicodeToAnsi(strSource, 0)
DecodeString = AnsiToUnicode(strTemp, FromCodePage)
End Function
Public Function AnsiToUnicode(ByVal strSource As String, Optional ByVal codePage As Long = -1, Optional lFlags As Long = 0) As String
Dim strBuffer As String
Dim cwch As Long
Dim pwz As Long
Dim pwzBuffer As Long
If codePage = -1 Then codePage = GetACP()
pwz = StrPtr(strSource)
cwch = MultiByteToWideChar(codePage, lFlags, pwz, -1, 0&, 0&)
strBuffer = String$(cwch + 1, vbNullChar)
pwzBuffer = StrPtr(strBuffer)
cwch = MultiByteToWideChar(codePage, lFlags, pwz, -1, pwzBuffer, Len(strBuffer))
AnsiToUnicode = Left(strBuffer, cwch - 1)
End Function
Public Function UnicodeToAnsi(ByVal strSource As String, Optional ByVal codePage As Long = -1, Optional lFlags As Long = 0) As String
Dim strBuffer As String
Dim cwch As Long
Dim pwz As Long
Dim pwzBuffer As Long
If codePage = -1 Then codePage = GetACP()
pwz = StrPtr(strSource)
cwch = WideCharToMultiByte(codePage, lFlags, pwz, -1, 0&, 0&, ByVal 0&, ByVal 0&)
strBuffer = String$(cwch + 1, vbNullChar)
pwzBuffer = StrPtr(strBuffer)
cwch = WideCharToMultiByte(codePage, lFlags, pwz, -1, pwzBuffer, Len(strBuffer), ByVal 0&, ByVal 0&)
UnicodeToAnsi = Left(strBuffer, cwch - 1)
End Function
[code]VB6/A在使用内置运算符读取/写入文件时使用隐式双向UTF16-ASCII转换
Private Declare Function MultiByteToWideChar Lib "kernel32" (ByVal codePage As Long, ByVal dwFlags As Long, ByVal lpMultiByteStr As Long, ByVal cchMultiByte As Long, ByVal lpWideCharStr As Long, ByVal cchWideChar As Long) As Long
Private Declare Function WideCharToMultiByte Lib "kernel32" (ByVal codePage As Long, ByVal dwFlags As Long, ByVal lpWideCharStr As Long, ByVal cchWideChar As Long, ByVal lpMultiByteStr As Long, ByVal cchMultiByte As Long, ByVal lpDefaultChar As Long, lpUsedDefaultChar As Long) As Long
Private Declare Function GetACP Lib "kernel32" () As Long
...
Open filePath For Input As #lFilePtr
Dim sInput as String
dim sResult as string
Do While Not EOF(lFilePtr)
Line Input #lFilePtr, sInput
sResult = sResult + sInput;
Loop
txtBody.DOM.Body.innerText = DecodeString(sResult, CP_UTF8);
Public Function DecodeString(ByVal strSource As String, Optional FromCodePage As Long = -1) As String
Dim strTemp As String
If strSource = vbNullString Then Exit Function
strTemp = UnicodeToAnsi(strSource, 0)
DecodeString = AnsiToUnicode(strTemp, FromCodePage)
End Function
Public Function AnsiToUnicode(ByVal strSource As String, Optional ByVal codePage As Long = -1, Optional lFlags As Long = 0) As String
Dim strBuffer As String
Dim cwch As Long
Dim pwz As Long
Dim pwzBuffer As Long
If codePage = -1 Then codePage = GetACP()
pwz = StrPtr(strSource)
cwch = MultiByteToWideChar(codePage, lFlags, pwz, -1, 0&, 0&)
strBuffer = String$(cwch + 1, vbNullChar)
pwzBuffer = StrPtr(strBuffer)
cwch = MultiByteToWideChar(codePage, lFlags, pwz, -1, pwzBuffer, Len(strBuffer))
AnsiToUnicode = Left(strBuffer, cwch - 1)
End Function
Public Function UnicodeToAnsi(ByVal strSource As String, Optional ByVal codePage As Long = -1, Optional lFlags As Long = 0) As String
Dim strBuffer As String
Dim cwch As Long
Dim pwz As Long
Dim pwzBuffer As Long
If codePage = -1 Then codePage = GetACP()
pwz = StrPtr(strSource)
cwch = WideCharToMultiByte(codePage, lFlags, pwz, -1, 0&, 0&, ByVal 0&, ByVal 0&)
strBuffer = String$(cwch + 1, vbNullChar)
pwzBuffer = StrPtr(strBuffer)
cwch = WideCharToMultiByte(codePage, lFlags, pwz, -1, pwzBuffer, Len(strBuffer), ByVal 0&, ByVal 0&)
UnicodeToAnsi = Left(strBuffer, cwch - 1)
End Function
行输入
使用非Unicode程序的当前系统代码页,将文件视为ASCII格式(一系列字节,每个字节代表一个字符)。读取的字符转换为UTF-16
当您以这种方式读取UTF-8文件时,得到的是一个“无效”字符串—您不能在语言中直接使用它(如果尝试,您将看到垃圾),但它包含可用的二进制数据
然后,指向该可用二进制数据的指针被传递到WideCharToMultiByte
(在UnicodeToAnsi
中),这将导致创建另一个“无效”字符串-这次它包含“ASCII”数据。这有效地恢复了VB使用行输入自动进行的转换,因为原始文件是UTF-8格式的,所以现在有一个包含UTF-8数据的“无效”字符串,尽管转换函数认为它正在转换为ASCII
指向第二个无效字符串的指针被传递到MultiByteToWideChar
(在AnsiToUnicode
中),该指针最终创建了一个可在VB中使用的有效字符串
这段代码令人困惑的地方在于string
s用于包含“无效”数据。从逻辑上讲,所有这些都应该是字节数组。我会重构代码,以二进制模式从文件中读取字节,并将数组直接传递给MultiByteToWideChar
。GSerg-你真是个天才。我有一种感觉,这是一种倒退的转变,但这对我来说毫无意义。以ASCII格式读取文件并将其转换为UTF-16?哇!关于重构,您完全正确,不幸的是,这是一个更大的类的一部分,用于读取和解析电子邮件,而Line Input命令是这个类的核心。使用字节数组重新编写所有内容将非常麻烦,效率也不高,我必须不断地来回转换。非常感谢你帮了我的忙!我相信这些信息对其他人也很有用。@user884248在该类中,您真的将无效字符串存储为一级数据吗?即,在您显示的代码中,它们仅用于创建和存储解码字符串,并且它是有效字符串,应存储为字符串。看起来你不需要来回转换。不幸的是,是的。代码读取一行,然后开始检查其内容。即使我不必来回转换,这也意味着重新编写整个类,而且我没有单元测试。到目前为止,它已经工作了,所以我宁愿保持原样。+1您已经正确地说过VB6文件编码取决于Windows代码页。在Windows文档中,这种编码通常被称为“ANSI”——这是一个误导性的术语,但它是常用的。它可能比ASCII更好。小诡辩-你说过每个字节代表一个字符,但在某些代码页上,一个字符有多个字节,例如简体中文。这让我注意到OP描述的原始代码还有另一个问题——它可能会在某些代码页中失败。在某些代码页上,UTF8字节流可能不是有效的“ANSI”字节流。