Unicode 如何在日本机器上使用zlib?

Unicode 如何在日本机器上使用zlib?,unicode,vb6,internationalization,zlib,Unicode,Vb6,Internationalization,Zlib,我试图通过使用压缩字符串(我已经在zlib的当前1.2.3版本和zlib 1.1.3版本中尝试了这段代码)。我的代码工作正常,除非在日本机器上运行。压缩文件后,我将对其进行加密。解密成功,但对解压缩的调用返回-3(Z_DATA_ERROR,表示输入数据已损坏)。由于没有记录错误,我知道没有抛出异常,压缩函数返回0(Z_OK,这意味着它工作正常) 因此,我怀疑问题在于,sCompressed字符串在“sCompressed=Left(sCompressed,lcompressedlen)”行或“e

我试图通过使用压缩字符串(我已经在zlib的当前1.2.3版本和zlib 1.1.3版本中尝试了这段代码)。我的代码工作正常,除非在日本机器上运行。压缩文件后,我将对其进行加密。解密成功,但对解压缩的调用返回-3(
Z_DATA_ERROR
,表示输入数据已损坏)。由于没有记录错误,我知道没有抛出异常,压缩函数返回0(
Z_OK
,这意味着它工作正常)

因此,我怀疑问题在于,
sCompressed
字符串在“
sCompressed=Left(sCompressed,lcompressedlen)
”行或“
encryptedData.Content=sCompressed
”行上正在丢失完整性,VB6可能在调用
compress
期间对
sCompressed
的内容做了一些愚蠢的帮助。我知道这个函数的返回值以后不会被破坏,因为那样会破坏解密,而解密工作正常

Public Function EncryptString(ByVal Definition As String) As String
On Error GoTo ErrorHandler
    Dim encryptedData As New CAPICOM.encryptedData
    encryptedData.SetSecret KEY_CONST
    Dim lStringLen As Long
    Dim lcompressedlen As Long
    Dim sCompressed As String
    Dim lReturn As Long
    Dim tstpost As String
    lStringLen = Len(Definition)
    lcompressedlen = (lStringLen * 1.01) + 13
    sCompressed = Space(lcompressedlen)
    lReturn = compress(sCompressed, lcompressedlen, Definition, lStringLen)
    If lReturn <> 0 Then
        sCompressed = "Error: " & CStr(lReturn)
        '<LOG ERROR>'
    Else
        sCompressed = Left(sCompressed, lcompressedlen)
    End If
    encryptedData.Content = sCompressed
    encryptedData.Algorithm.Name = CAPICOM_ENCRYPTION_ALGORITHM_3DES
    EncryptXmlString = encryptedData.Encrypt
Exit Function
ErrorHandler:
    '<LOG ERROR>'
    Resume Next
End Function
Public函数EncryptString(ByVal定义为String)作为String
关于错误转到错误处理程序
将encryptedData设置为新CAPICOM.encryptedData
encryptedData.SetSecret KEY_CONST
暗淡的蓝色和蓝色一样长
暗淡的lcompressedlen与长
被压缩成细绳的暗淡的皱褶
变暗,变长
将tstpost设置为字符串
lStringLen=Len(定义)
lcompressedlen=(lStringLen*1.01)+13
sCompressed=空间(lcompressedlen)
lReturn=压缩(sCompressed、lcompressedlen、Definition、lStringLen)
如果lReturn为0,则
sCompressed=“错误:”&CStr(lReturn)
''
其他的
sCompressed=左(sCompressed,lcompressedlen)
如果结束
encryptedData.Content=sCompressed
encryptedData.Algorithm.Name=CAPICOM\u ENCRYPTION\u Algorithm\u 3DES
EncryptXmlString=encryptedData.Encrypt
退出功能
错误处理程序:
''
下一步继续
端函数
结论:

最后,我让程序给出一条错误消息,如果在具有可疑字符集的机器上运行,则退出。很可能在一些设置中仍然存在此错误,并且在触发错误的某些设置中也可能不存在此错误。然而,由于目标受众是说英语的人,通过土耳其测试并不重要,因此不足以证明在这方面花费更多时间。

当你想通过字节数组时,是否停止使用字符串

当然,当您像这里一样使用字符串时,您将获得自动的ANSI转换和数据重新压缩。

Bob是。这些只是我对他的回答的脚注。请注意,我对zlib完全不熟悉-我假设您正在使用
声明
for
压缩
调用DLL

使用字符串而不是字节数组并不意味着可以避免ANSI转换。它通常只是意味着VB6隐式地进行转换,而您无法控制它——例如,当您使用
Declare
语句调用DLL并传递字符串时

压缩返回的神奇字节序列可能不是日文代码页上的有效“ANSI”字符串。某些字符序列在该代码页的上未定义。如果使用
Declare
语句调用DLL,并希望将字符串返回到sCompressed中,则该DLL最好将有效的“ANSI”字符串写入相应的缓冲区。如果它写入无效的字节序列,则可能发生任何情况。你在汉语(936和950)和韩语(949)方面也会有困难

您所描述的可能会发生:当
compress
返回无效的字节序列时,可能会将其转换为“Unicode”字符串,而不会报告错误—可能是与字节序列的第一部分匹配的截断Unicode字符串。然后,当您稍后尝试解压缩时,该Unicode字符串将转换回ANSI字符串,并且它与您开始的原始字节序列不匹配。这不可能匹配。在代码页932上,没有可能的Unicode字符串会转换为无效字符串的字节序列形式的“ANSI”字符串

这里有一些关于VB6实现Unicode的可怕的混乱的更多信息:来自Michael Kaplan的优秀著作


我还怀疑您可能混淆了字符串中的字符数和它在ANSI表示中占用的字节数(我怀疑
lStringLen
lcompressdlen
)。同样,日语是一个双字节字符集,因此对于N个字符,ANSI字符串可能最多占用2*N个字节

使用字节数组很烦人。执行strconv复制(转换为ansi)并不完美,执行copymemory包含多余的null。如果绝对必须使用字符串,请使用StrPtr,这样运行时就不会将它们转换为ansi和back(此外,缓冲区长度必须加倍),避免字节数组并不意味着避免ansi转换。它通常只是意味着VB6隐式地执行它——例如,当您通过Declare调用DLL并传递字符串时。@MarkJ:我旁边有一本卡普兰书的死树副本。事实上,这是我桌上唯一的一本书。好极了!那样的话你就没事了。