Go Back   Winamp & SHOUTcast Forums > Developer Center > NSIS Discussion

Reply
Thread Tools Search this Thread Display Modes
Old 16th May 2017, 20:48   #1
r2du-soft
Senior Member
 
r2du-soft's Avatar
 
Join Date: Nov 2013
Location: Iran
Posts: 221
Question search string in a text file and write that string line exist to another text file

hi
i search word "Used=/" in file "$ExeDir\HKSCS.txt" and read the line that the word is found and write that line to another file "$ExeDir\Dissociation.log"...

in HKSCS.txt file,found 368 item and some times more...

this codes work fine but application low speed.
It takes a lot of time at any time to read the file and the new file to be written.


HTML Code:
!include "MUI2.nsh"

!macro WriteToFile NewLine File String
  !if `${NewLine}` == true
  Push `${String}$\r$\n`
  !else
  Push `${String}`
  !endif
  Push `${File}`
  Call WriteToFile
!macroend
!define WriteToFile "!insertmacro WriteToFile false"
!define WriteLineToFile "!insertmacro WriteToFile true"

Function FileSearch
Pop $7 ;~~~~Piotrek occurance numberw
Exch $R0 ;search for
Exch
Exch $R1 ;input file
Push $R2
Push $R3
Push $R4
Push $R5
Push $R6
Push $R7
Push $R8
Push $R9
 
 
  StrLen $R4 $R0
  StrCpy $R7 0
  StrCpy $R8 0
  ;~~~~Piotrek start
  StrCpy $9 0
  ${If} $7 == ""
	StrCpy $7 0 ; occurence number user specified
  ${EndIf}
  ;~~~~Piotrek end
  ClearErrors
  FileOpen $R2 $R1 r
  IfErrors Done
 
  LoopRead:
    ClearErrors
    FileRead $R2 $R3
    IfErrors DoneRead
	IntOp $9 $9 + 1 ;Piotrek
 
    IntOp $R7 $R7 + 1
    StrCpy $R5 -1
    StrCpy $R9 0
 
    LoopParse:
      IntOp $R5 $R5 + 1
      StrCpy $R6 $R3 $R4 $R5
      StrCmp $R6 "" 0 +4
        StrCmp $R9 1 LoopRead
          IntOp $R7 $R7 - 1
          Goto LoopRead
 
      StrCmp $R6 $R0 0 LoopParse
        StrCpy $R9 1
        IntOp $R8 $R8 + 1
		;~~~~Piotrek start
		${If} $R8 == $7 ;if occurence is specified - outputs a specified occurence if not last occurence is output]
			StrCpy $0 $9
			StrCpy $7 "-1"
		${ElseIf} $7 == 0
			StrCpy $0 $9
		${EndIf}
		;~~~~Piotrek end
        Goto LoopParse
 
  DoneRead:
    FileClose $R2
  Done:
    StrCpy $R0 $R8
    StrCpy $R1 $R7
 
Pop $R9
Pop $R8
Pop $R7
Pop $R6
Pop $R5
Pop $R4
Pop $R3
Pop $R2
Exch $R1 ;number of lines found on
Exch
Exch $R0 ;output count found
Push $0 ;You need to pop that out after function call as first parameter ````Piotrek
FunctionEnd

Function ReadFileLine
Exch $0 ;file
Exch
Exch $1 ;line number
Push $2
Push $3
 
  FileOpen $2 $0 r
 StrCpy $3 0
 
Loop:
 IntOp $3 $3 + 1
  ClearErrors
  FileRead $2 $0
  IfErrors +2
 StrCmp $3 $1 0 loop
  FileClose $2
 
Pop $3
Pop $2
Pop $1
Exch $0
FunctionEnd

Function ReplaceOnLine
Exch $R0 ;file
Exch
Exch $R1 ;line
Exch 2
Exch $R2 ;replace with
Exch 2
Exch 3
Exch $R3 ;string to replace
Exch 3
Push $R4
Push $R5
Push $R6
Push $R7
Push $R8
Push $R9
Push $9
 FileOpen $R4 $R0 r
 GetTempFileName $R5
 FileOpen $R6 $R5 w
