VB快速查找大型文件中包含的字符串

前端之家收集整理的这篇文章主要介绍了VB快速查找大型文件中包含的字符串前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。


关于查找大型文件中包含的字符串,一般都把文件内容读入到内存,然后在内存里进行比较,却不知这种办法有一个致命的弱点,那就是由于大量的内存申请和释放导致的内存颠簸,会使系统性能下降,严重影响了查找的速度。特别是在递归中对多个文件进行查找时,这个问题会更加突出,有时甚至会导致VB程序挂掉。为避免这种情况,同时加快大型文件中字符串的查找速度,俺基于内存影射文件和VB模拟指针技术,编写了一个通用字符串查找函数

首先,先看一个普通的查找函数

  1. '使用普通方式查找文件中包含的字符串(返回字符位置)@H_403_30@
  2. Private@H_403_37@FunctionFindText(@H_403_37@ByValstrFileName@H_403_37@As@H_403_37@String,@H_403_37@ByValstrText@H_403_37@String)@H_403_37@Long@H_403_30@
  3. @H_403_37@Dimfn@H_403_37@Integer@H_403_30@
  4. DimstrFileText@H_403_37@String@H_403_30@
  5. @H_403_30@
  6. DimMyString,MyNumber@H_403_30@
  7. DimS@H_403_37@String@H_403_30@
  8. @H_403_30@
  9. fn=FreeFile()@H_403_30@
  10. OpenstrFileName@H_403_37@ForBinary@H_403_37@As#fn'打开输入文件@H_403_30@
  11. strFileText=Input(LOF(fn),fn)@H_403_30@
  12. Close#fn@H_403_30@
  13. FindText=InStr(strFileText,strText)@H_403_30@
  14. End@H_403_37@Function@H_403_30@

用一个400K的文本进行测试,测试次数为20次,测试代码如下:

copy

    SubMain()@H_403_30@
  1. DimlStartTime '比较两个方式的运行速度@H_403_30@
  2. lStartTime=GetTickCount@H_403_30@
  3. CallFindText("G:/Inst/小说/沧海凤歌.txt","打打秋风")'此返回值为字符位置@H_403_30@
  4. Debug.PrintGetTickCount-lStartTime@H_403_30@
  5. Sub@H_403_30@

根据测试结果,最大耗时为2050ms,最小耗时为890ms,平均在950ms左右。

然后,我看再看一下基于内存影射和模拟指针的查找函数代码如下:

