Best/Simplest way to replace lines of text in a file

This forum is meant for questions and discussions about the X# language and tools
FFF
Posts: 1532
Joined: Fri Sep 25, 2015 4:52 pm
Location: Germany

Best/Simplest way to replace lines of text in a file

Post by FFF »

Feeling a bit like Jeff, as it's a dummy question:
I read files from a directory, select some of them, replace some lines in each file with some other text and write the modified content to a new file.
Starts like this:

Code: Select all

	oInfo:=Directoryinfo{cPfad}
	aFiles:=oInfo:GetFiles("*.s4w")
	FOREACH x AS  FileInfo IN aFiles
		oSource := Streamreader{x:FullName}
		DO WHILE .not. oSource:EndOfStream
			cLine:=oSource:ReadLine()
			IF cLine:Contains("NA=")  .and. cLine:Length > 4 
				? cLine:Replace(cS4P_Dolli, cPfad_S4P)
			ENDIF
		END DO
Works, and the relevant cLine is changed as it should.
But now on i feel like there are to many possibilites to proceed ;)

Any hint welcomed!
Regards
Karl
(on Win8.1/64, Xide32 2.19, X#2.19.0.2.)
User avatar
Chris
Posts: 4587
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

Best/Simplest way to replace lines of text in a file

Post by Chris »

Hi Karl,

Do you mean, how to write the data back on disk? I'd say simply create a StreamWriter and write to it line by line, after you make the necessary adjustments to each one. Or did you mean something else?
Chris Pyrgas

XSharp Development Team test
chris(at)xsharp.eu
Terry
Posts: 306
Joined: Wed Jan 03, 2018 11:58 am

Best/Simplest way to replace lines of text in a file

Post by Terry »

Karl

No, it's not a dummy question.

I don't know enough about X# language syntax to comment on the code. But what are you trying to do overall?

I assume you are trying to perform some sort of textual transformation. Probably complex. Thousands of alternatives - most of which you want to exclude. If this is not the case then please ignore the following.

1 Whenever you have too many possible alternatives to address, try and think the reverse way: Could you, more easily, identify the alternatives you DON'T want, then negate the result?

2 When reading and writing to a file you are creating quite a time consuming processing overhead. Would it be better to do it all via Lists or Arrays.

3 Data Structures have a significant part to play in respect of performance: Try searching web for Rope Data Structures.

Hope that helps a bit - there's more to this than hits the eye.

Terry
User avatar
kevclark64
Posts: 127
Joined: Thu Aug 15, 2019 7:30 pm
Location: USA

Best/Simplest way to replace lines of text in a file

Post by kevclark64 »

You'd have to test it, but it seems like it would have to be faster to read the whole file first, do the processing you want, then write the whole file back at once.
FFF
Posts: 1532
Joined: Fri Sep 25, 2015 4:52 pm
Location: Germany

Best/Simplest way to replace lines of text in a file

Post by FFF »

Terry,
thanks, but it IS dump... I'm way lower in my coding ambitions - nothing "big data", only some files in a folder to handle ;)
@Chris: yes, that describes it. As you see in my code, i already "have" the modified data in the streamreader, so i thought, one might feed that into a writer. But following the docs this seems not to be the way to do it...
(Sorry, i code so seldom these days i way faster forget than i have learned...)

@Kevin: i "think", that's what i did with the StreamReader?
Regards
Karl
(on Win8.1/64, Xide32 2.19, X#2.19.0.2.)
User avatar
Chris
Posts: 4587
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

Best/Simplest way to replace lines of text in a file

Post by Chris »

Hi Karl,

Either do as Kevin said, load everything in an array (File.ReadAllLines()), manipulate it and write back with File.WriteAllLines(), or if you want to just adjust the above code, create a StreamWriter and use oStreamWriter:WriteLine() for each line. Not sure what you don't like about this, can you please explain a bit more?
Chris Pyrgas

XSharp Development Team test
chris(at)xsharp.eu
FFF
Posts: 1532
Joined: Fri Sep 25, 2015 4:52 pm
Location: Germany

Best/Simplest way to replace lines of text in a file

Post by FFF »

Chris,
nothing not to like, simply no clue ;)
Anyway, following Kevin's/your suggestion:

Code: Select all

	FOREACH x AS  FileInfo IN aFiles
		VAR NewFileName :=Path.GetFileNameWithoutExtension(x:FullName)
		VAR NewFullFilename := x:DirectoryName+  NewFileName + "_a" +  x:Extension
		VAR acLines := File.ReadAllLines(x:Fullname)
		FOREACH cLine AS  STRING IN acLines
			IF cLine:Contains("NA=")  .and. cLine:Length > 4 
				? cLine
				? cLine:Replace(cS4P_Dolli, cPfad_S4P)
			ENDIF
		NEXT
		File.WriteAllLines(NewFullFilename, acLines)
	NEXT
Works, as it changes the content of some of the lines and creates a copy of the sourcefile with modified name.
ONLY one fault, the modified lines don't make it into the new file, there i find the old ones.
?
Thx for your patience
EDIT: Found it. The "inmutable" string thing got me - i.e. after the ? cLine:Replace() this result gets dropped.
So:

Code: Select all

FOREACH x AS  FileInfo IN aFiles
		VAR NewFileName :=Path.GetFileNameWithoutExtension(x:FullName)
		VAR NewFullFilename := x:DirectoryName+  NewFileName + "_a" +  x:Extension
		VAR acLines := File.ReadAllLines(x:Fullname)

		FOR VAR i := 1 UPTO acLines:Length
			IF acLines[i]:Contains("NA=")  .and. acLines[i]:Length > 4 
				VAR cNewLine:= acLines[i]:Replace(cS4P_Dolli, cPfad_S4P)
				acLines[i]:= cNewLine
			ENDIF
		NEXT
		File.WriteAllLines(NewFullFilename, acLines)
	NEXT
RETURN   TRUE
Works as it should. Note: Verrry sloppy code, not to be copied without adding necessary exeption handling etc. For me (that's the usual excuse) it suffices, as i'll have to use it in exactly one place maybe 5 times a year ;)
Regards
Karl
(on Win8.1/64, Xide32 2.19, X#2.19.0.2.)
User avatar
kevclark64
Posts: 127
Joined: Thu Aug 15, 2019 7:30 pm
Location: USA

Best/Simplest way to replace lines of text in a file

Post by kevclark64 »

I think your first version should work if you replace:
? cLine
? cLine:Replace(cS4P_Dolli, cPfad_S4P)
with:
? cLine
cLine:=cLine:Replace(cS4P_Dolli, cPfad_S4P)
? cLine
FFF
Posts: 1532
Joined: Fri Sep 25, 2015 4:52 pm
Location: Germany

Best/Simplest way to replace lines of text in a file

Post by FFF »

Kevin Clark wrote:I think your first version should work if you replace:
cLine:=cLine:Replace(cS4P_Dolli, cPfad_S4P)
Gave it a try, but the line does not compile:
XS9064: Cannot assign to 'cLine' because it is a 'foreach iteration variable'

Thx for trying ;)
Regards
Karl
(on Win8.1/64, Xide32 2.19, X#2.19.0.2.)
User avatar
kevclark64
Posts: 127
Joined: Thu Aug 15, 2019 7:30 pm
Location: USA

Best/Simplest way to replace lines of text in a file

Post by kevclark64 »

Interesting that wouldn't compile. I tried the following, which is doing basically the same thing you are doing, and it worked:

local array1[2]
array1[1]="Old line 1"
array1[2]="Old line 2"
FOR EACH cArrayLine as String IN array1
cArrayLine="This is a new line"
? cArrayLine
NEXT

The above is in the Foxpro dialect so maybe that makes a difference, but the beauty of using FOR EACH is that it makes it easier to manipulate each variable or object within an array or collection. Not being able to modify the resulting variable or object would sort of defeat the purpose.
Post Reply