PDA

View Full Version : How to delete a line from an external file?


ILS
02-05-2009, 05:29 PM
I have an external txt file that my script accesses to read values for different properties, basically I need to figure out a way to delete a line from that txt file using maxscript.

Any ideas how I can do that?

MoonDoggie
02-05-2009, 05:46 PM
check out file i/o methods in the mxs reference for ReadLine() and associated methods to find the answer!

ILS
02-05-2009, 05:51 PM
the problem with that is it can only read and write - I guess I can write a blank space for every character in the line but then how do I get rid of the blank line.

Another method would be to create temp copy of the file and copy line by line to a new file with the exception of the line I want to delete but this seems too cumbersome for a simple function.

ZeBoxx2
02-05-2009, 06:11 PM
oddly enough, that's what 99% of the editors do when you delete a line... either...

A.
Create a new file
Read a line from the old file
Write that line to the new file
Skip the line you want to delete

or

B.
Overwrite the existing file in-place
Read a line from memory (containing the original file entirely)
Write the line to the new file
Skip the line you want to delete

There's very few (if any, these days), editors that will work on a file in-place on the harddisk via, say, the description data or metadata in the filesystem (essentially, the line still exists, but as the filesystem contains no record for data including the data for that line, it's essentially gone from the file.

The only optimization you -can- do is use .NET - it's still the same procedure, but it can be a bit faster.

ILS
02-06-2009, 03:06 PM
that is unfortunate that maxscript doesn't have a built in function for this.

what would be the method for using .net to do this? I'm not really familiar with .net do you know any tutorials.

ZeBoxx2
02-06-2009, 07:59 PM
probably the fastest method (takes a bit of memory as each line is a string in an array)...


-- usage:
-- deleteLine <string>filename <int>lineNumberToDelete
-- result:
-- line 'lineNumberToDelete' is removed from file 'filename'
-- notes:
-- NO backups are made! Use at your own risk
fn deleteLine f linenum = (
local lines = (dotNetClass "System.IO.File").ReadAllLines f
deleteItem lines linenum
(dotNetClass "System.IO.File").WriteAllLines f lines
)

ILS
02-06-2009, 11:47 PM
Thanks a lot for your help I'll try this out. I'm not as worried about memory I run win 64 with 8 Gb ram so I have some to spare unfortunately what I don't have to spare is time which is why I'm trying to write scripts. Thanks again.

ILS
02-07-2009, 01:08 AM
It works - well sort of.

I am actually having problems closing the file after I do

myfile = openFile (mypath)

close myfile
returns OK

but I still have issues accessing it.
Your script works if I don't do openFile on the file prior to running it.
it gives me this:
MAXScript Rollout Handler Exception: -- Runtime error: dotNet runtime exception: The process cannot access the file 'C:\..\..\..' because it is being used by another process.

I wonder if I should not use maxscript openFIle method and switch to .net for external file handling. What do you think?

ZeBoxx2
02-07-2009, 07:32 AM
well, with the function given, you wouldn't use openFile at all - just feed the function the (string) path to the file, not a maxscript file handle :)

If you're using openFile to open the file for some other operations before removing the lines, you would have to close the file in maxscript first. Alternatively, as you said, you may be able to do all of the processing using .NET .. depends a bit on what you're doing :)

ILS
02-08-2009, 12:46 AM
yeah I know about the fact that I don't need the openFile bit to use the .net script you described above.

Basically the external file is for listing camera names and their respective frame ranges and any other information I need. One part of the script collects all cameras in the scene and sets up a default setting for each and writes it to an external file - there are also other helper objects created with respect to each camera. Because there are so many things that depend on the camera in a scene, if I want to get rid of one or more cameras I also need to delete the assosiated objects and external file references - all of this is prone to human error. So that is basically why I need to figure out a way to delete lines from external files.

I use openFile to read the external file to get information from it. After opening I do use the close function as it is described in max help but the permissions are still not relinquised from either max or the script (i don't know which), I have to restart max to gain permission to edit the opened file again.

Thanks for all your help thus far. :)

ZeBoxx2
02-08-2009, 09:16 AM
must not be closing the file handle entirely somewhere, then - are you opening it twice, perhaps? opening it in a loop? etc.


-- create a temp file, stick 3 lines in it, close the file
f = createFile "$temp\\temp.txt"
format "First line\nSecond line\nThird line" to:f
close f

-- open the file, read all lines from it and print them, close the file
f = openFile "$temp\\temp.txt"
while (not eof f) do ( print (readline f); OK )
close f
-- "First line"
-- "Second line"
-- "Third line"

-- delete the 2nd line
deleteLine (getDir #temp + "\\temp.txt") 2

-- do the read+print thing again
f = openFile "$temp\\temp.txt"
while (not eof f) do ( print (readline f); OK )
close f
-- "First line"
-- "Third line"

ILS
02-09-2009, 01:29 AM
I looked at it again and I figured out that I was opening it twice but I thought that closing it once would do the trick regardless of how many times it was opened prior. But now that I think about it - it's a bit sloppy to open the same file twice.

What I have is createFile function as well as openFile function for the newly created file. I don't really need the openFile after the create because apparently it is already open for reading/writing. :shrug: Learn something everyday.

I just want to know one last thing though:
g = maxfilepath + "text.txt"
"C:\text.txt"
(dotNetClass "System.IO.File").Create g
dotNetObject:System.IO.FileStream
(dotNetClass "System.IO.File").ReadAllLines g
-- Runtime error: dotNet runtime exception: The process cannot access the file 'C:\text.txt' because it is being used by another process.

In this case do I need to close the file after creating it to read it? How would I do it?
In "msdn.microsoft.com" it says that
The FileStream (http://msdn.microsoft.com/en-us/library/system.io.filestream.aspx) object created by this method has a default FileShare (http://msdn.microsoft.com/en-us/library/system.io.fileshare.aspx) value of None (http://msdn.microsoft.com/en-us/library/system.io.fileshare.none.aspx); no other process or code can access the created file until the original file handle is closed.
While down the line it also says:
By default, full read/write access to new files is granted to all users. The file is opened with read/write access and must be closed before it can be opened by another application.

BTW you can't use "lines" as a variable - it turns out to be a reserved word for maxscript.

ZeBoxx2
02-09-2009, 10:09 AM
I just want to know one last thing though:
g = maxfilepath + "text.txt"
"C:\text.txt"
(dotNetClass "System.IO.File").Create g
dotNetObject:System.IO.FileStream
(dotNetClass "System.IO.File").ReadAllLines g
-- Runtime error: dotNet runtime exception: The process cannot access the file 'C:\text.txt' because it is being used by another process.

In this case do I need to close the file after creating it to read it? How would I do it?
Use something like...


local myFile = (dotNetClass "System.IO.File").Create g
myFile.close()
(dotNetClass "System.IO.File").ReadAllLines g



BTW you can't use "lines" as a variable - it turns out to be a reserved word for maxscript.
Sure I can! I can do Anything! *sets 'local gravity = 0.0', jumps off cliff and drifts away*

But you're right, you should typically avoid it, even though overriding it with a local is usually just fine - except that you won't be able to access the reserved version within that scope anymore. In this case, the file thing probably doesn't much care about the objectgroup that is 'lines'. Usually I do change the variables from 'thing' to 'myThing' or '_thing', whichever is more appropriate.

ILS
02-09-2009, 09:19 PM
Thanks a lot for your help.
Better keep that gravity var a local - I just got used to the 9.8 :)

CGTalk Moderation
02-09-2009, 09:19 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.