Top:
  FileRead $R4 $R7
  IntOp $R8 $R8 + 1
  StrCmp $R8 $R1 +3
  FileWrite $R6 $R7
  Goto Top
   StrLen $9 $R3
Loop_Top:
   StrCpy $R8 0
Loop:
   IntOp $R8 $R8 - 1
   StrCpy $R9 $R7 $9 $R8
   StrCmp $R9 "" Finish
   StrCmp $R9 $R3 0 Loop
    StrCpy $R9 $R7 $R8
    IntOp $R8 $R8 + $9
    StrCpy $R7 $R7 "" $R8
    StrCpy $R7 $R9$R2$R7
detailprint $R7
    FileWrite $R6 $R7
    Goto Loop_Top
Finish:
  ClearErrors
  FileRead $R4 $R7
  IfErrors +3
  FileWrite $R6 $R7
  Goto Finish
FileClose $R4
FileClose $R6
SetDetailsPrint none
Delete $R0
Rename $R5 $R0
SetDetailsPrint both
Pop $9
Pop $R9
Pop $R8
Pop $R7
Pop $R6
Pop $R5
Pop $R4
Pop $R3
Pop $R2
Pop $R1
Pop $R0
FunctionEnd

Function WriteToFile
Exch $0 ;file to write to
Exch
Exch $1 ;text to write
 
  FileOpen $0 $0 a #open file
  FileSeek $0 0 END #go to end
  FileWrite $0 $1 #write to file
  FileClose $0
 
Pop $1
Pop $0
FunctionEnd
 

  






Section


  Delete /REBOOTOK '$ExeDir\Dissociation.log'
  
  DoAgain:
		Push "$ExeDir\HKSCS.txt"
		Push "Used=/"
		Push 1 # line should be displayed for occurance number of the searched string, if empty string is passed or 0 the last occurance will be displayed
		Call FileSearch
		Pop $2 # the line number the string was found for specified occurance number
		Pop $0 #Number of times found throughout
		StrCmp $0 0 end 0 ;----------------------------------------
		Pop $1 #Number of lines found on
		;StrCmp $0 0 +2
		;MessageBox MB_OK "$\"hello$\" string was found in the file $0 times on $1 lines and the first line was $2"
		;string was found in the file $0
		;on $1 lines 
		;the first line was $2
		DetailPrint "$0"
		;----------------------------------------
		Push $2 ;number of first line find word on that
		Push "$ExeDir\HKSCS.txt"
		Call ReadFileLine
		Pop $0 ;string text
		;MessageBox MB_OK "$0"
		;----------------------------------------
		${WriteToFile} "$ExeDir\Dissociation.log" "$0"
		;----------------------------------------
		Push "" ;text in line to replace
		Push "" ;replace with
		Push $2 ;line to replace on
		Push "$ExeDir\HKSCS.txt" ;file to replace in
		Call ReplaceOnLine
		Goto DoAgain
  
  
  end:
  SetDetailsPrint both
DetailPrint "$0 | Finished."
SetDetailsPrint none
SectionEnd



What is the script problem,Why it works slowly?


Download Script and HKSCS.txt file
Attached Files
File Type: zip Search String and write string line to new file.zip (115.7 KB, 20 views)
r2du-soft is offline   Reply With Quote
Old 16th May 2017, 22:17   #2
JasonFriday13
Major Dude
 
JasonFriday13's Avatar
 
Join Date: May 2005
Location: New Zealand
Posts: 844
Well, it's slow because the functions are designed for single use, and because they are looped (in fact, nested loops), it's re-reading the file many times from the disk, which is why it's slow.

The code needs to be changed so that the file is only read once for each line, then do all the string searching on that line for the info you need.

"Only a MouseHelmet will save you from a MouseTrap" -Jason Ross (Me)
NSIS 3 POSIX Ninja
Wiki Profile
JasonFriday13 is offline   Reply With Quote
Old 17th May 2017, 02:21   #3
r2du-soft
Senior Member
 
r2du-soft's Avatar
 
