找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 6761|回复: 24

[问题求助] 【已解决】求助jscript使用adodb.stream

[复制链接]
发表于 2025-8-28 17:30:56 | 显示全部楼层 |阅读模式
本帖最后由 HalloWord 于 2025-9-2 21:20 编辑

各位大佬们,问一下
jscript使用adodb.stream

  1. var ado=WScript.CreateObject('adodb.stream');
  2. ado.open();
  3. ado.writetext('1111111');
  4. //...
复制代码
写文件时用的open方法据说是写在内存里的,这有什么限制没?比如大小限制之类的
还有怎么不写在内存,直接open一个文件,然后往里面写内容?
网上找了好久都找不到相关信息
========超华丽的分割线========
嗯嗯,winapi太难用了,而且好多东西要自己实现
想用musl libc,但是不知道支不支持windows
暂时就这样了,弄了个简单的部分读取文件并输出的exe,其他的然后交给jscript或bat再处理,编译后体积不到4k,压缩一下不到2k,将bytes弄成hex字符串输进去后再还原应该要不了多久,
祈祷不会出问题

  1. #define _USING_V140_SDK71
  2. #define UNICODE
  3. #include <windows.h>
  4. #pragma comment(lib, "kernel32")
  5. #pragma comment(lib, "shell32")
  6. #define size_of_buff (sizeof(char)*1024*64*64)

  7. int read_partial(wchar_t*,wchar_t*,long long,long long);
  8. long long atoll2(const wchar_t*);

  9. /*
  10. for 32bit winxp
  11. msvc link with /entry:mei /subsystem:console,5.01
  12. gcc and clang do not know
  13. */
  14. int mei(){
  15.   int argc;
  16.   wchar_t **argv;
  17.   argv=CommandLineToArgvW(GetCommandLineW(), &argc);
  18.   int v=-1;
  19.   if(argc<5)goto end;
  20.   long long _start=atoll2(*(argv+3));
  21.   long long _size=atoll2(*(argv+4));
  22.   if(!_size)goto end;
  23.   v=read_partial(*(argv+1),*(argv+2),_start,_size);
  24.   end:
  25.   LocalFree(argv);
  26.   return v;
  27. }

  28. int read_partial(wchar_t *file_in,wchar_t *file_out,long long read_start,long long read_size){
  29.   int v=0;
  30.   LPVOID chars_buff=VirtualAlloc(NULL,size_of_buff,MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE);
  31.   if(NULL==chars_buff)return GetLastError();

  32.   HANDLE in_file_handle=CreateFileW(file_in,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
  33.   if(INVALID_HANDLE_VALUE==in_file_handle)return 1;
  34.   HANDLE out_file_handle=CreateFileW(file_out,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
  35.   if(INVALID_HANDLE_VALUE==out_file_handle){
  36.     CloseHandle(in_file_handle);
  37.     return 2;
  38.   }
  39.   
  40.   LARGE_INTEGER _size;
  41.   _size.QuadPart=read_start;
  42.   if(!SetFilePointerEx(in_file_handle,_size,NULL,FILE_BEGIN)){
  43.     v=GetLastError();
  44.     goto end;
  45.   }
  46.   
  47.   DWORD chars_read,chars_write;
  48.   long long t=0;
  49.   while(ReadFile(in_file_handle,chars_buff,size_of_buff,&chars_read,NULL)){
  50.     if(0==chars_read)break;
  51.     t+=chars_read;
  52.     if(t>read_size){
  53.       chars_read=chars_read-(DWORD)(t-read_size);
  54.     }
  55.     if (!WriteFile(out_file_handle,chars_buff,chars_read,&chars_write,NULL)) {
  56.       v=GetLastError();
  57.       goto end;
  58.     }
  59.     if(t>read_size)break;
  60.   }
  61.   end:
  62.   CloseHandle(in_file_handle);
  63.   CloseHandle(out_file_handle);
  64.   VirtualFree(chars_buff,0,MEM_RELEASE);
  65.   return v;
  66. }

  67. long long atoll2(const wchar_t *s){
  68.   long long num=0;
  69.   int neg=0;
  70.   while(*s&&(*s<=' '))s++;
  71.   if(*s){
  72.     if(*s=='-'){neg=1;s++;}
  73.     if(*s=='+'){s++;}
  74.   }
  75.   while((*s>='0')&&(*s<='9')){
  76.     num=10*num-(*s-'0');
  77.     s++;
  78.   }
  79.   return neg?num:-num;
  80. }
复制代码

评分

参与人数 1技术 +1 收起 理由
czjt1234 + 1 感谢分享

查看全部评分

发表于 2025-8-28 18:44:57 | 显示全部楼层
本帖最后由 aloha20200628 于 2025-8-28 19:19 编辑

回复 1# HalloWord

示例代码如下(将字符串 'abc中文123' 写入输出文件 c:\abc\xyz.txt)。至于能写出多大文件,未见官方声明,自己实测吧...

  1. ads=WSH.createObject('adodb.stream'), ads.type=2, ads.charset='gb2312', ads.open(), ads.writeText('abc中文123'), ads.savetoFile('c:\\abc\\xyz.txt',2), ads.close();
复制代码
发表于 2025-8-28 19:19:20 | 显示全部楼层
经测试,ADODB.Stream支持小于4G,最大 2^32 - 1 字节的文件
但Position和Size属性是Long类型,在超过 2^31 - 1 字节的文件时不能使用

如果以文本格式读取较大的文件,则速度会很慢
实测以文本格式读取一个5M的文本文件约需要6秒
发表于 2025-8-28 19:57:54 | 显示全部楼层
ADODB.Stream 你猜为什么前缀是ADODB,用来保存数据库记录的字段的,比如一条record中某字段是个图片,那么用ADODB.Stream来读写该字段;不适合直接读写操作系统的文件;之所以用它来读写文件,是因为没有其他的COM对象可以直接读写文件流;实际上是错用;
 楼主| 发表于 2025-8-28 22:18:39 | 显示全部楼层
回复 2# aloha20200628


    感谢,自己改着测试了下,写入1.67g左右就爆内存退出了,虽然机器内存有点小,不过很明显不适合写入大文件

  1. var ado=WScript.CreateObject('adodb.stream');
  2. ado.open();
  3. for(var i=0;i<4096;i++){
  4.   var str=str+'1';
  5. }
  6. var size=0;
  7. try{
  8.   while(1){
  9.     ado.writetext(str);
  10.     WScript.echo(size+=4096);
  11.   }
  12. }catch(e){
  13.   ado.close();
  14. }
  15. //1799864320
复制代码
 楼主| 发表于 2025-8-28 22:44:38 | 显示全部楼层
回复 3# czjt1234


原来如此,不过64位的Long类型其实是可以大于 2^31 - 1 字节的,只是它的Long类型应该是32位的
loadfromfile读取文件也是整个直接读进内存的,跟写入一样不适合大文件。。。
 楼主| 发表于 2025-8-28 22:55:34 | 显示全部楼层
回复 4# flashercs


要是能像scripting.filesystemobject那样就好了,scripting.filesystemobject的文件操作不能设定编码太伤了
发表于 2025-8-28 23:41:18 | 显示全部楼层
ADODB是30年前的东西了,换个语言吧;
发表于 2025-8-29 09:12:40 | 显示全部楼层
回复 5# HalloWord


肯定是要分段读写的啊,JScript和VBScript不支持这么大的内存

要读写大文件,支持各种编码,要用powershell的[System.IO]系列对象

  1. 'vbs示例:测试读取速度和最大文件大小
  2. Dim oStream, n, s, t
  3. Set oStream = CreateObject("ADODB.Stream")
  4. oStream.Type = 1    'adTypeBinary
  5. oStream.Mode = 3    'adModeReadWrite
  6. oStream.Open()
  7. t = Now()
  8. oStream.LoadFromFile "D:\2G-1.xml"
  9. Do Until oStream.EOS
  10.     n = LenB(oStream.Read(1024 * 1024 * 21))
  11. Loop
  12. 'MsgBox oStream.Position & vbCrLf & oStream.Size
  13. oStream.Close()
  14. s = Now()
  15. MsgBox n & vbCrLf & t & vbCrLf & s
复制代码

  1. 已有文件 D:\2G-1.xml 大小2147483647字节
  2.          D:\2G.xml   大小2147483648字节 = 2^31
  3.          D:\4G-1.xml 大小4294967295字节
  4.          D:\4G.xml   大小4294967296字节 = 2^32
  5. 读取D:\2G-1.xml时,Position和Size属性可读
  6. 读取D:\2G.xml时,读取Position和Size属性会报错
  7. 读取D:\4G-1.xml时,最后返回的 n 数值正常
  8. 读取D:\4G.xml时,最后返回的 n 数值异常
  9. 实测读取 D:\2G.xml 文件约需要13秒
  10. 测试环境:CPU  Intel(R) Core(TM) i3-7100 CPU @ 3.90GHz
  11.           硬盘 INTEL SSDSA2CW120G3 ATA Device
复制代码

评分

参与人数 1技术 +1 收起 理由
HalloWord + 1 感谢测试!

查看全部评分

发表于 2025-8-29 10:33:01 | 显示全部楼层
本帖最后由 aloha20200628 于 2025-9-1 12:56 编辑

回复 7# HalloWord

楼主可以参考研习微软官方有关 adodb.stream 编程的文档 (https://learn.microsoft.com/zh-c ... -to-ado-programming),功能/特性/方法相当丰富,远超 scripting.filesystemobject 的 opentextfile 等方法,更适合写出超大文件(其关键是要采用 '文件追加方式' 分段写出即采用 ads.savetoFile('d:\\tmp\\biggest.txt') 默认写出方式,而非 '覆盖方式' 一次性写出,还须配合写入内存块的实时管理,如定长覆盖或释放等...),当然操作文件体量越大其效率会有所降低。据网言有人实测过采用 '文件追加方式'+'内存块管理' 方法可以写满整个磁盘 ...
 楼主| 发表于 2025-8-29 15:55:36 | 显示全部楼层
回复 8# flashercs


    系统自带的比较方便,winxp都能用
 楼主| 发表于 2025-8-29 16:44:09 | 显示全部楼层
回复 9# czjt1234


    写入是可以分段写入,但是读取无法分段读取,读取大于4g的就报错退出了
position,size属性应该也可以根据read出来的长度n来自行分段?
winxp不自带powershell不够便利
adodb.stream的open方法可以带参数,只是没有示例,不知道如何用,也不知道能否通过那个source参数直接open一个文件
 楼主| 发表于 2025-8-29 16:47:59 | 显示全部楼层
回复 10# aloha20200628


    这个看了,可是感觉说的太零散了,而且很多都没有示例,有示例的也过于简洁了,看得云里雾里的
发表于 2025-8-29 19:12:32 | 显示全部楼层
回复 12# HalloWord


你的需求是在xp环境处理大于4G的文件?

那你试试第三方软件sed啊什么的
发表于 2025-8-29 23:47:52 | 显示全部楼层
换成vb.net或者JScript.net
windows7以上都自带.net framework了
system.io都处理得明明白白
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-17 05:28 , Processed in 0.024144 second(s), 9 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表