Notifications
Clear all

[Closed] Rewriting a line

I’m having trouble making a function for rewriting data in a txt file. If the contents of the file are:

“text 1.1” “text 1.2” “text 1.3”
“text 2.1” “text 2.2” “text 2.3”

and I fire up the function fn_data_rewrite 2 3 “new data” it would rewrite the 3rd entry on the 2nd line of the file into the string.
Is is possible to have this done though .net?

7 Replies

it’s possible to do many different ways…
but a question is first.
can you do any coding (mxs, c#, c++, any)? if so, please, post your attempt of a trying to solve the task.

1 Reply
(@linkbird)
Joined: 11 months ago

Posts: 0

I only know how to program in maxscript. I had to learn basic coding though it.

Here was my attempt at solving the problem:

txtfile = "D:\Text File.txt"
  fn data_rewrite line entry newtext =
  	(
  	openf = openFile txtfile mode:"a+"
  	for m = 1 to line do new_line = readLine openf
  	new_POS = filterString new_line "***\""
  	new_POS[entry] = newtext
  	print new_POS[entry]
  	close openf
  	)
  data_rewrite 2 3 "new data"

Here the data in the txt file was separated with 3 stars. It obviously doesn’t work. The only way I could think of doing what I wanted through maxscript was to rewrite the whole txt file but having the line and entry in question be different, but it sounds way too cumbersome and overly complicated for wanting to do something so simple. That’s why I asked for a solution in .net, because I assumed it would handle the problem more elegantly.

it’s always good to show what you tried to solve an issue when you ask for help.
it helps to understand your coding level to give the right (clear) answer.

well…

#1 in your case it’s better to stay with mxs. using of .net is probably overkill if you don’t need to update very big files.

#2 you have better organize your data using right delimiter (separator) for easier parsing (filtering)

for example for numbers (float numbers) i prefer to use space(” “), “;”, or “,” (usually just space)
for names (filenames) i use “|” (because it unlikely be used in the name)

let’s say you have a names:

this is file content:

name_01|name_02|name_03|name_04|name_05|name_06
name_11|name_12|name_13|name_14|name_15|name_16
name_21|name_22|name_23|name_24|name_25|name_26

this is mxs version:

fn mxs_readReplaceInFile file line index text separator:"|" =
(
	if doesfileexist file and (fs = openfile file mode:"r+") != undefined do
	(
		ss = stringstream ""
		current_line = 1
		out = off
		while not eof fs and not out do
		(
			str = readline fs
			if current_line == line do
			(
				strs = filterstring str separator
				if strs.count < index then out = on else
				(
					strs[index] = text
					str = ""
					for k=1 to strs.count do 
					(
						str += strs[k]
						if k < strs.count do str += separator
					)
					format ""str to:fs
				)
			)
			format "%
" str to:ss
			current_line += 1
		)
		if not out do
		(
			seek fs 0
			format "%" (ss as string) to:fs
		)
		close fs
	)
)
/*** using **
mxs_readReplaceInFile @"c:	emp\data.txt" 2 3 "ABCDEFG"
*/

this is .net version:

fn net_readReplaceInFile file line index text separator:"|" =
(
	if (dotnetclass "System.IO.File").Exists file do try
	(
		lines = (dotnetclass "System.IO.File").ReadAllLines file
		strs = (dotnetobject "System.String" lines[line]).Split separator 
		strs[index] = text
		lines[line] = (dotnetclass "System.String").Join separator strs
		(dotnetclass "System.IO.File").WriteAllLines file lines
		ok
	)
	catch()
)
/*** using **
net_readReplaceInFile @"c:	emp\data.txt" 1 2 "ABCDEFG"
*/

if you have any questions, feel free to ask

Thank you for your help once again I’ll try and include my attempts at solving a problem from now on when asking a question on this forum.
I have a question though:

I tried to make a code that looks for all lines that contain a specific word in the 3rd entry and saves their line position for use by your program later. Here I’m using the .net version of your script

Here was my attempt: (I’m using your .net version of the function)

global txtfile = "D:\Text File.txt"
global qline = 1
fn read_replace file _line index _text separator:"|" =
	(
	.....
	)
openf = openFile txtfile mode:"a+"
new_line = readLine openf
new_POS = filterString new_line "|\""
while not eof openf do
	(
	new_line = readLine openf
	new_POS = filterString new_line "|\""
	if new_POS[3] == "Text" then
		(
		read_replace txtfile qline 3 "New Text"
		)
	qline += 1
	)
close openf

I managed to write the part that finds the lines (I think?).I tried quite a few times but it doesn’t seem to work. I’m not really sure what the problem is. I didn’t want to rewrite your code to fit this extra functionality since I am using it in another place in my program and I’d rather just reference it.

Hi, linkbird.

I’m not an expert at all but:

  • why do you read the first line before the “while” loop? I think you shouldn’t.
  • why do you look for “|”” instead of “|”?

Changing these two things, I think it should work.

you have to make a decision what variant to use and continue do everything in this style…
so if you want to do it .net way:

fn net_findAndReplaceInFile file source target separator:"|" =
(
	if (dotnetclass "System.IO.File").Exists file do --try
	(
		lines = (dotnetclass "System.IO.File").ReadAllLines file
		lines_changed = #{}
		for k=1 to lines.count do
		(
			strs = (dotnetobject "System.String" lines[k]).Split separator 
			found = off
			while (i = finditem strs source) != 0 do
			(
				strs[i] = target
				found = on
			)
			if found do 
			(
				lines[k] = (dotnetclass "System.String").Join separator strs
				append lines_changed k
			)
		)
		if not lines_changed.isempty do (dotnetclass "System.IO.File").WriteAllLines file lines
		lines_changed
	)
	--catch()
)
/*
net_findAndReplaceInFile @"c:	emp\data.txt" "name_24" "XXXXXXX"
*/

but there is another (advanced :)) method to this kind of things in .net – System.Text.RegularExpressions.Regex

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

something like:

fn net_findAndReplaceRegex file source target =
(
	text = (dotnetclass "System.IO.File").ReadAllText file
	_text = (dotnetclass "System.Text.RegularExpressions.Regex").Replace text ("(" + source + ")") target
	(dotnetclass "System.IO.File").WriteAllText file _text
	text != _text
)
/*
net_findAndReplaceRegex @"c:	emp\data.txt" "name_21" "XXXXXXX"
*/