GetPrivateProfileString和LEFT综合的问题
[ABC]
DEF=中华人民共和国
有时DEF=中华人ABC民共和国
有时DEF=ABCDEFG
如果才能不管键值是单字节还是双字节都能正确读取.
用LEFT取得的数据不是后面有chr(0)的字符就是有些是乱码.
n = GetPrivateProfileString("ABC", "DEF", "123", keykey, 256, App.Path & "\setup.ini")
str = LeftB(keykey, n)
问题点数:30、回复次数:9Top
1 楼cindytsai(笨笨的蔡鸟)回复于 2005-01-01 12:23:41 得分 3
帮顶一下Top
2 楼asmgirl(过期菜鸟)回复于 2005-01-01 13:15:50 得分 3
学习Top
3 楼jautomn(Oce@n Chu)回复于 2005-01-01 14:49:30 得分 0
太好了,自己试出来了,分享
abc = StrConv(LeftB(StrConv(keykey, vbFromUnicode), n), vbUnicode)
Top
4 楼VBAHZ(凌云(E文词汇量580))回复于 2005-01-01 15:20:01 得分 8
那是因为你没有事先给keykey分配内存空间(API就是这样死板)
keykey = String(256, 0)
N = GetPrivateProfileString("ABC", "DEF", "123", keykey, 256, App.Path & "\setup.ini")
str = LeftB(keykey, N)
===============
str=中华人民共和国
另外,API的定义需要注意:
Private Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" _
(ByVal lpApplicationName As String, ByVal lpKeyName As Any, _
ByVal lpDefault As String, ByVal lpReturnedString As String, _
ByVal nSize As Long, ByVal lpFileName As String) As Long
Top
5 楼homezj(小吉)回复于 2005-01-01 20:50:26 得分 8
呵呵,这种问题在字符串中有中英文混合的情况下,不可避免,因为API返回的是ANSI字符长度,这个长度比Len的取值长,比LenB的取值短。
StrConv是常用的办法,不过这种方法,还是有一点小局限性:这也是我以前无意中发现的。
当用户是中文系统,可控制面板的区域设置中,却指定了一个非中国区域,如:美国。这在国外华侨中非常普遍,当然还有一些D版XP也是这样。
你会发现这样的系统中,虽然看不出中文显示有什么异样,但用StrConv处理过的中文就会是乱码,因为其对非Unicode编码的默认字符集不是GB。
若想兼容性更好,最好放弃API的返回值,自己判断长度,我给你一个通用函数。
Public Function GetIni(sec As String, key As String, file As String, Optional BufLen As Long = 1024) As String
Dim i As Long, s As String, j As Long
s = Space(BufLen)
i = GetPrivateProfileString(sec, key, "", s, BufLen, file)
If i > 0 Then
s = replace(RTrim(s), Chr(0) & Chr(0), "")
If Right(s, 1) = Chr(0) Then
GetIni = Left(s, Len(s) - 1)
Else
GetIni = s
End If
End If
End Function
Top
6 楼VBAHZ(凌云(E文词汇量580))回复于 2005-01-01 21:38:48 得分 8
效率太低,最坏的情况(在执行API后)从源码来看有15个步骤6行语句:
1、判断I值
2-3、转换字符Chr(0) Chr(0)
4、合并字串Chr(0)&Chr(0)
5、RTrim(S)
6、""(抄来的:""这里VB做了很多工作,首先,VB在编译时,把””当成了一个常量,它必须为这个空字符串内部申请一个变量。当EXE文件加载后,也得把它设定一个地址,虽然它什么都不代表
是一个 00 00 00 00 00 00 这样的字符串,它需要6个字节(四个头字节和2个尾字节)
然后当看到这句时再把第五个字节的地址值传回。所以,虽然你只是信手写了一个””,结果VB多作了很多工作。6个字节虽然不多,但是在一个大工程里,大家都到处写“”,那么也是很可观的一笔开销。)
7、替换(个人认为这是最没效率的一句,既然结果我们不会要Chr(0)的字符,替换它干啥?况且不兼容VB5)
8、赋值回S
9、Right(S,1)
10、转换字符Chr(0)
11、比较是否为Chr(0)
12、Len(S)
13、减一
14、Left(S,)
15、GetIni赋值
虽然俺不懂汇编,但听说VB中效率最低的就是字符串操作,所以应该尽量减少吧?俺认为能减少源码的执行步骤,最终生成的代码总是效率高一点吧?
API认为Chr(0)是字符串的终结,而VB中也不会显示Chr(0),INI文本中不应该出现Chr(0)
那在调用前就申明为Chr(0)
s =String(BufLen,0)
I=.....
GetINI=Left(S, InStr(S,vbNullChar) - 1)
就这一句(4个步骤)完事!
Top
7 楼jautomn(Oce@n Chu)回复于 2005-01-17 13:09:14 得分 0
我都看不懂,谢谢大家的关心,都加分,分是少了点,一点心意。问题已解决了。就用这个。
abc = StrConv(LeftB(StrConv(keykey, vbFromUnicode), n), vbUnicode)Top
8 楼homezj(小吉)回复于 2005-01-17 14:24:52 得分 0
今天才看到这个贴子!
To:VBAHZ(凌云(E文词汇量580))
很高兴有人对那段代码效率提出看法,我也估计很多人会对那个函数不理解。Left(S, InStr(S,vbNullChar) - 1)是提取API返回值最常用方法,我当然不会不知道,你把问题想简单了!
Ini文件有个很重要的功能,就是返回一个段下的全部键名,而多个键名就是用chr(0)分割的,若用查找第一个Chr(0)的办法,是得不到多个值的。这种情况还常见于,OpenFile对话框返回多个值。
所以函数中只能去掉返回值的未尾所有的Chr(0),而不能去串中间的Chr(0)。这类问题见多了,就会理解的。Top
9 楼VBAHZ(凌云(E文词汇量580))回复于 2005-01-20 03:05:10 得分 0
今天才看到这个贴子!
To:homezj(小吉)
很高兴有人对那段代码提出看法,你把问题想复杂了!
用INI文件,几乎有90%以上的时候是要返回单个键的值,(当然,返回全部键还是要用到的,这时候往往要大批量的处理,所以效率更重要)
API函数基本以C来写的,所以大多以CHR(0)分割,但这不适合VB,VB的字符操作就是慢!若返回大段的字符再分割CHR(0)就更慢了,还不如自定义函数,找到段名,一次读入全部文本数据快。(懒的写代码的人除外,那叫——用户)
接下来,若要在Text中显示,直接转过去就行,无需再拼接回车换行符,若要分解,也只不过以vbCrlf来分解而已。
要知道INI文件本身就是定义严格的以回车换行符分割的文本行文件,跳过API的载入读取分解拼接(重新以Chr(0)拼接)过程,经过实践,用VB自己的Line Input能更高效率的处理它。(指大段的文本行)
Top




