Тема: VBScript: работа с большими текстовыми файлами
ADOFromText.wsf
<?XML version="1.0" standalone="yes" ?>
<job id="ADOFromText">
<?job error="True" debug="True" ?>
<runtime>
<description>This script XOR-filtering lines from Source file by part lines from Filter file, then save result lines in Result file</description>
<named name="PathToSchema" helpstring="Path to schema" type="string" required="true" />
<named name="SourceFile" helpstring="Name of source file" type="string" required="true" />
<named name="SourcePathDiff" helpstring="Diff part of source's path" type="string" required="true" />
<named name="FilterFile" helpstring="Name of filter file" type="string" required="true" />
<named name="FilterPathDiff" helpstring="Diff part of filter's path" type="string" required="true" />
<named name="ResultFile" helpstring="Name of result file" type="string" required="true" />
<example>Example: ADOFromText.wsf /PathToSchema:"c:\temp" /SourceFile:"SourceFile.txt" /SourcePathDiff:"c:\Install" /FilterFile:"FilterFile.txt" /FilterPathDiff:"\\server\Installation$" /ResultFile:"ResultFile.txt"</example>
</runtime>
<reference object="ADODB.Connection" />
<object id="objRecordSetResult" progid="ADODB.Recordset" />
<object id="objFSO" progid="Scripting.FileSystemObject" />
<script language="VBScript">
<![CDATA[
Option Explicit
Dim objNamedArgs : Set objNamedArgs = WScript.Arguments.Named
If objFSO.FileExists(objFSO.BuildPath(objNamedArgs.Item("PathToSchema"), objNamedArgs.Item("ResultFile"))) Then
objFSO.DeleteFile objFSO.BuildPath(objNamedArgs.Item("PathToSchema"), objNamedArgs.Item("ResultFile"))
End If
objRecordSetResult.Open "SELECT S.[FileName], S.[Path], S.[DateTimeModified], S.[Size] INTO [" & _
objNamedArgs.Item("ResultFile") & "] " & _
"FROM [" & objNamedArgs.Item("SourceFile") & "] AS S LEFT JOIN [" & _
objNamedArgs.Item("FilterFile") & "] AS F ON " & _
"S.[FileName] = F.[FileName] AND " & _
"MID(S.[Path], " & CStr(Len(objNamedArgs.Item("SourcePathDiff")) + 1) & ") = " & _
"MID(F.[Path], " & CStr(Len(objNamedArgs.Item("FilterPathDiff")) + 1) & ") AND " & _
"S.[DateTimeModified] = F.[DateTimeModified] AND S.[Size] = F.[Size] " & _
"WHERE F.[FileName] IS NULL", _
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & objNamedArgs.Item("PathToSchema") & ";Extended Properties=""text;""", _
adOpenStatic, adLockOptimistic, adCmdText
Set objNamedArgs = Nothing
WScript.Quit 0
]]>
</script>
</job>
Schema.ini
[HomeComp.txt]
ColNameHeader=False
Format=Delimited(;)
TextDelimiter=none
CharacterSet=ANSI
Col1=FileName Text
Col2=Path Text
Col3=DateTimeModified DateTime
Col4=Size Long
[JobComp.txt]
ColNameHeader=False
Format=Delimited(;)
TextDelimiter=none
CharacterSet=ANSI
Col1=FileName Text
Col2=Path Text
Col3=DateTimeModified DateTime
Col4=Size Long
[ResultFile.txt]
ColNameHeader=False
Format=Delimited(;)
TextDelimiter=none
DateTimeFormat=mm.dd.yy hh:nn
CharacterSet=ANSI
Col1=FileName Text
Col2=Path Text
Col3=DateTimeModified DateTime
Col4=Size Long
Пример файла JobComp.txt
IM000001.JPG;C:\Install\My Archivies\ФОТКИ\28-05-06 (Н.Я.День рожденье);28.05.2006 17:17;1437280
IM000002.JPG;C:\Install\My Archivies\ФОТКИ\28-05-06 (Н.Я.День рожденье);28.05.2006 17:26;1453600
IM000003.JPG;C:\Install\My Archivies\ФОТКИ\28-05-06 (Н.Я.День рожденье);28.05.2006 17:27;1576192
IM000006.JPG;C:\Install\My Archivies\ФОТКИ\28-05-06 (Н.Я.День рожденье);28.05.2006 17:30;1483488
IM000007.JPG;C:\Install\My Archivies\ФОТКИ\28-05-06 (Н.Я.День рожденье);28.05.2006 17:34;1335840
IM000008.JPG;C:\Install\My Archivies\ФОТКИ\28-05-06 (Н.Я.День рожденье);28.05.2006 17:37;1516512
IM000009.JPG;C:\Install\My Archivies\ФОТКИ\28-05-06 (Н.Я.День рожденье);28.05.2006 17:38;1672512
IM000010.JPG;C:\Install\My Archivies\ФОТКИ\28-05-06 (Н.Я.День рожденье);28.05.2006 17:38;1521632
IM000011.JPG;C:\Install\My Archivies\ФОТКИ\28-05-06 (Н.Я.День рожденье);28.05.2006 17:39;1367072
Пример файла HomeComp.txt
IM000001.JPG;D:\Other\ФОТКИ\28-05-06 (Н.Я.День рожденье);28.05.2006 17:17;1437280
IM000002.JPG;D:\Other\ФОТКИ\28-05-06 (Н.Я.День рожденье);28.05.2006 17:26;1453600
IM000005.JPG;D:\Other\ФОТКИ\28-05-06 (Н.Я.День рожденье);28.05.2006 17:29;1606784
IM000006.JPG;D:\Other\ФОТКИ\28-05-06 (Н.Я.День рожденье);28.05.2006 17:30;1483488
IM000010.JPG;D:\Other\ФОТКИ\28-05-06 (Н.Я.День рожденье);28.05.2006 17:38;1521632
IM000011.JPG;D:\Other\ФОТКИ\28-05-06 (Н.Я.День рожденье);28.05.2006 17:39;1367072
Для примера: все указанные файлы находятся в [c:\0001]. Тогда вызов ADOFromText.wsf осуществляется командой:
cscript.exe //nologo "c:\0001\ADOFromText.wsf" /PathToSchema:"c:\0001" /SourceFile:"JobComp.txt" /SourcePathDiff:"C:\Install\My Archivies" /FilterFile:"HomeComp.txt" /FilterPathDiff:"D:\Other" /ResultFile:"ResultFile.txt"
Результирующий файл ResultFile.txt
IM000003.JPG;C:\Install\My Archivies\ФОТКИ\28-05-06 (Н.Я.День рожденье);05.28.06 17:27;1576192
IM000007.JPG;C:\Install\My Archivies\ФОТКИ\28-05-06 (Н.Я.День рожденье);05.28.06 17:34;1335840
IM000008.JPG;C:\Install\My Archivies\ФОТКИ\28-05-06 (Н.Я.День рожденье);05.28.06 17:37;1516512
IM000009.JPG;C:\Install\My Archivies\ФОТКИ\28-05-06 (Н.Я.День рожденье);05.28.06 17:38;1672512
Примечания:
Собственно, вся функциональность лежит в использовании запроса
RecordSet.Open "SELECT <поля> INTO "ResultFile" FROM "SourceFile" LEFT JOIN "FilterFile" ON <Связь полей>, <Соединение>,…
Мы извлекаем все записи из "SourceFile", связанного с "FilterFile" (LEFT JOIN) по указанному условию <Связь полей>. Нас интересуют равенство полей [FileName], [DateTimeModified] и [Size] (S.[FileName] = F.[FileName], …). Из полей [Path] при сравнении мы исключаем несовпадающие начальные части, указанные в параметрах скрипта (MID(S.[Path], " & CStr(Len(objNamedArgs.Item("SourcePathDiff")) + 1) & ")=…). Также, из полученного набора мы исключаем записи, в которых значения полей из правой таблицы — пустые (для примера взято поле [File]: WHERE F.[FileName] IS NULL). И, наконец, помещаем полученный набор записей в результирующую таблицу "ResultFile" (INTO [" & objNamedArgs.Item("ResultFile") & "]).
Как правило, стоит заключать строки в кавычки, как и положено в CSV, хотя это и необязательно. В примере я не использовал их и для выходного файла (Schema.ini:TextDelimiter=none).
Формат дата/время желательно представлять с секундами В примере я не использовал секунды и для выходного файла (Schema.ini:DateTimeFormat=mm.dd.yy hh:nn) [в скобках замечу, что мне не удалось использовать указание такого формата для входных файлов, приводило к ошибке].
Вместо
If objFSO.FileExists(objFSO.BuildPath(objNamedArgs.Item("PathToSchema"), objNamedArgs.Item("ResultFile"))) Then
objFSO.DeleteFile objFSO.BuildPath(objNamedArgs.Item("PathToSchema"), objNamedArgs.Item("ResultFile"))
End If
можно использовать "DROP TABLE [" & objNamedArgs.Item("ResultFile") & "]", однако это приводит и к удалению из схемы информации о соответствующей таблице , а она у нас не совсем стандартная (-кавычки, -секунды), так что, для простоты, пользуем простое удаление результирующего файла [также отмечу, что операция DELETE для Text Driver не поддерживается в принципе].
Часть параметров из Schema.ini можно указывать в строке подключения, как свойства:
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\txtFilesFolder\;Extended Properties="text;HDR=Yes;FMT=Delimited"
Полного описания я, к сожалению, не нашёл.
Автор статьи - alexii.
В названии ветки всегда должен быть указан язык программирования или среда исполнения скрипта, если это возможно.