Sign in to follow this  
Followers 0
Jibberish

Replacing String in a text file

6 posts in this topic

#1 ·  Posted

Junior Programmer here... 

Not much experience with opening, changing and closing files.

I am trying to replace strings in a Text file except StringReplace does not actually replace the text.

Here is a sample of my code...

#include <File.au3>
#include <MsgBoxConstants.au3>
#include <WinAPIFiles.au3>

Local $iStrReturn = 0
Local $hFile
Local $sText
Local $sNewText

; Location of File to be read
$sFileName = "C:\Temp\MyPlayer.exe.config"

; The default is FALSE. We want to change this to TRUE
$bLoopChecked = True

CheckBox()


Func Checkbox()
    $hFile = FileOpen($sFileName,$FO_READ) ; Open file in read mode to get text
    If $hFile = -1 Then
        MsgBox($MB_SYSTEMMODAL, "", "An error occurred when Opening the file.")
        Exit
    EndIf
    FileSetPos($hFile, 0, 0)    ; No idea if I need to do this, grasping at straws
    $sText = FileRead($hFile)   ; Read the file into $sText
    If $sText = 1 Then
        MsgBox($MB_SYSTEMMODAL, "", "An error occurred when reading/writing the file.")
        Exit
    Else
        FileClose($hFile)       ; Finished reading the file into $sText, so close the file.
        FileFlush($hFile)       ; Manual says to use FileFlush between File Close and Open so here it is
    EndIf

    MsgBox(0,"Before Replacement",$sText)   ; Displays the text read from the file to make sure something is there.

    ; Loop Check
    If $bLoopChecked = True Then
        ; Find the string return > 0 for success
        $iStrReturn = StringInStr('"<add key="LoopCheckbox" value=""False" />"', "False")
        ;MsgBox(0,"", "LoopCheckBox is " & $iStrReturn)
        If $iStrReturn > 0 Then     ; If StringInStr returned > 0 the it found the string!
            ; The Meat of the code. This is where we have to replace "False" with "True"
            $sNewText = StringReplace($sText, '"<add key="LoopCheckbox" value="False" />"', '"<add key="LoopCheckbox" value="True" />"')
            MsgBox(0,"After Replacement",$sNewText) ; Display the text to see if it worked.
            $hFile = FileOpen($sFileName,$FO_OVERWRITE) ; Reopen the file to write to it, overwriting everything.
            FileWrite($hFile,$sNewText)                 ; Write the text to the file
            FileClose($hFile)                           ; Close the file
        EndIf
    EndIf
EndFunc

This is the file I am reading...

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
  </startup>
  <appSettings>
    <add key="LoopCheckbox" value="false"/>
  </appSettings>
</configuration>

I tried opening the file with $FO_UTF8 and $FO_UTF8_NOBOM but got errors opening the file.

The MsgBox "After Replacement" shows the value is still false.

Share this post


Link to post
Share on other sites



#2 ·  Posted

@Jibberish one of our Regex experts will doubtless wander along and provide something more elegant, but for a simple method this works well for me. For this example my file is sitting on the desktop, change your file path accordingly. Let me know if you have any questions:

#include <File.au3>

Local $aFile, $sText, $sFile = @DesktopDir & "\test.xml"
    _FileReadToArray($sFile, $aFile)

    For $a = 1 To $aFile[0]
        If StringInStr($aFile[$a], '"LoopCheckbox" value="false"') Then
            $sText = StringReplace(FileReadLine($sFile, $a), '="false"', '="true"')
            _FileWriteToLine($sFile, $a, $sText, 1)
        EndIf
    Next

 

1 person likes this

√-1 2^3 ∑ π, and it was delicious!

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

maybe:

Dedug version:

Global $sFile = "C:\Temp\MyPlayer.exe.config"
Global $bLoopChecked = True

Local $sValueTrue = '<add key="LoopCheckbox" value="true"/>'
Local $sValueFalse = '<add key="LoopCheckbox" value="false"/>'

Local $xFileEncoding = FileGetEncoding($sFile), $xContent = FileRead($sFile)
If @error Or Not FileExists($sFile) Then Exit MsgBox(48, "ERROR", "Read file error: " & $sFile)


