//stream 文件流 import util.metaProperty; import com.interface.IStream; namespace fsys; class stream{ ctor( str,len,grfMode){ if( type(str) == "pointer" ){ this.stream = ..com.interface(str,..com.interface.IStream ); if(len) ..com.Release(str); } elseif( type(len) == type.string ){ var mode = len; var grfMode = 0; var f=mode[1]; var seekend; if(grfMode===null) grfMode = 0x00000020/*STGM_SHARE_DENY_WRITE*/ if( f='r'# ) { grfMode |= 0/* _STGM_READ*/ } else { if( f='w'# ) { grfMode |= 0x00001000/*STGM_CREATE*/ | 1/*STGM_WRITE*/; if( ..io.exist(str) ) ..io.remove(str) } else{ grfMode |= 1/*STGM_WRITE*/ if(! ..io.exist(str) ) grfMode |= 0x00001000/*STGM_CREATE*/; seekend = true; } } if(..string.indexAny(mode,"+") ){ grfMode = grfMode | 2/*STGM_READWRITE*/; } var ppstm = {ptr pIStream} var hr = ::Shlwapi.SHCreateStreamOnFileW(..io.fullpath(str), grfMode,ppstm); if( (hr)<0/*_FAILED*/ ) return; this.stream = ..com.interface(ppstm.pIStream,..com.interface.IStream) ..com.Release(ppstm.pIStream); if(seekend)this.stream.Seek(0,0x2/*_FILE_END*/,0); } else{ var hMemory; if( #str || len ){ if(!len) len = #str; len = ..math.max(len,#str) hMemory= ::GlobalAlloc( 0x2 /*_GMEM_MOVEABLE*/, len); if( str ){ var pMemory=::GlobalLock(hMemory); ::CopyMemory(pMemory,str,len); ::GlobalUnlock(hMemory); } } var hr,pIStream = ::CreateStreamOnHGlobal(hMemory, true/*GlobalFree*/); if( (hr)<0/*_FAILED*/ ) return; this.stream = ..com.interface(pIStream,..com.interface.IStream) ..com.Release(pIStream); } this.__isIStream = true; }; @_metaProperty; } namespace stream{ _metaProperty = ..util.metaProperty( close = function(){ if(owner.stream){ ..com.Release(owner.stream); owner.stream = null; } }; readAll = function(){ owner.reset(); return owner.read(-1); }; readLine = lambda() owner.read();//@Deprecated lines = function(){ var f = owner; return function(){ return f.read(); } }; read = function(len){ if( len === null ){ var d = {}; var buf = ..raw.buffer(1); while( var hr,size; hr,size = owner.stream.Read(buf,1,0); ( (hr)>=0/*_SUCCEEDED*/ && size ) ) { if( buf[1] == '\n'# ) return ..string.join(d); if( buf[1]!='\r'#)..table.push(d,tostring(buf)); } if(#d) return ..string.join(d); return; } if( len[["_struct"]] ){ var t = len; var buf = ..raw.buffer(t) var hr,size = owner.stream.Read(buf,#buf,0); if( (hr)>=0/*_SUCCEEDED*/ ) { if(size == #buf) return ..raw.convert(buf,t); } return; } if(len===0){ var c = owner.seek(); var len = owner.seek("end",0); owner.seek("set",c); return c=0/*_SUCCEEDED*/ ) { if(size != len)return ..string.left(buf,size); return tostring(buf); } }; readTo = function(ends){ if( type(ends)!="string" || (!#ends) ) error("参数错误",2); var lends = #ends; var bytes = {} var push = ..table.push; var buf = ..raw.buffer(1); while( var hr,byte,size; hr,size = owner.stream.Read(buf,1,0); ( (hr)>=0/*_SUCCEEDED*/ ) && size ) { push(bytes,tostring(buf)); if( buf[1] == ends[lends]){ var l = #bytes; for(i=lends-1;1;-1){ if( ends[[i]] != bytes[l-lends + i ] ){ continue 2; } } ..table.pop(bytes,lends); return ..string.join(bytes); } } }; readBuffer = function(buf,len){ if(len===null) len=#buf; var hr,size = owner.stream.Read(buf,len,0); if( (hr)>=0/*_SUCCEEDED*/ ) { return size; } }; write = function(str,len){ if( str[["_struct"]]) str = ..raw.buffer(str); if(!len) len = #str; var hr,len = owner.stream.Write(str,len,0); if( (hr)>=0/*_SUCCEEDED*/ ){ var cur = owner.seek(); if( cur > owner.size() ) owner.setSize(cur); return len; } }; writeBuffer = function(buf,len){ if(len===null) len=#buf; var hr,len = owner.stream.Write(buf,len,0); if( (hr)>=0/*_SUCCEEDED*/ ){ var cur = owner.seek(); if( cur > owner.size() ) owner.setSize(cur); return len; } }; seek = function(org="cur",move=0){ var hr,pos = owner.stream.Seek(move,_seekMode[org],0); if( (hr)>=0/*_SUCCEEDED*/ ) return pos; }; setSize = function(size){ var hr,pos = owner.stream.SetSize(size); if( (hr)>=0/*_SUCCEEDED*/ ) return size; }; stat = function(flag = 0/*_STATFLAG_DEFAULT*/ ){ var hr,s = owner.stream.Stat( STATSTG(),flag); if( (hr)>=0/*_SUCCEEDED*/ ) return s; }; size = function(){ var c = owner.seek(); var len = owner.seek("end",0); owner.seek("set",c); return len; }; reset = function(){ owner.seek("set",0); return owner; }; commit = function(flag){ owner.stream.Commit(flag:0); }; revert = function(flag){ return owner.stream.Revert(flag:0); } flush = function(){ owner.stream.Commit(flag:0); }; lockPointer = function(){ var hr,handle = ::GetHGlobalFromStream(owner.stream); if( (hr)<0/*_FAILED*/ ) return; if( !handle ) return; var size = ::GlobalSize(handle); var ptr = ::GlobalLock(handle); return ptr,size; }; unlockPointer = function(){ var hr,handle = ::GetHGlobalFromStream(owner.stream); if( (hr)<0/*_FAILED*/ ) return; if( !handle ) return; return !::GlobalUnlock(handle); }; _topointer = function(){ return owner.stream; }; _serialize = function(kernelCall){ return "null" } _type="fsys.stream"; ) ::Shlwapi := ..raw.loadDll("Shlwapi.dll"); _seekMode = { ["cur"] = 0x1/*_FILE_CURRENT*/; ["end"] = 0x2/*_FILE_END*/; ["set"] = 0x0/*_FILE_BEGIN*/; } class STATSTG { pointer pwcsName; INT type; LONG cbSize; struct mtime = ::FILETIME(); struct ctime = ::FILETIME(); struct atime = ::FILETIME(); INT grfMode; INT grfLocksSupported; struct clsid = ..win.guid(); INT grfStateBits; INT reserved; } } /**intellisense() fsys.stream = 文件流对象\n兼容IStream,ISequentialStream接口 fsys.stream( = 创建文件流对象,返回对象可传入其他线程使用。 fsys.stream(.(IStream接口指针) = 直接使用指针创建对象 fsys.stream(.(IStream接口指针,true) = 直接使用指针创建对象,该指针的COM引用计数减一\n注意对象自身会增加COM引用计数并在释放时移除 fsys.stream(.(初始化数据,缓冲区长度) = 创建内存流文件,所有参数可选\n可选使用参数@3指定选项,此参数请参考库源码 fsys.stream(.("文件路径","r+") = 读写模式打开文件流,文件必须存在\n注意流对象总是以二进制模式读写,不需要添加b标记 fsys.stream(.("文件路径","w") = 只写模式打开文件流,创建新文件清空原文件\n注意流对象总是以二进制模式读写,不需要添加b标记 fsys.stream(.("文件路径","w+") = 读写模式打开文件流,创建新文件清空原文件\n注意流对象总是以二进制模式读写,不需要添加b标记 fsys.stream(.("文件路径","a") = 只写追加模式打开文件流,创建新文件保留原文件 fsys.stream(.("文件路径","a+") = 读写追加模式打开文件流,创建新文件保留原文件\n注意流对象总是以二进制模式读写,不需要添加b标记 fsys.stream() = !fsys_stream. !fsys_stream.read( = 读数据 !fsys_stream.read(.(-1) = 参数指定读取长度,-1为读到尾部\n参数也可以指定一个结构体用于填充读取的数据,\n无参数读取一行 !fsys_stream.read(0) = 是否未到达文件尾。\n如果已经到达文件尾返回 null,否则返回空字符串。\n注意在布尔表达式工 null 等于 false,空字符串等于 true。 !fsys_stream.readAll() = 移到指针到文件头\n读取到文件尾返回所有数据 !fsys_stream.readTo( = 读取直到以指定的字符串结束 !fsys_stream.readTo(.('结束串') = 读取直到以指定的字符串结束,返回值不包含结束串,\n该函数每次仅读取一个字节,效率较低 !fsys_stream.lines() = @for line in ??.lines(){ __/*逐行读取数据,循环返回当前行(字符串值)。\n无论是否以文本模式打开,读取数据总是移除回车符与换行符。*/ } !fsys_stream.size() = 得到数据长度 !fsys_stream.write( = 写数据 !fsys_stream.write(.(数据,长度) = 写入数据\n参数@1可使用字符串、buffer、指针、结构体等\n如果指定指针就必须明确指定写入长度 !fsys_stream.readBuffer(.(buffer,读取长度) = 读取数据到 buffer,\n参数@1应是 buffer 对象或指针,\n参数@2省略则默认为缓冲区长度。\n成功返回读取长度 !fsys_stream.writeBuffer(.(buffer,读取长度) = buffer 写入流,\n参数@1应是 buffer 对象或指针,\n参数@2省略则默认为缓冲区长度 !fsys_stream.seek("end") = 移动指针至结束处 !fsys_stream.seek("end",__) = 移动至相对结束处的指定偏移量 !fsys_stream.seek() = 得到当前位置 !fsys_stream.seek("cur",__) = 移动至相对当前位置的指定偏移量 !fsys_stream.seek("set") = 移动指针到开始 !fsys_stream.seek("set",__) = 移动至相对开始处的指定偏移量 !fsys_stream.reset() = 文件指针移动到开始\n类似seek(0,"set"),不同的是此函数返回对象自身\n!fsys_stream. !fsys_stream.close() = 关闭对象 !fsys_stream.stat() = 返回流状态\n返回值为STATSTG结构体\n!fsysstramSTATSTG. !fsys_stream.flush() = 提交更改\n兼容aardio标准流接口 !fsys_stream.commit(.(flags) = 提交更改 !fsys_stream.revert() = 撤消更改 !fsys_stream.lockPointer() = 如果这是一个内存流,\n锁定内存并返回内存指针,内存长度,\n需要使用对象的unlockPointer()成员函数解锁内存\n写入内存流可能导致重新分配内存,所以返回的指针可能会变动 !fsys_stream.unlockPointer() = 解锁内存\n用lockPointer函数获取内存指针使用以后,必须调用此函数 !fsysstramSTATSTG.cbSize = 文件长度 end intellisense**/