Output file is empty using vbscript - vbscript

Starting from an input file (input.txt) i have to find some strings and write them in another file txt (output.txt) This is the input.txt
**********************************************************
* NAME : CONTROLLER
* FUNCTION : NOTHING IMPORTANT
* BEGIN DATE : 31/07/13
* TIME BEGIN : 23.39.17.75
**********************************************************
* DATA INPUT READ : 000000540
**********************************************************
And this is the code:
Const ForReading = 1
Const ForWriting = 2
Dim objFSO 'File System Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
Dim objInputTS 'Text Stream Object
Set objInputTS = objFSO.OpenTextFile("D:\input.txt", ForReading, False)
Dim objOutputTS 'Text Stream Object
Set objOutputTS = objFSO.OpenTextFile("D:\output.txt", ForWriting, True)
Do Until objInputTS.AtEndOfStream
Dim strLine
strLine = objInputTS.ReadLine()
If (Left(strLine, 13) = "BEGIN DATE:") Then objOutputTS.WriteLine(Mid(strLine, 20))
If (Left(strLine, 13) = "TIME BEGIN:") Then objOutputTS.WriteLine(Mid(strLine, 20))
If (Left(strLine, 18) = "DATA INPUT READ:") Then objOutputTS.WriteLine(Mid(strLine, 22))
Loop
objOutputTS.Close()
objInputTS.Close()
But in the output file nothing appears. Any helps? i want this output for esxample
20/05/2013 22/05/2013 21.00.00.00 0000000054

The line
* BEGIN DATE : 31/07/13
does not match the condition
If (Left(strLine, 13) = "BEGIN DATE:")
you have to ac*count* for the "* " prefix too.
To spell it out:
>> s1 = "* BEGIN DATE : 31/07/13"
>> s2 = Left(s, 13)
>> WScript.Echo """" & s2 & """"
>>
"* BEGIN DATE "
>> c1 = "BEGIN DATE:"
>> c2 = "* BEGIN DATE "
>> WScript.Echo 1, CStr(c1 = s2)
>> WScript.Echo 2, CStr(c2 = s2)
>>
1 False
2 True

Related

Replacing text function value input in txt file not work

This is my expiration.txt file :
foo1; 2020-03-01 13:33;
foo2; 2020-02-01 08:45;
foo3; 2020-01-01 11:30;
I need open the expiration.txt file and replace the all date value from:
2020-03-01 13:33 to 2020-03-01
2020-02-01 08:45 to 2020-02-01
2020-01-01 11:30 to 2020-01-01
I have tried this code without success, because the replace not working.
Const ForReading = 1
Const ForWriting = 2
' create object
set oFSO = CreateObject("Scripting.FileSystemObject")
' open the input file
set oInFile = oFSO.OpenTextFile("expiration.txt", 1)
str_input = ""
' for each line in the input file
do while not oInFile.AtEndOfStream
' read the line
str_input = trim(oInFile.ReadLine())
Wscript.echo str_input
' if date found then exit the loop
if isDate(str_input) then
WScript.echo "Date in file found: '" & str_input & "'"
strNewText = Replace(str_input, left(str_input, 10))
Set objFile = oFSO.OpenTextFile("expiration.txt", 2)
objFile.WriteLine strNewText
WScript.echo "Date in file found: '" & strNewText & "'"
exit do
end if
loop
' close the input file
oInFile.close
' release object from memory
set oFSO = nothing
How to do resolve this ?
Using regular expression
Const ForReading = 1
Const ForWriting = 2
' create object
Set oFSO = CreateObject("Scripting.FileSystemObject")
str_input = ""
' open the input file
Set oInFile = oFSO.OpenTextFile("expiration.txt", 1)
' read the file contents
str_input = oInFile.ReadAll()
' close the input file
oInFile.Close
' use regular expression to find and replace text
Set oRegEx = CreateObject("VBScript.RegExp")
With oRegEx
.Multiline = True
.Global = True
.Pattern = "(\d+)-(\d+)-(\d+)\s(\d+):(\d+);" 'will match entire date including ;
End With
str_input = oRegEx.Replace(str_input, "$1-$2-$3;")
' open the input file to overwrite
Set oInFile = oFSO.OpenTextFile("expiration.txt", 2)
oInFile.Write str_input
' close the input file
oInFile.Close
' release object from memory
set oFSO = nothing

How can we decrease code execution time in VBScript

I have the below code to replace NUL characters in a text file. This code is working as per my requirement for smaller files but the problem is when the file size is increasing it is taking more time. I have a file which consists of more than 200,000 lines consists of 160MB+ size. I have executed my code for this file and I waited for more than 2 hours still the code executing.
Const ForReading = 1
Const ForWriting = 2
Const TriStateUseDefault = -2
If (WScript.Arguments.Count > 0) Then
sInfile = WScript.Arguments(0)
Else
WScript.Echo "No filename specified."
WScript.Quit
End If
If (WScript.Arguments.Count > 1) Then
sOutfile = WScript.Arguments(1)
Else
sOutfile = sInfile
End If
'Get the text file from cmd file
sData = ""
FinalData = ""
sInfile = WScript.Arguments(1)
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set re = New RegExp
re.Pattern = "\x00.*"
re.Global = True
Set f = oFSO.OpenTextFile(sInfile, 1, False, -1)
Do Until f.AtEndOfStream
sData = Replace(f.ReadLine, vbCrLf, "")
FinalData = FinalData + re.Replace(sData, "") + vbCrLf
Loop
f.Close
Set oOutfile = oFSO.OpenTextFile(sOutfile, 2, True, -1)
oOutfile.Write(FinalData)
oOutfile.Close
Set oOutfile = Nothing
Set oFS = Nothing
WScript.Quit
Is there any way to optimize the code to execute in less interval of time.
EDIT 1:
Updated Code:
Const ForReading = 1
Const ForWriting = 2
Const TriStateUseDefault = -2
If (WScript.Arguments.Count > 0) Then
sInfile = WScript.Arguments(0)
Else
WScript.Echo "No filename specified."
WScript.Quit
End If
If (WScript.Arguments.Count > 1) Then
sOutfile = WScript.Arguments(1)
Else
sOutfile = sInfile
End If
'Get the text file from cmd file
sData = ""
FinalData = ""
sInfile = WScript.Arguments(1)
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set re = New RegExp
re.Pattern = "\x00.*"
re.Global = True
Set f = oFSO.OpenTextFile(sInfile, 1, False, -1)
Do Until f.AtEndOfStream
sData = Replace(f.ReadAll, vbCrLf, "")
FinalData = FinalData + re.Replace(sData, "") + vbCrLf
Loop
f.Close
Set oOutfile = oFSO.OpenTextFile(sOutfile, 2, True, -1)
oOutfile.Write(FinalData)
oOutfile.Close
Set oOutfile = Nothing
Set oFS = Nothing
WScript.Quit
Do not use ReadAll for large files. Reading large files into memory might exhaust the available RAM on your computer, so that it will come grinding to a halt because it starts swapping.
Also avoid concatenating strings in a loop, because the operation is slow.
Change this:
Set f = oFSO.OpenTextFile(sInfile, 1, False, -1)
Do Until f.AtEndOfStream
sData = Replace(f.ReadLine, vbCrLf, "")
FinalData = FinalData + re.Replace(sData, "") + vbCrLf
Loop
f.Close
Set oOutfile = oFSO.OpenTextFile(sOutfile, 2, True, -1)
oOutfile.Write(FinalData)
oOutfile.Close
to this:
Set f = oFSO.OpenTextFile(sInfile, 1, False, -1)
Set oOutfile = oFSO.OpenTextFile(sOutfile, 2, True, -1)
Do Until f.AtEndOfStream
oOutFile.WriteLine re.Replace(f.ReadLine, "")
Loop
f.Close
oOutfile.Close
Same code with string operations instead of a regular expression replacement:
Set f = oFSO.OpenTextFile(sInfile, 1, False, -1)
Set oOutfile = oFSO.OpenTextFile(sOutfile, 2, True, -1)
Do Until f.AtEndOfStream
line = f.ReadLine
pos = InStr(line, Chr(0))
If pos > 0 Then line = Left(line, pos-1)
oOutFile.WriteLine line
Loop
f.Close
oOutfile.Close
I know it's not up to date, but it might be useful to someone.
I tried another approach that takes about 5 seconds! :)
It seems that scripting engine (wscript) or FileSystemObject has a problem loading 160 MB at a time (by .ReadAll method).
So I tried to load all data (into the Dictionary) line by line via .ReadLine, process it and then save it to the output file at once.
Appendix:
- I added the option to create a test file - if you specify "CreateData" as the second argument:wscript util.vbs "C:\Temp\SampleData.txt" CreateData
- You do not need to remove CR + LF from a string that returns .ReadLine. They are already skipped.
- Sometimes it is good to test .AtEndOfStream before .ReadAll method, because if the file will be empty, the method will cause run-time error.
Dim mode, sInFile, sOutFile
If (WScript.Arguments.Count > 0) Then
sInfile = WScript.Arguments(0)
Else
WScript.Echo "No filename specified."
WScript.Quit
End If
If (WScript.Arguments.Count > 1) Then
If StrComp(WScript.Arguments(1), "CreateData", 1) = 0 then
mode = "CreateData"
sOutfile = sInFile
Else
mode = "processing"
sOutfile = WScript.Arguments(1)
End If
Else
mode = "processing"
sOutfile = sInfile
End If
Set oFSO = CreateObject("Scripting.FileSystemObject")
if mode = "CreateData" then
Call CreateDataFile(sInfile, 160) '160 = approx. 160 MB'
Wscript.Quit
end if
Dim dictData, i, sLine, tim
tim = Timer()
'Load data
set dictData = CreateObject("Scripting.Dictionary")
Set f = oFSO.OpenTextFile(sInfile, 1, False, -1)
do while not f.AtEndOfStream
dictData.Add dictData.Count, f.ReadLine()
loop
f.Close
'Process data
for each i in dictData
sLine = dictData(i)
dictData(i) = Replace(sLine, Chr(0), "")
next
'Save processed data
sFinalData = Join(dictData.Items, vbCrLf)
Set oOutfile = oFSO.OpenTextFile(sOutfile, 2, True, -1)
oOutFile.Write sFinalData
oOutfile.Close
'Message
WScript.Echo "Data processed (" & (Timer() - tim) & " sec)"
'-------------------------------------------------------------------------------
sub CreateDataFile(ByVal sFilePath, ByVal nSizeInMB)
'-------------------------------------------------------------------------------
Dim sLine, arrData, i, iMax, sData, tim
rem tim = Timer()
sLine = String(255, "A") & Chr(0) & String(254, "B")
iMax = CLng((nSizeInMB*1024*1024)/(Len(sLine)*2)) 'Unicode chars take 2 bytes
ReDim arrData(iMax)
for i = 0 to iMax
arrData(i) = sLine
next
sData = Join(arrData, vbCrLf)
set oFile = oFSO.CreateTextFile(sFilePath, True, True)
oFile.Write sData
oFile.Close
rem WScript.Echo "Data created (" & (Timer() - tim) & " sec)"
end sub