Local $sCheckTrue = StringInStr($xContent, $sValueTrue)
Local $sCheckFalse = StringInStr($xContent, $sValueFalse)
ConsoleWrite("- Before:" & @CRLF & $xContent & @CRLF)
If $sCheckFalse And Not $bLoopChecked Then
    Exit MsgBox(48, "Set value to: " & $bLoopChecked, "But cureent LoopCheckbox=false")
ElseIf $sCheckTrue And $bLoopChecked Then
    Exit MsgBox(48, "Set value to: " & $bLoopChecked, "But cureent LoopCheckbox=true")
EndIf

If $sCheckFalse And $bLoopChecked Then
    MsgBox(64, "Will Set value to: " & $bLoopChecked, "Cureent LoopCheckbox=false")
    $xContent = StringReplace($xContent, $sValueFalse, $sValueTrue)
;~  ConsoleWrite("-" & @extended & @CRLF)
Else
    MsgBox(64, "Will Set value to: " & $bLoopChecked, "Cureent LoopCheckbox=true")
    $xContent = StringReplace($xContent, $sValueTrue, $sValueFalse)
;~  ConsoleWrite("-" & @extended & @CRLF)
EndIf
Local $hOpen = FileOpen($sFile, 2 + 8 + $xFileEncoding)
FileWrite($hOpen, $xContent)
FileClose($hOpen)

ConsoleWrite("+ After:" & @CRLF & $xContent & @CRLF)

If (StringInStr($xContent, $sValueTrue) And $bLoopChecked) Or (StringInStr($xContent, $sValueFalse) And Not $bLoopChecked) Then
    Exit MsgBox(64, "Set value to: " & $bLoopChecked, "Set value OK")
Else
    Exit MsgBox(48, "Set value to: " & $bLoopChecked, "Set value ERROR")
EndIf

 

Product version:

Global $sFile = "C:\Temp\MyPlayer.exe.config"
Global $bLoopChecked = True

If _SetLoopChecked($bLoopChecked, $sFile) Then
    MsgBox(64, "Set value to: " & $bLoopChecked, "Set value OK" & @CRLF & "File: " & $sFile)
Else
    MsgBox(48, "Set value to: " & $bLoopChecked, "Set value ERROR" & @CRLF & "File: " & $sFile)
EndIf

Func _SetLoopChecked($iTrue, $sFile = @ProgramFilesDir & "\MyApp\MyPlayer.exe.config")
    Local $xFileEncoding = FileGetEncoding($sFile), $xContent = FileRead($sFile)
    If @error Or Not FileExists($sFile) Then Return SetError(1, 0, 0)
    Local $sValueTrue = '<add key="LoopCheckbox" value="true"/>'
    Local $sValueFalse = '<add key="LoopCheckbox" value="false"/>'
    Local $sCheckTrue = StringInStr($xContent, $sValueTrue)
    Local $sCheckFalse = StringInStr($xContent, $sValueFalse)
    If $sCheckFalse And Not $iTrue Then
        Return SetError(0, 1, 1)
    ElseIf $sCheckTrue And $iTrue Then
        Return SetError(0, 1, 1)
    EndIf
    If $sCheckFalse And $iTrue Then
        $xContent = StringReplace($xContent, $sValueFalse, $sValueTrue)
    Else
        $xContent = StringReplace($xContent, $sValueTrue, $sValueFalse)
    EndIf
    Local $hOpen = FileOpen($sFile, 2 + 8 + $xFileEncoding)
    Local $WOK = FileWrite($hOpen, $xContent)
    FileClose($hOpen)
    If $WOK And ((StringInStr($xContent, $sValueTrue) And $iTrue) Or (StringInStr($xContent, $sValueFalse) And Not $iTrue)) Then Return SetError(0, 0, 1)
    Return SetError(2, 0, 0)
EndFunc   ;==>_SetLoopChecked

 

Edited by Trong
add version

Regards,
 

Share this post


Link to post
Share on other sites

#4 ·  Posted

6 hours ago, JLogan3o13 said:

@Jibberish one of our Regex experts will doubtless wander along and provide something more elegant, but for a simple method this works well for me. For this example my file is sitting on the desktop, change your file path accordingly. Let me know if you have any questions:

#include <File.au3>