Join Date: Nov 2013
Location: Iran
Posts: 221
Question

thanks mr JasonFriday13

problem solved with you'r help


The first method:
HTML Code:
!include "x64.nsh"


Function FileSearch
!include "x64.nsh"


Function FileSearch
Delete /REBOOTOK '$ExeDir\Dissociation.log'

Pop $7 ;~~~~Piotrek occurance numberw
Exch $R0 ;search for
Exch
Exch $R1 ;input file
Push $R2
Push $R3
Push $R4
Push $R5
Push $R6
Push $R7
Push $R8
Push $R9
 
 
  StrLen $R4 $R0
  StrCpy $R7 0
  StrCpy $R8 0
  ;~~~~Piotrek start
  StrCpy $9 0
  ${If} $7 == ""
	StrCpy $7 0 ; occurence number user specified
  ${EndIf}
  ;~~~~Piotrek end
  ClearErrors
  FileOpen $1 "$EXEDIR\Dissociation.log" w
  FileOpen $R2 $R1 r
  IfErrors Done
 
  LoopRead:
    ClearErrors
    FileRead $R2 $R3
    IfErrors DoneRead
	IntOp $9 $9 + 1 ;Piotrek
  ;MessageBox MB_OK "$9"
    IntOp $R7 $R7 + 1
    StrCpy $R5 -1
    StrCpy $R9 0
 
    LoopParse:
      IntOp $R5 $R5 + 1
      StrCpy $R6 $R3 $R4 $R5
      StrCmp $R6 "" 0 +4
        StrCmp $R9 1 LoopRead
          IntOp $R7 $R7 - 1
          Goto LoopRead
 
      StrCmp $R6 $R0 0 LoopParse
        StrCpy $R9 1
        IntOp $R8 $R8 + 1
		;~~~~Piotrek start
		${If} $R8 == $7 ;if occurence is specified - outputs a specified occurence if not last occurence is output***93;
			StrCpy $0 $9
			StrCpy $7 "-1"
		${ElseIf} $7 == 0
			StrCpy $0 $9
		${EndIf}
		;Sleep 555
		;Call RetuenProcess
			;${StrRep} $R3 $R3 "$\r$\n" ""
			;${StrRep} $R3 $R3 "$\r" ""
			;${StrRep} $R3 $R3 "$\n" ""
		  ;MessageBox MB_OK "1.First String In Line: $0 \
		  ;$\r$\n2.Find String In Line: $9 \
		  ;$\r$\n3.Line $9 String IS: $R3 \
		  ;$\r$\n4.Find String $R8 Time."
		  
		  
		  DetailPrint "Time:$R8_Line:$9"
			FileWrite $1 "$R3" ;$\r$\n
			
		  
		  
		;~~~~Piotrek end
        Goto LoopParse
  DoneRead:
		  ;MessageBox MB_OK "[$0]_[$1]_[$2]_[$3]_[$4]_[$5]_[$6]_[$7]_[$8]_[$9]_[$R1]_[$R2]_[$R3]_[$R4]_[$R5]_[$R6]_[$R7]_[$R8]_[$R9]"
    FileClose $R2
	FileClose $1
  Done:
    StrCpy $R0 $R8
    StrCpy $R1 $R7
 
Pop $R9
Pop $R8
Pop $R7
Pop $R6
Pop $R5
Pop $R4
Pop $R3
Pop $R2
Exch $R1 ;number of lines found on
Exch
Exch $R0 ;output count found
Push $0 ;You need to pop that out after function call as first parameter ````Piotrek
FunctionEnd







Section

		Push "$ExeDir\HKSCS.txt"
		Push "Used=/"
		Push 1 # line should be displayed for occurance number of the searched string, if empty string is passed or 0 the last occurance will be displayed
		Call FileSearch

SectionEnd


The second method:

HTML Code:
!include "x64.nsh"


Function WriteToFile
Exch $0 ;file to write to
Exch
Exch $1 ;text to write
 
  FileOpen $0 $0 a #open file
  FileSeek $0 0 END #go to end
  FileWrite $0 $1 #write to file
  FileClose $0
 