Writeline / Readline

I'm trying to get a script to read a file and display the content. However, I need to only display 5 lines per window. How can I limit the display of the file?
Set MyFile = fso.OpenTextFile(FileName, ForReading)
Do While MyFile.AtEndOfStream <> True
TextLine = MyFile.ReadLine
MsgBox TextLine,0, "Student Information"
Loop
MyFile.Close
SOLUTION:
I got the solution! Here it comes:
Set MyFile = fso.OpenTextFile(FileName, ForReading)
Do While MyFile.AtEndOfStream <> True
TextLine = textline & MyFile.ReadLine & VBCR
counter = counter + 1
if (counter mod 5 = 0) then
MsgBox TextLine,0, "Petar Moraliev"
textline = ""
end if
Loop
MsgBox TextLine,0, "Petar Moraliev"
MyFile.Close
You need an array of cnLines (e.g. 5) elements to store each range of lines from the file. If that (ring) buffer is full, do your output (e.g. MsgBox). Just be careful at the end: are there still lines in the buffer?
In code:
Option Explicit
Const cnLines = 5
Dim nUB : nUB = cnLines - 1
Dim tsIn : Set tsIn = CreateObject("Scripting.FileSystemObject").OpenTextFile(".\23117849.txt")
Dim nIdx : nIdx = nUB
ReDim aLines(nUB)
Do Until tsIn.AtEndOfStream
nIdx = (tsIn.Line - 1) Mod cnLines
aLines(nIdx) = tsIn.ReadLine()
If nIdx = nUB Then
WScript.Echo Join(aLines, " * ") ' MsgBox Join(aLines, vbCrLf)
End If
Loop
tsIn.Close
If Not nIdx = nUB Then
ReDim Preserve aLines(nIdx)
WScript.Echo Join(aLines, " * ") ' MsgBox Join(aLines, vbCrLf)
End If
output (for a file of 11 lines):
cscript 23117849.vbs
1 * 2 * 3 * 4 * 5
6 * 7 * 8 * 9 * 10
11