Local $aFile, $sText, $sFile = @DesktopDir & "\test.xml"
    _FileReadToArray($sFile, $aFile)

    For $a = 1 To $aFile[0]
        If StringInStr($aFile[$a], '"LoopCheckbox" value="false"') Then
            $sText = StringReplace(FileReadLine($sFile, $a), '="false"', '="true"')
            _FileWriteToLine($sFile, $a, $sText, 1)
        EndIf
    Next

 

@JLogan3o13

Always the smartest code :) :bye:


Click here to see my signature:

Spoiler

I will always thank you for the time you spent for me.
I'm here to ask, and from your response, I'd like to learn.
By my knowledge, I can help someone else, and "that someone" could help in turn another, and so on.

Share this post


Link to post
Share on other sites

#5 ·  Posted

Or you could go with @Trong's Rube Goldberg script :)

 


√-1 2^3 ∑ π, and it was delicious!

Share this post


Link to post
Share on other sites

#6 ·  Posted

Wow! The support here is amazing! I'll try all these out and try to understand why these work and mine doesn't. Always learning...!

Cheers,

Jibberish

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0

  • Similar Content

    • num1g8rfan
      By num1g8rfan
      Hi All,
      I have a script whose sole purpose is to walk through about 15,000 - 20,000 files in a single directory structure, making modifications to 5 or 6 lines within each file.  Simple.  I have a small splash screen that is simply counting how many files have been completed out of the overall total.  The script is functioning fine and the splash screams through the initial files, but through time begins to slow to a crawl (It becomes noticeable after about 1,000 to 1,500 files).  
      I have used a combination of methods to write to the file, but none of which appear to make much of any difference:
      Local $FileOpen = FileOpen($FileInList,1) FileWriteLine($FileOpen,@CRLF) FileClose($FileOpen) OR
      FileWriteLine($FileHandle, $NewLineString & @CRLF) OR
      Local $FileHandle = FileOpen($FileInList,2) _FileWriteFromArray($FileHandle,$FileContentArray,1) FileClose($FileHandle) I have checked and the CPU and memory are fine.  My current work-around is to create 5-10 separate directory structures from the original one that contains 20,000 files, run the script and then combine them again in the end.  It works, but isn't very portable.  Any ideas?
      Cleanup_AutoITPost.au3
    • MrSparty1995
      By MrSparty1995
      I have a good handle on how to read a file line by line, and search for a given string.
      Basically using, FileOpen, FileReadLine, and StringInStr.
      I have been trying to figure out why my search keeps coming back with no match.
      For example, if my string line was "Where is Waldy", and I was searching for Waldy that comes back fine.
      But in my file, Let's say it is
      Where is "Waldy"
      So i read that line in and do a search for Waldy, but i comes back with no match since there is quotes around it.
      Is there a way to resolve this?
      Here is my actual example
      The line comes back like this
          <JposEntry logicalName="LineDisp_iSC480">
      I'm searching for LineDisp_iSC480, but its coming back with no match due to the quotes.
      Thanks in advance, James
    • fmlk
      By fmlk
      Hello,
      In a main script I have added logging and that is working. Now I created another small script where I need also logging. So I used the same code:
      What is wrong? Why is the logfile not created?

      $default_delay = 2000
      $logFilePath = ("C:\AutoIT_TestLogs")
      DirCreate($logFilePath)
      $Logfile = FileOpen($logFilePath & "\GMS_install" & @MON & "/" & @MDAY & "/" & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC & ".log",1)
      FileWriteLine($logFile,@CR & @MON & "/" & @MDAY & "/" & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC & "_Install_licenses")
      Consolewrite("Install_licenses" & @CR)
      Run("C:\Users\factory\Desktop\LicenseInstaller\LicenseInstaller.exe","C:\Users\factory\Desktop\LicenseInstaller")
      Sleep(1000)
      WinWait("Gatan License Installer")
      WinActivate("Gatan License Installer")
      WinWaitActive("Gatan License Installer")
      ControlClick("[ACTIVE]","","[NAME:CMD_Install]")
      Sleep($default_delay)
       If WinExists("LicenseInstaller") Then
           WinActivate("LicenseInstaller")
            WinWaitActive("LicenseInstaller")
            ControlClick("[ACTIVE]","","[CLASS:Button; INSTANCE:1]")
              sleep($default_delay)
         EndIf
      FileWriteLine($logFile,@CR & @MON & "/" & @MDAY & "/" & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC & "_Licenses_Installed")
      Consolewrite("Licenses are installed" & @CR)
       
    • AnAdventurer
      By AnAdventurer
      Hello hello!
      As the title suggests, I am fairly new to AutoIt. In fact, I am new to scripting/coding in general! I've done a few Codecademy courses on CSS and HTML and perhaps Java though this was all a few years back. I've recently come across AutoIt and decided to give it a try since I do quite a few repetitive tasks on a daily basis. In the last couple of weeks I've managed to master (or at least get comfortable with) mouse clicks(left/right), window focus, sending key strokes, controls, and pixel search.
      Now let's get to the topic.
      At this point in time I've tried out a few simple IE scripts but I am having difficulty understanding some things and tying everything together into one tool.
      Specifically, I am struggling with this little bit of code I got from DaleHohm in his IE examples thread. Post #3 (The last example.)
      #include <IE.au3> $sImgDir = "c:\foo\"; Please make certain this folder already exists (silent failure if not) $sWebPage = "http://www.autoitscript.com/forum/index.php?"; webpage with images $oIE = _IECreate() _IENavigate($oIE, $sWebPage) $oIMGs = _IETagNameGetCollection($oIE.document, "img") ; Loop through all IMG tags and save file to local directory using INetGet For $oIMG in $oIMGs $sImgUrl = $oIMG.src $sImgFileName = $oIMG.nameProp INetGet($sImgUrl, $sImgDir & $sImgFileName) Next I have a couple questions about the code above.
      1) ".src" ".nameProp" What are these called? I figured out that I can change the .src to something like .href and it gets anything on the webpage with a .href tag but where can I learn more about these? I still haven't been able to figure out what ".nameProp" is for or what it does. Is there any documentation/list of all the different ".PurpleTextAfterAVariable" (Edit: Not sure why it's red in the above example, just checked SciTE and it's purple there) that I can use?
      2) I understand that the code above gets every "For $oIMG in $oIMGs" on the page but how can I make it only get the first 5? I've tried doing a "count" and a "for" but I am unsure what to replace the "For...in" statement with to keep the script functional. Is there a way to limit the _IETagNameGetCollection function to only get a specific amount of tags?
       
      Finally, the reason I can't just use the code as is.
      The site I am trying to get images from works in this way:
      A href= "Link-To-Picture.jpg" Img src= "Link-To-Picture-thumbnail.jpg" The script above downloads every single thumbnail from the image gallery which is great, it does what it's supposed to but I need the full resolution image.
      After changing the script to get anything with an "A href" tag it does what I need it to do, it gets every single image in full resolution... along with every single one of the 80-100 extra files/links to other sites that are listed under an "A href" tag.
       
      Now I've come up with two solutions but unfortunately, as I mentioned above. I don't know how to put my solution into the code above to make it work.
      Solution 1) Only get the first 5 instances of "A href" on the page.
      As mentioned above. I don't know how to do this.
      Solution 2) Read the entire page, find "-Thumbnail.jpg" replace with ".jpg" and use the script as is.
      I understand how to do a replace. All I am missing is how to do a replace within a field in the code of an IE page. I assume that I have to use the HTMLRead functions but how do I use/alter the data read?
      I really hope all of this make sense and that someone here will be able to help me figure out a solution to my issue or at least answer one of my questions! I do have plenty more questions and I am sure that I'll have even more by the time I figure this out.
      Thank you very much for your time!
    • SorryButImaNewbie
      By SorryButImaNewbie
      Hello, I try to pull some data from a webpage.
      I need the value of local currency compared to the euro. I can go and open the required API page on the required date interval, read in from elsewhere, its format in the memory of the script is like this: 20161005 so YYYYMMDD.
      The return string if I try to view the opened API's source code is simple, but if I use _IEBodyReadHTML, _IEDocReadHTML, _IEBodyReadText i get it back with a lot of html code (i guess, it looks like HTML, and one of them doesn't show any string in the MsgBox when I try to chechk it) about its color etc. I need dates and the corresponding currency exchange rates (these can be found between  <kozep>exchangerate</kozep>, but I need the first only after every month because the second is the avarage exchange rate of the month (i guessed this again).
      Now I have an approach which will work evantually I guess, but I'm pretty sure its not the standard aproach or how the creators of autoit envisiond the useage of their functions
      So I post my code here hoping, someone tells me how to do this simply and inteligently.
      Sorry for such question but I only used regex for much, much simplier tasks. My approach is to identify everything I dont need basicly, after getting rid of a few key problematic chars (like " ) and do this untill I'm only left with what I need. THe problem with this if anything change in the envierment the script has like 99,9999% chance to not run properly, and I would like to handle this better, even if APIs usually don't change that much according to my knowladge.
      Also I write this in a separat function for now, I will plan to call it from my other function which does different things with the corresponding excel files, among them is the calculation of local currency values of the bills with data from MNB (Hungarian National Bank or something)
      Here is my code so far, and what its gives back, I will update this with the pic from the source code I see from internet explorer and the webpage I see. Thank you for your help and insight!
      Func InternetRead() ;Create the URL for napiarfolyam API #cs http://api.napiarfolyam.hu/?bank=mnb&valuta=eur&datum=20160901&datumend=20160926 </penznem> után jön a használt árfolyam Példa Return: <item> <bank>mnb</bank> <datum>2016-09-06 11:25:18</datum> <penznem>EUR</penznem> <kozep>309.8500</kozep> <kozep>310.1700</kozep> </item> #ce ;Global $MinTime ;20160601000000 these are example variables I read in, during the function that will call this one ;Global $MaxTime ;20160610000000 Local $URLbase = "http://api.napiarfolyam.hu/?bank=mnb&valuta=eur" ;view-source: ;Local $MinTimeFormated = StringTrimRight($MinTime, 6) ;Local $MaxTimeFormated = StringTrimRight($MaxTime, 6) Local $URL = $URLbase & ("&datum=" & "20160601" & "&datumend=" & "20160603" & "") ;20160603 $MinTimeFormated, $MaxTimeFormated MsgBox(64, "Értesítés", "URL:" & $URL & "") Local $oIE = _IECreate($URL) Sleep(1000) Local $sHTML = _IEDocReadHTML($oIE) ;_IEBodyReadHTML - Is string but, MsgBox shows nothing ;_IEDocReadHTML - at least retunrs something (extra then what i see from thw source code, ctrl+u) ;_IEBodyReadText - at least retunrs something (extra then what i see from thw source code, ctrl+u) $sHTML = String($sHTML) If IsString($sHTML) Then MsgBox(64, "HTML String?", "The variable is a string") Else MsgBox(64, "HTML String?", "The variable is not a string") EndIf ;Variable is a String! ;StringSplit ;">datum</span>&gt;</a>" & "20160601" Local $Stuff = Chr(34) ;The " char ;Local $Stuff2 = "<a xmlns=http://www.w3.org/1999/xhtml class=collapse style=color: blue; marginleft: 2em; position: relative; href=#>&lt;<span style=color: rgb(153,0,0);>" Local $StringInput = $sHTML Local $sHTML = StringRegExpReplace($StringInput, "[-]", "") Local $StringInput = $sHTML Local $sHTML = StringStripWS($StringInput, $STR_STRIPLEADING + $STR_STRIPTRAILING + $STR_STRIPSPACES) Local $StringInput = $sHTML Local $sHTML = StringReplace($StringInput, $Stuff, "") ;Local $StringInput = $sHTML ;Local $sHTML = StringReplace($StringInput, $Stuff2, "") Local $StringInput = $sHTML Local $ValutaPosition = StringInStr($StringInput, "</valuta>") Local $sHTML = StringTrimLeft($StringInput, $ValutaPosition+8) Local $StringInput = $sHTML ;StringReplace($StringInput, "<a xmlns="http://" ;Local $StringInput = $sHTML ;StringInStr ;Local $sHTML = StringTrimLeft($StringInput, 1850) ;Local $aDays = StringSplit($sHTML, ">datum</span>&gt;</a>") ;_ArrayDisplay($aDays) ;If @error Then Exit MsgBox($MB_SYSTEMMODAL, "StringRegExpReplace Error", "Error listing:" & @CRLF & "@error = " & @error & ", @extended = " & @extended) MsgBox(64, "HTML String?", "$sHTML:" & $sHTML) EndFunc ;==>InternetRead  

      Edit:
      Sorry for the long post and I hope I was able to write dowm my problem in a way that others can understand, pls ask anything if you don't.