<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title type="html"><![CDATA[Серый форум &mdash; JScript: Альтернативные чтение и запись файлов]]></title>
	<link rel="self" href="http://forum.script-coding.com/extern.php?action=feed&amp;tid=10092&amp;type=atom" />
	<updated>2014-10-30T20:42:03Z</updated>
	<generator>PunBB</generator>
	<id>http://forum.script-coding.com/viewtopic.php?id=10092</id>
		<entry>
			<title type="html"><![CDATA[JScript: Альтернативные чтение и запись файлов]]></title>
			<link rel="alternate" href="http://forum.script-coding.com/viewtopic.php?pid=87857#p87857" />
			<content type="html"><![CDATA[<p>Приветствую. Думаю, что для вас не секрет, что чтение файлов посредством FileSystemObject и ADODB.Stream довольно тормозное. Хорошей и скоростной альтернативой может послужить <a href="http://forum.script-coding.com/viewtopic.php?id=4284">SAPI.spFileStream</a>.</p><p>В общем, я написал обертку, которая позволяет работать с файлами как с бинарными данными, так и с текстовыми. Она позволяет работать с файлами огромного размера на высокой скорости. Данная технология не грузит файлы целиком в память,&nbsp; а работает только с нужными фрагментами.&nbsp; В настоящий момент осуществляется поддержка текстовой кодировки UTF-8. </p><p>Функции:<br /><strong>FileOpen</strong> (FilePath, Mode) - Открытие файла.&nbsp; FilePath - это путь к файлу. Mode - режим открытия, принимает следующие значения: 0 (по умолчанию) - режим чтения, 1 - режим записи (каретка находится в конце файла), 2 - режим перезаписи, 8 - создание структуры папок, если ее не существует. Возвращает так называемый FileHandle.</p><p><strong>FileRead</strong> (FileHandle, count, result) - Читает файл. FileHandle - это либо путь к файлу, либо то, что возвращает FileOpen. сount (по умолчанию - 0) - сколько байт читать. Если параметр равен нулю или опущен, то считывается весь файл. result - объект, в котором будут записаны свойства buffer (результат чтения) и count (сколько байт прочитано). Функция возвращает то, что было прочитано (то же самое, что result.buffer).</p><p><strong>FileReadLine</strong>(FileHandle) - Читает строку в файле. </p><p><strong>FileWrite</strong>(FileHandle, data) - Пишет в файл. FileHandle - это либо путь к файлу, либо то, что возвращает FileOpen. data - данные. <br /><strong>FileWriteLine</strong>(FileHandle, data) - без комментариев.</p><p><strong>FileGetPos</strong> (FileHandle) - текущая позиция в файле.</p><p><strong>FileSetPos</strong>(FileHandle, offset, origin). Задает позицию в файле. offset - смещение в байтах. origin - относительно чего осуществится смещение. Принимает следующие значения: 0 (по умолчанию) - начало файла, 1 - текущая позиция, 2 - конец файла.</p><p>Пример:<br /></p><div class="codebox"><pre><code>
var Stream = FileOpen(GetScriptFullPath()+&quot;.123.txt&quot;, 2);
    
    MsgBox(FileGetPos(Stream));
    FileWriteLine(Stream, &quot;Hello!&quot;);
    FileWrite(Stream, &quot;Привет!&quot;);
    FileSetPos(Stream, 0, 0);
    MsgBox(FileRead(Stream));
    FileSetPos(Stream, 0, 0);
    MsgBox(FileReadLine(Stream));
    MsgBox(FileReadLine(Stream));
    FileSetPos(Stream, 0, 0);
    FileWrite(Stream, ArrayToBinary([65,65,65,65,65,65,65,65,65,65,65,65,65,65])); // пишем побайтово
    FileSetPos(Stream, 0, 0);
    MsgBox(FileReadLine(Stream, 10));
    Exit();
</code></pre></div><p>А теперь весь код 8-)<br /></p><div class="codebox"><pre><code>
var GlobalObject = this;
var FSO = fso = new ActiveXObject(&quot;Scripting.FileSystemObject&quot;);
var WshShell = new ActiveXObject(&quot;WScript.Shell&quot;);

if (GlobalObject.WScript &amp;&amp; FileExists(&quot;%WinDir%\\SysWow64\\wscript.exe&quot;) &amp;&amp; !/wow64/i.test(WScript.FullName + &quot;&quot;)) {
    WshShell.Run(&quot;%WinDir%\\SysWow64\\wscript.exe \&quot;&quot; + WScript.FullName + &quot;\&quot;&quot;, 1, 0);
    WScript.Quit();
}

var vbs = &quot;\r\n\
Function [_MidB](v, s, l):[_MidB]=MidB(v, s+1, l):End Function\r\n\
Function [_Asc](v):[_Asc]=Asc(v):End Function\r\n\
Function [_Chr](v):[_Chr]=Chr(v):End Function\r\n\
Function [_LenB](v):[_LenB]=LenB(v):End Function\r\n\
Function [_VarType](v):[_VarType]=VarType(v):End Function\r\n\
Function [_TypeName](v):[_TypeName]=TypeName(v):End Function\r\n\
Function [_ChrB](v):[_ChrB]=ChrB(v):End Function\r\n\
Function [_AscB](v):[_AscB]=AscB(v):End Function\r\n\
Function [_LeftB](v, l):[_LeftB]=LeftB(v, l):End Function\r\n\
Function [_RightB](v, l):[_RightB]=RightB(v, l):End Function\r\n\
Function [_InstrB](start, stringtosearch, stringtofind, comparemode):[_InstrB]=InstrB(start, stringtosearch, stringtofind, comparemode):End Function\r\n\
\r\n\
Sub ConvertBinaryToJSArray(arrByteArray, js_arr)\r\n\
Dim i\r\n\
For i = 1 To LenB(arrByteArray)\r\n\
    js_arr.push(AscB(MidB(arrByteArray, i, 1)))\r\n\
Next\r\n\
End Sub\r\n\
\r\n\
Function MultiByteToBinary(MultiByte)\r\n\
  \&#039; 2000 Antonin Foller, http://www.motobit.com\r\n\
  \&#039; MultiByteToBinary converts multibyte string To real binary data (VT_UI1 | VT_ARRAY)\r\n\
  \&#039; Using recordset\r\n\
  Dim RS, LMultiByte, Binary\r\n\
  Const adLongVarBinary = 205\r\n\
  Set RS = CreateObject(\&quot;ADODB.Recordset\&quot;)\r\n\
  LMultiByte = LenB(MultiByte)\r\n\
  If LMultiByte&gt;0 Then\r\n\
    RS.Fields.Append \&quot;mBinary\&quot;, adLongVarBinary, LMultiByte\r\n\
    RS.Open\r\n\
    RS.AddNew\r\n\
      RS(\&quot;mBinary\&quot;).AppendChunk MultiByte &amp; ChrB(0)\r\n\
    RS.Update\r\n\
    Binary = RS(\&quot;mBinary\&quot;).GetChunk(LMultiByte)\r\n\
  End If\r\n\
  MultiByteToBinary = Binary\r\n\
End Function\r\n\
    \r\n\
Function RSBinaryToString(xBinary)\r\n\
\&#039;1999 Antonin Foller, Motobit Software\r\n\
\&#039;This function converts binary data (VT_UI1 | VT_ARRAY or MultiByte string)\r\n\
\&#039;to string (BSTR) using ADO recordset\r\n\
\&#039;The fastest way - requires ADODB.Recordset\r\n\
\&#039;Use this function instead of MBBinaryToString if you have ADODB.Recordset installed\r\n\
\&#039;to eliminate problem with PureASP performance\r\n\
\r\n\
Dim Binary\r\n\
\&#039;MultiByte data must be converted to VT_UI1 | VT_ARRAY first.\r\n\
if vartype(xBinary) = 8 then Binary = MultiByteToBinary(xBinary) else Binary = xBinary\r\n\
\r\n\
Dim RS, LBinary\r\n\
Const adLongVarChar = 201\r\n\
Set RS = CreateObject(\&quot;ADODB.Recordset\&quot;)\r\n\
LBinary = LenB(Binary)\r\n\
\r\n\
if LBinary&gt;0 then\r\n\
RS.Fields.Append \&quot;mBinary\&quot;, adLongVarChar, LBinary\r\n\
RS.Open\r\n\
RS.AddNew\r\n\
RS(\&quot;mBinary\&quot;).AppendChunk Binary\r\n\
RS.Update\r\n\
RSBinaryToString = RS(\&quot;mBinary\&quot;)\r\n\
Else\r\n\
RSBinaryToString = \&quot;\&quot;\r\n\
End If\r\n\
End Function\r\n\
\r\n\
Sub SAPIFileRead(o, count, js_obj)\r\n\
Dim s, buffer\r\n\
s = o.Read(buffer, count)\r\n\
js_obj.count = s\r\n\
js_obj.buffer = buffer\r\n\
End Sub\r\n\
&quot;;

var VBSEngine = new ActiveXObject(&#039;ScriptControl&#039;);
VBSEngine.Language = &#039;VBScript&#039;;
VBSEngine.AddCode(vbs);

function VarType(s)
{
    return VBSEngine.CodeObject._VarType(s);
}

function TypeName(s)
{
    return VBSEngine.CodeObject._TypeName(s);
}

WshShell.CurrentDirectory = GetScriptDir();

function GetScriptDir() {
    return GetScriptFullPath().replace(/[^\\]+$/g, &quot;&quot;);
}
//MsgBox(GetScriptDir());
//Exit();

//@ScriptFullPath Equivalent to @ScriptDir &amp; &quot;\&quot; &amp; @ScriptName 
function GetScriptFullPath() {
    if (GlobalObject.location &amp;&amp; GlobalObject.location.href) return location.href.replace(/^.+\/\/\//, &quot;&quot;).replace(/\//g, &quot;\\&quot;);
    if (GlobalObject.WScript) return WScript.ScriptFullName;
    return &quot;&quot;;
}
//MsgBox(GetScriptFullPath());
//Exit();

function MsgBox(strText, strTitle, nType) {
    return WshShell.Popup(strText, 0, strTitle, nType);
}

function Exit() {
    if (GlobalObject.WScript) WScript.Quit();
    if (GlobalObject.window) window.close();
}

//BinaryMid Extracts a number of bytes from a binary variant. Start - 0
function BinaryMid(s, l, c) {
    return VBSEngine.CodeObject._MidB(s, l, c);
}

function BinaryLen(s) {
    return VBSEngine.CodeObject._LenB(s);
}

// -1 = not found
function BinaryInBinary(stringtosearch, stringtofind, start, comparemode) {
    if (!start) start = 1;
    else start++;
    return VBSEngine.CodeObject._InstrB(start, stringtosearch, stringtofind, comparemode) - 1;
}
//MsgBox(BinaryInBinary(Binary(&quot;123123123&quot;), Binary(&quot;123&quot;)));

//array of integers (bytes) to ByteArray
function ArrayToBinary(ar) {
var ms = new ActiveXObject(&quot;SAPI.spMemoryStream&quot;);
for (var i=0, l=ar.length; i&lt;l;i++)
{
        ms.Write(ar[i]);
        ms.Seek(i+1);
}
s = ms.GetData();
var l = BinaryLen(s);
s = BinaryMid(s, 0, l-3)

return MultiByteToBinary(s);
}

function BinaryToArray(binary) {
    var ar = [];
    VBSEngine.CodeObject.ConvertBinaryToJSArray(binary, ar);
    return ar;
}

function MultiByteToBinary(x)
{
    return VBSEngine.CodeObject.MultiByteToBinary(x);
}


//FileExists Checks if a file or directory exists.
function FileExists(Path) {
    Path = WshShell.ExpandEnvironmentStrings(Path);
    return FSO.FolderExists(Path) || FSO.FileExists(Path);
}

//FileDelete Delete one or more files. (принудительное удаление. принимает как массивы файлов, так и просто путь) поддерживает удаление по маске.
function FileDelete(Path) {
    if (/Array/i.test(Path.constructor + &quot;&quot;)) {
        for (var i = 0, l = Path.length; i &lt; l; i++)
            FileDelete(Path[i]);

        return true;
    }

    Path = WshShell.ExpandEnvironmentStrings(Path);
    try {
        FSO.DeleteFile(Path, true);
        return 1;
    } catch (e) {
        return 0
    }
}

function FileOpen(FilePath, Mode)
{
    var StreamMode = 0;
    
    if (!FilePath) return false;

    if (!Mode) Mode = 0;

    if (Mode &amp; 0) {StreamMode = 0;}
    if (Mode &amp; 1) {StreamMode = 1;}//Write mode (append to end of file)
    if (Mode &amp; 2) {FileDelete(FilePath); FSO.CreateTextFile(FilePath).Close(); StreamMode = 1;}//$FO_OVERWRITE (2) = Write mode (erase previous contents)
    if (Mode &amp; 8) DirCreate(FileGetDirectory(FilePath)); //$FO_CREATEPATH (8) = Create directory structure if it doesn&#039;t exist (See Remarks).
    

    var Stream = new ActiveXObject(&quot;SAPI.spFileStream&quot;)
    Stream.Open(FilePath, StreamMode);
    
    if (Mode &amp; 1) FileSetPos(Stream, 0, 2); //$FO_APPEND (1) = Write mode (append to end of file)
    
    return Stream;
}

//FileRead Read in a number of characters from a previously opened text file.
function FileRead(FileHandle, count, result)
{
    if (!result) result = {};
    if (typeof FileHandle == &quot;string&quot;)
    {
        if (!count) count = FileGetSize(FileHandle);
        FileHandle = FileOpen(FileHandle, 0);
    }
    
    result.count = 0;
    result.buffer = &quot;&quot;;
    
    if (!count) count = 1024;
    VBSEngine.CodeObject.SAPIFileRead(FileHandle, count, result);
//    MsgBox(result.buffer);
//    MsgBox(result.count);
    return result.buffer;
}

//FileSetPos Sets the current file position.
/*

Origin
Must be one of the following:
    $FILE_BEGIN (0) = Beginning of the file.
    $FILE_CURRENT (1) = Current position.
    $FILE_END (2) = End of the file.
Constants are defined in FileConstants.au3
*/
function FileSetPos(FileHandle, offset, origin)
{
    if (!origin) origin = 0;
    return FileHandle.Seek(offset, origin);
}

//FileGetPos Retrieves the current file position.
function FileGetPos(FileHandle)
{
    return FileSetPos(FileHandle, 0, 1);
}

//FileWrite Append a text/data to the end of a previously opened file.
function FileWrite(FileHandle, data)
{
    if (typeof FileHandle == &quot;string&quot;)
    {
        FileHandle = FileOpen(FileHandle, 1);
    }
    
    if (typeof data == &quot;string&quot;)
    {
        data = MultiByteToBinary(data);
    }
    
    return FileHandle.Write(data);
}

//FileWriteLine Append a line of text to the end of a previously opened text file.
function FileWriteLine(FileHandle, data)
{
    return FileWrite(FileHandle, data + &quot;\r\n&quot;);
}

//FileReadLine Read in a line of text from a previously opened text file.
function FileReadLine(FileHandle)
{
    if (typeof FileHandle == &quot;string&quot;)
    {
        FileHandle = FileOpen(FileHandle, 0);
    }

    var result = {count:0, buffer:&quot;&quot;}, 
    startPos = FileGetPos(FileHandle), 
    pos = -1, i=0, step = 1024, len=2,
    buffer, CrLf = ArrayToBinary([13,0,10,0]),
    Cr = ArrayToBinary([13,0]);

    while (true){
        FileRead(FileHandle, step, result); 
        pos = BinaryInBinary(result.buffer, CrLf);
        
        if (pos!=-1) {len=4; break};
        pos = BinaryInBinary(result.buffer, Cr);
        if (pos!=-1) {len=2; break};
        if (result.count&gt;4) {FileSetPos(FileHandle, -4, 1); i+=step-4;} else
        i+=step;
        
        if (result.count!=step) break;
    }
    
    var result = &quot;&quot;;
    if (pos==0) {FileSetPos(FileHandle, startPos+len, 0); return &quot;&quot;};
    
    FileSetPos(FileHandle, startPos, 0);
    result = FileRead(FileHandle, i+pos);
    FileSetPos(FileHandle, len, 1);
    return result;
}
var Stream = FileOpen(GetScriptFullPath()+&quot;.123.txt&quot;, 2);
    
    MsgBox(FileGetPos(Stream));
    FileWriteLine(Stream, &quot;Hello!&quot;);
    FileWrite(Stream, &quot;Привет!&quot;);
    FileSetPos(Stream, 0, 0);
    MsgBox(FileRead(Stream));
    FileSetPos(Stream, 0, 0);
    MsgBox(FileReadLine(Stream));
    MsgBox(FileReadLine(Stream));
    FileSetPos(Stream, 0, 0);
    FileWrite(Stream, ArrayToBinary([65,65,65,65,65,65,65,65,65,65,65,65,65,65]));
    FileSetPos(Stream, 0, 0);
    MsgBox(FileReadLine(Stream, 10));
    Exit();
</code></pre></div>]]></content>
			<author>
				<name><![CDATA[JSmаn]]></name>
				<uri>http://forum.script-coding.com/profile.php?id=24434</uri>
			</author>
			<updated>2014-10-30T20:42:03Z</updated>
			<id>http://forum.script-coding.com/viewtopic.php?pid=87857#p87857</id>
		</entry>
</feed>