copy

    OptionExplicit@H_403_30@
  1. Declare@H_403_37@SubCopyMemory@H_403_37@Lib"kernel32"@H_403_37@Alias"RtlMoveMemory"(Destination@H_403_37@AsAny,Source@H_403_37@ByValLength@H_403_37@Long)@H_403_30@
  2. FunctionCreateFile@H_403_37@Alias"CreateFileA"(@H_403_37@ByVallpFileName@H_403_37@ByValdwDesiredAccess@H_403_37@Long,153); background-color:inherit; font-weight:bold">ByValdwShareMode@H_403_37@ByVallpSecurityAttributes@H_403_37@ByValdwCreationDisposition@H_403_37@ByValdwFlagsAndAttributes@H_403_37@ByValhTemplateFile@H_403_37@Long)@H_403_37@FunctionCloseHandle@H_403_37@Lib"kernel32"(@H_403_37@ByValhObject@H_403_37@Long@H_403_30@
  3. FunctionGetFileSize@H_403_37@ByValhFile403_37@ConstGENERIC_READ=&H80000000@H_403_30@
  4. ConstGENERIC_WRITE=&H40000000@H_403_30@
  5. ConstOPEN_EXISTING=3@H_403_30@
  6. ConstFILE_SHARE_READ=&H1@H_403_30@
  7. ConstFILE_SHARE_WRITE=&H2@H_403_30@
  8. ConstFILE_ATTRIBUTE_NORMAL=&H80@H_403_30@
  9. ConstFILE_ATTRIBUTE_ARCHIVE=&H20@H_403_30@
  10. ConstFILE_ATTRIBUTE_READONLY=&H1@H_403_30@
  11. ConstFILE_ATTRIBUTE_HIDDEN=&H2@H_403_30@
  12. ConstFILE_ATTRIBUTE_SYSTEM=&H4@H_403_30@
  13. FunctionCreateFileMapping@H_403_37@Alias"CreateFileMappingA"(@H_403_37@ByVallpFileMappigAttributes@H_403_37@ByValflProtect@H_403_37@ByValdwMaximumSizeHigh@H_403_37@ByValdwMaximumSizeLow@H_403_37@ByVallpName@H_403_37@FunctionMapViewOfFile@H_403_37@ByValhFileMappingObject@H_403_37@ByValdwFileOffsetHigh@H_403_37@ByValdwFileOffsetLow@H_403_37@ByValdwNumberOfBytesToMap@H_403_37@FunctionUnmapViewOfFile@H_403_37@Lib"kernel32"(lpBaseAddress@H_403_37@AsAny)@H_403_37@ConstPAGE_READWRITE=&H4@H_403_30@
  14. ConstFILE_MAP_READ=&H4@H_403_30@
  15. FunctionVarPtrArray@H_403_37@Lib"msvbvm60.dll"@H_403_37@Alias"VarPtr"(Ptr()@H_403_37@PrivateTypeSAFEARRAYBOUND@H_403_30@
  16. cElements lLbound@H_403_37@EndType@H_403_30@
  17. PrivateTypeSAFEARRAY1D@H_403_30@
  18. cDims@H_403_37@Integer@H_403_30@
  19. fFeatures cbElements clocks pvData rgsabound(0)@H_403_37@AsSAFEARRAYBOUND@H_403_30@
  20. '使用内存映射方式查找大型文件中包含的字符串@H_403_30@
  21. FunctionFindTextInFile(@H_403_37@DimhFile403_37@DimnFileSize403_37@Byte@H_403_30@
  22. DimppSA403_37@DimtagNewSA@H_403_37@AsSAFEARRAY1D,tagOldSA@H_403_37@AsSAFEARRAY1D@H_403_30@
  23. hFile=CreateFile(strFileName,_@H_403_30@
  24. GENERIC_READ@H_403_37@OrGENERIC_WRITE,_@H_403_30@
  25. FILE_SHARE_READ@H_403_37@OrFILE_SHARE_WRITE,_@H_403_30@
  26. 0,_@H_403_30@
  27. OPEN_EXISTING,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important; list-style-position:outside!important"> FILE_ATTRIBUTE_NORMAL@H_403_37@OrFILE_ATTRIBUTE_ARCHIVE@H_403_37@OrFILE_ATTRIBUTE_READONLY@H_403_37@Or_@H_403_30@
  28. FILE_ATTRIBUTE_HIDDEN@H_403_37@OrFILE_ATTRIBUTE_SYSTEM,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important; list-style-position:outside!important"> 0)'打开文件@H_403_30@
  29. IfhFile<>0@H_403_37@Then@H_403_30@
  30. nFileSize=GetFileSize(hFile,@H_403_37@ByVal0&)'获得文件大小@H_403_30@
  31. hFileMap=CreateFileMapping(hFile,PAGE_READWRITE,vbNullString)'创建文件映射对象@H_403_30@
  32. lpszFileText=MapViewOfFile(hFileMap,FILE_MAP_READ,0)'将映射对象映射到进程内部的地址空间@H_403_30@
  33. ReDimpbFileText(0)'初始化数组@H_403_30@
  34. ppSA=VarPtrArray(pbFileText)'获得指向SAFEARRAY的指针的指针@H_403_30@
  35. CopyMemorypSA,153); background-color:inherit; font-weight:bold">ByValppSA,4'获得指向SAFEARRAY的指针@H_403_30@
  36. CopyMemorytagOldSA,153); background-color:inherit; font-weight:bold">ByValpSA,Len(tagOldSA)'保存原来的SAFEARRAY成员信息@H_403_30@
  37. CopyMemorytagNewSA,tagOldSA,Len(tagNewSA)'复制SAFEARRAY成员信息@H_403_30@
  38. tagNewSA.rgsabound(0).cElements=nFileSize'修改数组元素个数@H_403_30@
  39. tagNewSA.pvData=lpszFileText'修改数组数据地址@H_403_30@
  40. CopyMemory'将映射后的数据地址绑定至数组@H_403_30@
  41. FindTextInFile=InStr(pbFileText,StrConv(strText,vbFromUnicode))'查找子字符串位置@H_403_30@
  42. '恢复数组的SAFEARRAY结构成员信息@H_403_30@
  43. ErasepbFileText'删除数组@H_403_30@
  44. UnmapViewOfFilelpszFileText'取消地址映射@H_403_30@
  45. CloseHandlehFileMap'关闭文件映射对象的句柄@H_403_30@
  46. If@H_403_30@
  47. CloseHandlehFile'关闭文件@H_403_30@
  48. 这个函数明显比上一个函数复杂得到,按理说,它运行速度肯定相应的要慢一些,咱们先不下定论,还是经过测试后再说吧,测试代码如下:

    调用代码如下:

    copy

    lStartTime=GetTickCount@H_403_30@
  1. CallFindTextInFile("G:/Inst/小说/沧海凤歌.txt",0); background-color:inherit">'此返回值为字节位置@H_403_30@
  2. Debug.PrintGetTickCount-lStartTime@H_403_30@
  3. 使用了同一个文本文件,同样测试了20次,嘿,第二个函数最大耗时为17ms,最小耗时为0ms,平均不超过1ms,这进一步验证了我的设计初衷。

    如果你有更好的思路和建议,恳请告诉俺,俺在此表示感谢了!

    原文链接 :http://blog.csdn.net/lyserver/article/details/4106290

    猜你在找的VB相关文章