Read data from ini file

i have a vbscript that takes input file name
the code is
Dim tsout: Set tsout = gofs.CreateTextFile("C:\....csv")
Dim tsin: Set tsin = gofs.OpenTextFile("C:\.....csv")
how can i configure this so that path createTextFile(....) is read from config file(.ini)
the file path for creating and writing output-to, must be taken from ini file
this is my ini file
// my ini file
[Read_file]
tsout=E:.....tt.csv
tsin=E:\....gt.csv
[col]
Number1=4
Number2=5
A simple version of an .ini file parser:
Option Explicit
Dim goFS : Set goFS = CreateObject("Scripting.FileSystemObject")
'WScript.Quit demoReadFile()
WScript.Quit demoReadIniFile()
Function demoReadFile()
demoReadFile = 0
Dim tsIn : Set tsIn = goFS.OpenTextFile(".\21825192.ini")
Do Until tsIn.AtEndOfStream
Dim sLine : sLine = tsIn.ReadLine()
WScript.Echo tsIn.Line - 1, sLine
Loop
tsIn.Close
End Function
Function demoReadIniFile()
demoReadIniFile = 0
Dim dicIni : Set dicIni = ReadIniFile(".\21825192.ini")
Dim sSec, sKV
For Each sSec In dicIni.Keys()
WScript.Echo "---", sSec
For Each sKV In dicIni(sSec).Keys()
WScript.Echo " ", sKV, "=>", dicIni(sSec)(sKV)
Next
Next
WScript.Echo dicIni("tsout")("Path")
End Function
Function ReadIniFile(sFSpec)
Dim dicTmp : Set dicTmp = CreateObject("Scripting.Dictionary")
Dim tsIn : Set tsIn = goFS.OpenTextFile(sFSpec)
Dim sLine, sSec, aKV
Do Until tsIn.AtEndOfStream
sLine = Trim(tsIn.ReadLine())
If "[" = Left(sLine, 1) Then
sSec = Mid(sLine, 2, Len(sLine) - 2)
Set dicTmp(sSEc) = CreateObject("Scripting.Dictionary")
Else
If "" <> sLine Then
aKV = Split(sLine, "=")
If 1 = UBound(aKV) Then
dicTmp(sSec)(Trim(aKV(0))) = Trim(aKV(1))
End If
End If
End If
Loop
tsIn.Close
Set ReadIniFile = dicTmp
End Function
output:
cscript 21825192.vbs
1 [pipapo]
2 Path=E:\dont\find\me.csv
3 Some = thing else
4
5 [tsout]
6 Path=E:\where\ever\output.csv
7 abc=def
cscript 21825192.vbs
--- pipapo
Path => E:\dont\find\me.csv
Some => thing else
--- tsout
Path => E:\where\ever\output.csv
abc => def
E:\where\ever\output.csv
(see this answer for background)
Update wrt comment/edit:
I added your sections to my sample .ini file:
type 21825192.ini
[pipapo]
Path=E:\dont\find\me.csv
Some = thing else
[tsout]
Path=E:\where\ever\output.csv
abc=def
[Read_file]
tsout=E:.....tt.csv
tsin=E:\....gt.csv
[col]
Number1=4
Number2=5
and - just for clarity - changed the final output line of my demoReadIniFile() function to:
WScript.Echo "tsout.Path", dicIni("tsout")("Path")
WScript.Echo "Read_file.tsin", dicIni("Read_file")("tsin")
WScript.Echo "col.Number2", dicIni("col")("Number2")
The output:
cscript 21825192.vbs
--- pipapo
Path => E:\dont\find\me.csv
Some => thing else
--- tsout
Path => E:\where\ever\output.csv
abc => def
--- Read_file
tsout => E:.....tt.csv
tsin => E:\....gt.csv
--- col
Number1 => 4
Number2 => 5
tsout.Path E:\where\ever\output.csv
Read_file.tsin E:\....gt.csv
col.Number2 5
So I don't understand at all why accessing 'the col section taking out number1=4 and Number2=5' causes any problems.
VBS do not support IniFile class. You need to create own parser of INI file. Other solution (also with creating own parsing functions, but much easy than to parse INI file): save TAB delimited data, for example: first comming OUTgoing file, than TAB char, than INcomming file.
Ekkehard's demo tweaked for Classic ASP:
Function demoReadIniFile()
demoReadIniFile = 0
Dim dicIni : Set dicIni = ReadIniFile("c:\path\to\21825192.ini")
Dim sSec, sKV
For Each sSec In dicIni.Keys()
response.write "---" & sSec & "<br>"
For Each sKV In dicIni(sSec).Keys()
response.write " " & sKV & " => " & dicIni(sSec)(sKV) & "<br>"
Next
Next
' response.write dicIni("tsout")("Path") & "<br>"
End Function
His ReadIniFile() works as written.

vbscript dictonary problem

I am using dictonary in VBscript. I have some problems that I don't understand some of the behaviour:
Dim CmdData
Set CmdData = CreateObject("System.Dictonary")
CmdData.Add "11", "tttzz"
CmdData.Add "sssid", "KRN"
WScript.Echo(" ZZZZZZZZ= " & CmdData.Count) 'It prints zero and not 2
Dim s
s = CmdData.Item("11")
alert(s)
WScript.Echo(s) 'It prints empry box and not tttzz
Dim a, j
a = CmdData.Keys
For j = 0 To CmdData.Count -1
WScript.Echo(" ZZZZZZZZ= " & CmdData.Count)
WScript.Echo(a(j)) ' doesn not print
Next
If (CmdData.Exists("-ad")) Then
'WScript.Echo (" RR ") ' It prints it although not in the dictonary
End If
Thanks
VBScript's Dictionary is "Scripting.Dictionary":
>> set syd = CreateObject("System.Dictionary")
>> syd.add "a",1
>>
Error Number: 429
Error Description: ActiveX component can't create object
>> set scd = CreateObject("Scripting.Dictionary")
>> scd.add "a",1
>> WScript.Echo scd.Count, scd("a")
>>
1 1

Resources