Pop $1
Pop $0
FunctionEnd
 
!macro WriteToFile NewLine File String
  !if `${NewLine}` == true
  Push `${String}$\r$\n`
  !else
  Push `${String}`
  !endif
  Push `${File}`
  Call WriteToFile
!macroend
!define WriteToFile `!insertmacro WriteToFile false`
!define WriteLineToFile `!insertmacro WriteToFile true`


Function FileSearch
Delete /REBOOTOK '$ExeDir\Dissociation.log'

Pop $7 ;~~~~Piotrek occurance numberw
Exch $R0 ;search for
Exch
Exch $R1 ;input file
Push $R2
Push $R3
Push $R4
Push $R5
Push $R6
Push $R7
Push $R8
Push $R9
 
 
  StrLen $R4 $R0
  StrCpy $R7 0
  StrCpy $R8 0
  ;~~~~Piotrek start
  StrCpy $9 0
  ${If} $7 == ""
	StrCpy $7 0 ; occurence number user specified
  ${EndIf}
  ;~~~~Piotrek end
  ClearErrors
  FileOpen $R2 $R1 r
  IfErrors Done
 
  LoopRead:
    ClearErrors
    FileRead $R2 $R3
    IfErrors DoneRead
	IntOp $9 $9 + 1 ;Piotrek
  ;MessageBox MB_OK "$9"
    IntOp $R7 $R7 + 1
    StrCpy $R5 -1
    StrCpy $R9 0
 
    LoopParse:
      IntOp $R5 $R5 + 1
      StrCpy $R6 $R3 $R4 $R5
      StrCmp $R6 "" 0 +4
        StrCmp $R9 1 LoopRead
          IntOp $R7 $R7 - 1
          Goto LoopRead
 
      StrCmp $R6 $R0 0 LoopParse
        StrCpy $R9 1
        IntOp $R8 $R8 + 1
		;~~~~Piotrek start
		${If} $R8 == $7 ;if occurence is specified - outputs a specified occurence if not last occurence is output***93;
			StrCpy $0 $9
			StrCpy $7 "-1"
		${ElseIf} $7 == 0
			StrCpy $0 $9
		${EndIf}
		;Sleep 555
		;Call RetuenProcess
			;${StrRep} $R3 $R3 "$\r$\n" ""
			;${StrRep} $R3 $R3 "$\r" ""
			;${StrRep} $R3 $R3 "$\n" ""
		  ;MessageBox MB_OK "1.First String In Line: $0 \
		  ;$\r$\n2.Find String In Line: $9 \
		  ;$\r$\n3.Line $9 String IS: $R3 \
		  ;$\r$\n4.Find String $R8 Time."
		  
		  
		  DetailPrint "Time:$R8_Line:$9"
			${WriteToFile} "$EXEDIR\Dissociation.log" "$R3"

		  
		  
		;~~~~Piotrek end
        Goto LoopParse
  DoneRead:
		  ;MessageBox MB_OK "[$0]_[$1]_[$2]_[$3]_[$4]_[$5]_[$6]_[$7]_[$8]_[$9]_[$R1]_[$R2]_[$R3]_[$R4]_[$R5]_[$R6]_[$R7]_[$R8]_[$R9]"
    FileClose $R2
  Done:
    StrCpy $R0 $R8
    StrCpy $R1 $R7
 
Pop $R9
Pop $R8
Pop $R7
Pop $R6
Pop $R5
Pop $R4
Pop $R3
Pop $R2
Exch $R1 ;number of lines found on
Exch
Exch $R0 ;output count found
Push $0 ;You need to pop that out after function call as first parameter ````Piotrek
FunctionEnd







Section

		Push "$ExeDir\HKSCS.txt"
		Push "Used=/"
		Push 1 # line should be displayed for occurance number of the searched string, if empty string is passed or 0 the last occurance will be displayed
		Call FileSearch

SectionEnd

The first method and The second method just difference is write to file...


thanks again
r2du-soft is offline   Reply With Quote
Reply
Go Back   Winamp & SHOUTcast Forums > Developer Center > NSIS Discussion

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump