How to search/replace string in text-file?

Luc_VanDyck
Member, Moderator, Administrator Posts: 3,633
I have a text-file where I need to replace a given string to something else. The problem is that the lines in this text-file are > 1024 characters, so I can't use recFile.READ(txtLine) to read this file line by line.
Is it possible with STREAMS to read this file, search for the string, replace it with another value, and write it back to the file? Can someone post some C/AL Code please?
Is it possible with STREAMS to read this file, search for the string, replace it with another value, and write it back to the file? Can someone post some C/AL Code please?
No support using PM or e-mail - Please use this forum. BC TechDays 2024: 13 & 14 June 2024, Antwerp (Belgium)
0
Comments
-
Here's code I've used to read thru a file looking for a value using streams:
Name DataType Length
FTPUploadLog File
FTPUpLoadLogIStream InStream
FTPUploadLogTextLine Text 1024
//Open the upload log to check the file upload status
FTPUploadLog.TEXTMODE(TRUE);
IF NOT FTPUploadLog.OPEN(EDITradingPartnerDoc."Document Folder" + 'FTPUploadLog.txt') THEN BEGIN
FOR i := 1 TO 10 DO BEGIN
SLEEP(5000);
IF FTPUploadLog.OPEN(EDITradingPartnerDoc."Document Folder" + 'FTPUploadLog.txt') THEN
i := 11;
END;
END;
FTPUploadLog.CREATEINSTREAM(FTPUpLoadLogIStream);
UploadError := TRUE;
IF FTPUploadLog.LEN > 0 THEN
REPEAT
IF FTPUpLoadLogIStream.READTEXT(FTPUploadLogTextLine) > 0 THEN BEGIN
FTPLog.WRITE(FTPUploadLogTextLine);
IF COPYSTR(FTPUploadLogTextLine, 1, 3) = '226' THEN
UploadError := FALSE;
END;
UNTIL FTPUpLoadLogIStream.EOS;0 -
You are still using a variable FTPUploadLogTextLine with length of 1024 to parse your text-file. What happens if the value '226' you are looking for, occurs at position 1023, 1024 of Line 1 and on position 1 of Line 2?No support using PM or e-mail - Please use this forum. BC TechDays 2024: 13 & 14 June 2024, Antwerp (Belgium)0
-
I'm coding a test scenario for that now. I'll post it in a few minutes. I believe I can just continue to read 1024 characters until the end of the file, replacing the string I'm looking for with whatever I need it to be.
If it occurs more than once in a line (a "line" is a text string ending in CRLF) you want each occurace replaced correct?0 -
It could occur multiple times in the text-file. The text-fle is saved from a XML DOM object. Don't know if CRLF is used in this file.No support using PM or e-mail - Please use this forum. BC TechDays 2024: 13 & 14 June 2024, Antwerp (Belgium)0
-
Can you use a BigText variable to get past the 1024 length limit?0
-
Hi Luc,
If you have a working routine developed - why not just call it twice with the second call using a seek of let say 500 to capture the strings on the 1023 - 1025 overlap.0 -
here's a function to return the position of a string in a text file:
variables:
wordInt, posInt,toReturns (Integers)
char (Text len 1)
fiel File
inStream inStreamfunction indexOf(searchStr (Text),targetFile (Text)) returns int wordInt := 1; posInt := 0; toReturn := -1; file.OPEN(targetFile); file.CREATEINSTREAM(inStream); WHILE NOT inStream.EOS DO BEGIN inStream.READTEXT(char,1); IF NOT (char = '') THEN // this skips over line breaks BEGIN IF FORMAT(searchStr[wordInt]) = char THEN BEGIN IF toReturn < 0 THEN toReturn := posInt; wordInt += 1; END ELSE BEGIN toReturn := -1; wordInt := 1; END; IF wordInt = STRLEN(searchStr) + 1 THEN BEGIN file.CLOSE; EXIT(toReturn); END; posInt += 1; END; END; file.CLOSE; EXIT(-1);
replacing the string however seems more challenging...0 -
Sorry I couldn't get this posted yesterday before I had to pick my son up from school...
I've included the text file I created for testing as well.
This needs to be re-written it's very crude, but it has my idea. Plus I'm getting some strange character written in textfile2 - 00h?
I like jreynolds' idea of pulling it into a bigtext and operating on it. When I get more time I'm going to have to investigate that route.Variables ***** TextFile1@1000000003 : File; TextFile2@1000000002 : File; TextFile1InStream@1000000001 : InStream; TextFile2OutStream@1000000009 : OutStream; ReadTextLineNew@1000000000 : Text[1024]; ReadTextLineOld@1000000008 : Text[1024]; TextToFind@1000000006 : Text[120]; ReplacementText@1000000011 : Text[240]; CreatedTextLine@1000000010 : Text[120]; ***** TextToFind := 'Text Being Sought'; ReplacementText := 'Text Has Been Replaced'; //File to read from... TextFile1.TEXTMODE(TRUE); TextFile1.OPEN('C:\TEMP\TextFile1.txt'); TextFile1.CREATEINSTREAM(TextFile1InStream); //File to write to... TextFile2.TEXTMODE(TRUE); TextFile2.WRITEMODE(TRUE); TextFile2.CREATE('C:\TEMP\TextFile2.txt'); TextFile2.CREATEOUTSTREAM(TextFile2OutStream); REPEAT ReadTextLineOld := ReadTextLineNew; //I'm trying to account for replacing a shorter text string //with a longer text string so I'm reading in less characters //than the string can actually handle IF TextFile1InStream.READ(ReadTextLineNew, MAXSTRLEN(ReadTextLineNew) - STRLEN(TextToFind)) > 0 THEN BEGIN IF STRPOS(ReadTextLineNew, TextToFind) > 0 THEN BEGIN IF STRPOS(ReadTextLineNew, TextToFind) = 1 THEN ReadTextLineNew := ReplacementText + COPYSTR(ReadTextLineNew, STRLEN(TextToFind) + 1) ELSE ReadTextLineNew := COPYSTR(ReadTextLineNew, 1, STRPOS(ReadTextLineNew, TextToFind) - 1) + ReplacementText + COPYSTR(ReadTextLineNew, STRPOS(ReadTextLineNew, TextToFind) + STRLEN(TextToFind)); END; IF STRLEN(ReadTextLineOld) > 0 THEN BEGIN IF STRLEN(ReadTextLineOld) > (STRLEN(ReadTextLineOld) - STRLEN(TextToFind)) THEN BEGIN //Create a string from the end of the old string and the beginning of //the new string IF STRPOS(COPYSTR(ReadTextLineOld, STRLEN(ReadTextLineOld) - STRLEN(TextToFind)) + COPYSTR(ReadTextLineNew, 1, STRLEN(TextToFind)), TextToFind) > 0 THEN BEGIN ReadTextLineOld := COPYSTR(ReadTextLineOld, 1, STRLEN(ReadTextLineOld) - STRLEN(TextToFind) - 1); ReadTextLineNew := COPYSTR(ReadTextLineNew, STRLEN(TextToFind) + 1); CreatedTextLine := COPYSTR(ReadTextLineOld, STRLEN(ReadTextLineOld) - STRLEN(TextToFind)) + COPYSTR(ReadTextLineNew, 1, STRLEN(TextToFind)); IF STRPOS(CreatedTextLine, TextToFind) = 1 THEN CreatedTextLine := ReplacementText + COPYSTR(CreatedTextLine, STRLEN(TextToFind) + 1) ELSE CreatedTextLine := COPYSTR(CreatedTextLine, 1, STRPOS(CreatedTextLine, TextToFind) - 1) + ReplacementText + COPYSTR(CreatedTextLine, STRPOS(CreatedTextLine, TextToFind) + STRLEN(TextToFind)); END ELSE CreatedTextLine := ''; END ELSE BEGIN END; TextFile2OutStream.WRITE(ReadTextLineOld); IF STRLEN(CreatedTextLine) > 0 THEN TextFile2OutStream.WRITE(CreatedTextLine); END; END; UNTIL TextFile1InStream.EOS; TextFile2OutStream.WRITE(ReadTextLineNew); TextFile1.CLOSE; TextFile2.CLOSE;
This is the test file I created... 1234567890123456789012345678901234567890123456789012345678901234567890123ISA*00* *00* *ZZ*TEST BASIC *01*060018611 *01 0509*1441*U*00401*000000091*0*T*>~GS*PO*TEST BASIC*060018611*20010509*144 1*000000005*X*004010VICS~ST*850*0001~BEG*00*SA*643787**20011020~REF*DP*087~REF*MR*TRYUE~FOB*CC*OR*ORIGIN~CSH*Y~ITD*05******60~DTM*001*20011219~DTM*002*20011204~DTM*010*20011119~DTM*015*20011211~TD5*B***H*SEE PARTNER ROUTING REQUIREMENT BOOK~N9*AH*PO MESSAGES~MSG*THIS IS AN EDI TEST PO, PLEASE DO NOT FILL~N1*BT*XYZ GROUP, INC*92*0069595550000~N3*192 MARKET Text Being SoughtSQUARE~N4*ATLANTA*GA*30117~N1*ST*XYZ GROUP, INC - ATLANTA*9*69590093~N3*450 PEACHTREE STREET~N4*ATLANTA*GA*30312~PO1**25*EA*29.4**UP*072495005099*VC*0509-6*CB*759873~PID*F*08***OVAL ROASTER 18"X12 1/4"X7 1/2" SPCKLD BLK~PO4*6~PO1**25*EA*20.58**UP*072495061064*VC*6106-6*CB*759874~PID*F*08***OVAL ROASTER 13"X8"X5" SPKLD BLK~PO4*6~CTT*2~SE*1*0001~GE*1*000000001~IEA*1*000000001~ISA*00* *00*Text Being SoughtT BASIC *01*060018611 *01 0509*1441*U*00401*000000091*0*T*>~GS*PO*TEST BASIC*060018611*20010509*144 1*000000005*X*004010V 002*20011204~DTM*010*20011119~DTM*015*20011211~TD5*B***H*SEE PARTNER ROUTING REQUIREMENT BOOK~N9*AH*PO MESSAGES~MSG*THIS IS AN EDI TEST PO, PLEASE DO NOT FILL~N1*BT*XYZ GROUP, INC*92*0069595550000~N3*192 MARKET Text Being SoughtSQUARE~N4*ATLANTA*GA*30117~N1*ST*XYZ GROUP, INC - ATLANTA*9*69590093~N3*450 PEACHTREE STREET~N4*ATLANTA*GA*30312~ ISA*00* *00* *ZZ*TEST BASIC *01*060018611 *01 0509*1441*U*00401*000000091*0*T*>~GS*PO*TEST BASIC*060018611*20010509*144 1*000000005*X*004010VICS~ST*850*0001~BEG*00*SA*643787**20011020~REF*DP*087~REF*MR*TRYUE~FOB*CC*OR*ORIGIN~CSH*Y~ITD*05******60~DTM*001*20011219~DTM*002*20011204~DTM*010*20011119~DTM*015*20011211~TD5*B***H*SEE PARTNER ROUTING REQUIREMENT BOOK~N9*AH*PO MESSAGES~MSG*THIS IS AN EDI TEST PO, PLEASE DO NOT FILL~N1*BT*XYZ GROUP, INC*92*006993484575595550000~N3*192 MARKET Text Being SoughtSQUARE~N4*ATLANTA*GA*30117~N1*ST*XYZ GROUP, INC - ATLANTA*9*69590093~N3*450 PEACHTREE STREET~N4*ATLANTA*GA*30312~PO1**25*EA*29.4**UP*072495005099*VC*0509-Text Being Sought ATLANTA*9*69590093~N3*450 PEACHTREE STREET~N4*ATLANTA*GA*30312~ ISA*00* *00* *ZZ*TEST BASIC *01*060018611 *01 0509*1441*U*00401*000000091*0*T*>~GS*PO*TEST BASIC*060018611*20010509*144 1*000000005*X*004010VICS~ST*850*0001~BEG*00*SA*643787**20011020~REF*DP*087~REF*MR*TRYUE~FOB*CC*OR*ORIGIN~CSH*Y~ITD*05******60~DTM*001*20011219~DTM*002*20011204~DTM*010*20011119~DTM*015*20011211~TD5*B***H*SEE PARTNER ROUTING REQUIREMENT BOOK~N9*AH*PO MESSAGES~MSG*THIS IS AN EDI TEST PO, PLEASE DO NOT FILL~N1*BT*XYZ GROUP, INC*92*0069595550000~N3*192 MARKET Text Being SoughtSQUARE~N4*ATLANTA*GA*30117~N1*ST*XYZ GROUP, INC - ATLANTA*9*69590093~N3*450 PEACHTREE
0 -
The following code streams a file into a BigText variable (InputText), finds and replaces all occurrences of one text string with another moving the text into a second BigText variable (OutputText), and finally streams that BigText variable out to another file.
PROCEDURE TextReplace@37002000(SourceFileName@37002001 : Text[250];DestinationFileName@37002002 : Text[250];TextToFind@37002003 : Text[250];TextToReplace@37002004 : Text[250]); VAR TextFile@37002006 : File; InStream@37002007 : InStream; OutStream@37002008 : OutStream; InputText@37002000 : BigText; OutputText@37002005 : BigText; SubText@37002010 : BigText; TextPosition@37002009 : Integer; BEGIN TextFile.TEXTMODE(FALSE); TextFile.OPEN(SourceFileName); TextFile.CREATEINSTREAM(InStream); InputText.READ(InStream); TextFile.CLOSE; TextPosition := InputText.TEXTPOS(TextToFind); WHILE TextPosition <> 0 DO BEGIN InputText.GETSUBTEXT(SubText,1,TextPosition - 1); OutputText.ADDTEXT(SubText); OutputText.ADDTEXT(TextToReplace); InputText.GETSUBTEXT(InputText,TextPosition + STRLEN(TextToFind)); TextPosition := InputText.TEXTPOS(TextToFind); END; OutputText.ADDTEXT(InputText); TextFile.TEXTMODE(FALSE); TextFile.CREATE(DestinationFileName); TextFile.CREATEOUTSTREAM(OutStream); OutputText.WRITE(OutStream); TextFile.CLOSE; END;
1 -
jreynolds,
Genius function! Using the BigText variables is elegant and works like a charm. I had no idea the BigText variable had that functionality.0 -
This is really nice
. But how to replace it with Tab to make it Tab-Delimited :roll: ?
0 -
Hi Cunny,
use
charTab := 9;
FORMAT(charTab);0 -
Ignore0
Categories
- All Categories
- 73 General
- 73 Announcements
- 66.6K Microsoft Dynamics NAV
- 18.7K NAV Three Tier
- 38.4K NAV/Navision Classic Client
- 3.6K Navision Attain
- 2.4K Navision Financials
- 116 Navision DOS
- 851 Navision e-Commerce
- 1K NAV Tips & Tricks
- 772 NAV Dutch speaking only
- 617 NAV Courses, Exams & Certification
- 2K Microsoft Dynamics-Other
- 1.5K Dynamics AX
- 320 Dynamics CRM
- 111 Dynamics GP
- 10 Dynamics SL
- 1.5K Other
- 990 SQL General
- 383 SQL Performance
- 34 SQL Tips & Tricks
- 35 Design Patterns (General & Best Practices)
- 1 Architectural Patterns
- 10 Design Patterns
- 5 Implementation Patterns
- 53 3rd Party Products, Services & Events
- 1.6K General
- 1.1K General Chat
- 1.6K Website
- 83 Testing
- 1.2K Download section
- 23 How Tos section
- 252 Feedback
- 12 NAV TechDays 2013 Sessions
- 13 NAV TechDays 2012 Sessions