PDA

View Full Version : file writing, saving, opening .... basics


tymznd
12-10-2003, 03:50 AM
I have been reading through the documentation on writing, opening, and reading files but I still have some basic questions....

I want to write out to a text file.
This is from the documentation:
$exampFile = (`internalVar -userTmpDir` + "example.tmp")
$fileID = `fopen $exampFile`;
-So... in order to print some data to a text file I first need to create a dummy file in the temp directory??? Is this correct?

- then when I want to save out the file... I would assume that it would be passed to the OS, where all the "file replace?" and options would be handled, is this correct??

Why can't I simply write out the data to a file without opening a file first?
Sorry if this is basic stuff.... it been a long day

jdj
12-10-2003, 05:42 AM
Hello rhythmone

No - you don't need a tempfile. You can open your file directly.

$hFile = `fopen "c:\Myfile.txt"`;
fwrite $hFile, "Hi there\n";
fclose $hFile;

(...ought to work - I'm not at my Maya computer right now).


Why can't I simply write out the data to a file without opening a file first?


You do need to open a file before you can write to it. On second thought I guess you mean "tempfile"... then the answer is "you can". :)

Cheers
/ Daniel
:beer:

brubin
12-10-2003, 01:13 PM
Originally posted by rhythmone

I want to write out to a text file.
This is from the documentation:
$exampFile = (`internalVar -userTmpDir` + "example.tmp")
$fileID = `fopen $exampFile`;
-So... in order to print some data to a text file I first need to create a dummy file in the temp directory??? Is this correct?

Why can't I simply write out the data to a file without opening a file first?

okay, how to explain this....:
let's say, you have a fish... oh, no - let's say you have a turkey, and you want to feed it, so it grows big and strong for being your xmas-roast.
if you want to feed it, you have to grab it and open it's mouth FIRST, otherwise it'll be a messy procedure and your turkey will stay lean.

turkey is a smart beast though, it has a sense of it's purpose to come, and it will not want to keep the feed inside, so in order for the feed to stay put you'll have to make sure that the mouth of the turkey is closed when you let go of the turkey's neck!

oh no! next thing you know is - you find you lost your watch inside the turkey while stuffing it, so in order to retrieve it, again you'll have to open the mouth, reach in and get it, and -for the reasons described above- make sure you'll close it again when finished.

that's the basic concept behind "fopen/fwrite/fread/fclose". :)
HIH
s.

tymznd
12-10-2003, 07:05 PM
So can someone please give me the basic process flow.... and also, where is the logic for overwriting files.

... say I want to write the follow string data to a text file....

select leg.smp[0][134217733]
leg.smp[1][134217728]
leg.smp[1][134217731];

I need to create a file to open?
$hFile = `fopen "c:\Myfile.txt"`;

What if that file already exists? Where is the logic to prompt that the file already exists.... so that I can do a "save as"..... My first impression is that this logic would be handled by the OS at the save point? Is this not the case? Do I need to build that logic in the script?

I mean I understand the fopen, fclose, etc... I guess I am just getting hung up on why I would need to specify a path for the fopen prior to the logic to see whether or not the file already exists.... does anyone see what I am saying?

mhovland
12-10-2003, 07:59 PM
The way I do this is through my interface. It prompts for a save location, and a file name, I then build the string for creating the file from the input I recieve.

Here is an example, look through the code and see if it helps you out any.

This creates a file with the name you specify, in the location you choose, with the .TXT extension.

This is also old code, so I would do things differently now, but it works.

Let me know if you have any questions.




global proc mhFileOut()
{

global string $curObjectNodeType;
global string $outDirTxt;
global string $lvlOutList;
global string $lvlFileName;
global string $lvlFileName;
global string $lvlPrefix;

if (`window -exists LvlOutWin`)
{
deleteUI -window LvlOutWin;
}

string $lvlWindow =`window -title "File Exporter v2.1" -width 200 -height 345
-sizeable 0 -tlc 150 150 LvlOutWin`;

string $form = `formLayout`;

string $dirOutBut = `button -width 150 -height 30 -label "Choose Output Directory" -c "getDestDirectory"`;
string $outTxt = `text -label "Output Directory:"`;
string $outDirTxt = `text -label ""`;
string $nameTxt = `text -label "Name:"`;
string $lvlFileName = `textField`;
string $expLVL = `button -label "Export File" -height 34 -c "expLvlFile"`;



formLayout -edit
-af $dirOutBut "left" 2
-af $dirOutBut "right" 2
-af $dirOutBut "top" 5

-af $outTxt "left" 2
-ac $outTxt "top" 2 $dirOutBut

-ac $outDirTxt "top" 2 $outTxt
-af $outDirTxt "left" 2

-af $nameTxt "left" 2
-ac $nameTxt "top" 2 $outDirTxt

-ac $lvlFileName "left" 2 $nameTxt
-ac $lvlFileName "top" 2 $outDirTxt
-af $lvlFileName "right" 2


-af $expLVL "left" 2
-af $expLVL "right" 2
-ac $expLVL "top" 2 $lvlFileName

$form;

showWindow $lvlWindow;

}


////////////////////////////////////
// Get Destination Directory //
////////////////////////////////////

global proc string getDestDirectory()
{

global string $targetDirectory;
string $targetNtDirectory;
string $targetPathElements[];
int $i, $pathElementsCount;
fileBrowser "getTargetDirectory" "Choose Destination Directory" "directory" 4;
tokenize($targetDirectory,"/",$targetPathElements);
$pathElementsCount=size($targetPathElements);
for ($i=0;$i<$pathElementsCount;$i++)
$targetNtDirectory=$targetNtDirectory+$targetPathElements[$i]+"\\";
return $targetNtDirectory;
}

///////////////////////////////
// Get Target Directory //
///////////////////////////////

global proc getTargetDirectory ( string $directory , string $type)
{
global string $outDirTxt;
global string $targetDirectory;
$targetDirectory=$directory + "/";
text -edit -label (""+$targetDirectory+"") $outDirTxt;
}

///////////////////////////
// Export the Level File //
///////////////////////////

global proc expLvlFile()
{
global string $curObjNodeType;
global string $lvlFileName;
global string $targetDirectory;
global string $lvlOutList;
global string $lvlPrefix;
//get the name of the file to be created
string $lvlFileNameTxt = `textField -q -tx $lvlFileName`;
$LvlFile = ($targetDirectory + $lvlFileNameTxt + ".txt");
$FileID = `fopen $LvlFile "w"`;

fprint $FileID "This is a test!\nAll is good\n";

fclose $FileID;
}

jdj
12-10-2003, 08:00 PM
Hi again

Check the online help file for information about the MEL command fopen (and fclose / fprint / fwrite / fread etc. for that sake). It is quite good.

The logic / flow is quite simple - you first open the file (to access its contents - see it as a file drawer, you need to open it before you can see or put anything inside). Then you read or write to the file and when you're finished - you close the file.

Try this to verify if a file already exists or not:


int $fileId = `fopen $filename "r"`;

if ($fileId == 0)
{ // File did not exist }
else
{ // File do exist }


To write the text that you typed you would do something like this


string $fileName = "c:\\Test.mel";
int $hFile = `fopen $fileName "w"`;
fprint $hFile "select leg.smp[0][134217733]\n";
fprint $hFile "leg.smp[1][134217728]\n";
fprint $hFile "leg.smp[1][134217731];";
fclose $hFile;


Read up on the difference between fwrite and fprint. In this case fprint is more appropriate since it is a textfile.

Cheers!
/ Daniel
:beer:

jdj
12-10-2003, 08:01 PM
mhovland - You beat me by a minute! :D

tymznd
12-10-2003, 08:11 PM
This is also old code, so I would do things differently now, but it works.
mhovland - thanks... I guess I am just kinda stunned because this seems so redundant..... and that anyone who was saving out data would have to write the same code.... why wouldn't this most common logic be predefined in a mel command???

int $fileId = `fopen $filename "r"`;

if ($fileId == 0)
{ // File did not exist }
else
{ // File do exist }
jdj - I believe that the above scenario would ALWAYS evaluate as existing.... as I understand it the fopen will create the file upone evaluation

macaroniKazoo
12-10-2003, 08:49 PM
I guess I am just kinda stunned because this seems so redundant..... and that anyone who was saving out data would have to write the same code.... why wouldn't this most common logic be predefined in a mel command???

because the file commands are built for flexibility basically... its like 3 lines of code to write the text you want to a file, and probably another two to check if the file exists and throw a warning or whatever.

there are pre-defined file saving scripts, such as the fileDialog command, and the fileBrowserDialog command, which is possibly more what you're after.

it is frustrating when you're learning to not be able to so something like:
fwriteFile "c:/project/yay.txt" "someText\n\r moreText\r\nstill more!";

and be done with it, but if it worked like that, you'd be alot more limited than you currently are. its all about flexibility i guess.

jdj
12-11-2003, 10:48 AM
Originally posted by rhythmone
jdj - I believe that the above scenario would ALWAYS evaluate as existing.... as I understand it the fopen will create the file upone evaluation

I haven't tried it but I think not. What you are saying is true for writing. But if you try to open a file for reading and it doesn't exist, the fopen function should fail and return 0.

I believe I can bet you a beer upon that. :)

Cheers!
/ Daniel
:beer:

mhovland
12-11-2003, 03:08 PM
You are correct jdj, it will return 0 if the file doesn't exist.

jdj
12-11-2003, 08:43 PM
Originally posted by rhythmone
mhovland - thanks... I guess I am just kinda stunned because this seems so redundant..... and that anyone who was saving out data would have to write the same code.... why wouldn't this most common logic be predefined in a mel command???

Hi again - I have almost never encountered a situation where just one or two lines are written to a file. Usually you write loads of information to a file using chunks and other structures generating many different write-commands, and to open & close the file for each value written would be terribly inefficient. And to try to pre-arrange information in memory so it could be written with one open/write/close statement would be a headache. So I must say that the open / do things / close logic is quite nice.

Anyhow - the logic applies to every programming language I have ever encountered, so once you get the hang of it it isn't so bad.



You are correct jdj, it will return 0 if the file doesn't exist


:bounce: Yes Yes, I won a beer, I won a beer *gulp* scheeezz tchanks ghuyjs!

Cheers
/ Daniel
:beer:

loked
12-14-2003, 01:41 PM
Hey,

I've got a bit of a problem with all this fwrite stuff.

I want to query something in Maya and write it to a text file. The problem is when I use fwrite to write a file, the first line works fine, then from then on there is a space before the rest, so when I use the fgetline or fgetword commands, it gets the first line, but not the rest.

The txt file looks like this

Hello World
How are you
I'm fine thanks, how are you?
I'm fine too

in order to print this, I'm doing this

$fileId =`fopen "c:/test.txt";
fwrite $fileId "Hello World\n\r";
fwrite $fileId "How are you\n\r";
fwrite $fileId "I'm fine thanks, how are you?\n\r";
fclose $fileId

Please help me out here, its killing me!!!

Thanks!
loked

jdj
12-14-2003, 01:56 PM
Hi loked

..haven't time to check things in Maya, but just looking at your code - shouldn't you use fprint for text files? And what's this "\r" character doing in the end? "\n" ought to suffice.

Cheers
/ Daniel

loked
12-14-2003, 03:00 PM
Okay, if I use fprint, how do I retrieve the file and make use of it in Maya, fread and fgetline doesnt work.

If I choose not to make a text file and stick with fwrite, what format should I write the file out to then.

For \n it doesnt put it on the next line and it puts a block thing similar to this [] if I just put \r then the same thing happens and if I put both, I get what I showed you earlier.

Thanks

loked

sbp
12-14-2003, 03:02 PM
hi,
Return is normally before linefeed. The space is probably the \r.

loked
12-14-2003, 03:16 PM
Yeah, but I've tried leaving it out as well and then I get everything on the same line and the sentences are just seperated by block like things []

Any other suggestions??

loked

sbp
12-14-2003, 04:14 PM
Hi,
Sorry if I didn't explain right.

$fileId = `fopen "c:/test.txt"`;
fprint $fileId "Hello World\r\n";
fprint $fileId "ok, I'm done.\r\n";
fclose $fileId;
$fileId = `fopen "c:/test.txt" "r"`;
print `fgetline $fileId`;
print `fgetline $fileId`;
fclose $fileId;

fgetline reads up until the next newline. A long as you write it, it works in fwrite or fprint. The difference is fwrite includes the trailing null which is the block glyph you see when you leave out the newline.

For unix a newline is only \n. For windows notepad or the clipboard and whatnot a newline is \r\n, but for maya, it only needs the \n.

loked
12-14-2003, 04:20 PM
Cool!! I'll give that a try right now. Thanks!!!! :)

later:wavey:
loked

tymznd
12-15-2003, 05:57 AM
loked

Just now got around to checking my email and saw your post.... not sure if you have already figured it out but here are some snippets of my code which all works now...

..... let me know if you have questions.

mel that write data to text file
// output collected data to file
$content = ($content + "// defType " + $defType);
$content = ($content + "\n" + "// origfile " + $fileName);
$content = ($content + "\n" + "// deepestLevel");
$content = ($content + "\n// |" + $deepestLevel);
$content = ($content + "\n" + "select ");
$content = ($content + "\n" + "// setMems");

for ($item in $deformerSet) {
$content = ($content + "\n" + $item);
$coord = `xform -q -t -ws ($item)`;
$ptLevel = `subdiv -cl $item`;
$content = ($content + " //" + " " + $coord[0] + " " + $coord[1] + " " + $coord[2] + " " + $ptLevel);
}
setAttr $defoEnv $defoEnvValue;
saveToTextFileCall $content;

The proc below makes a call to a proc copied from parts of UltraPose... which saves out libraries of info (the file save, or save as logic is handled there).... it worked for me without modification:

global proc saveToTextFileCall (string $content) {
string $result;
string $file;
int $fileID;

// This is the process for file location, naming,
// existence and "save as" checking, etc...
global string $gSaveFileDialogPath;
$result = `fileBrowser "mod_saveFileDialogCallback" Save "mel" 1`;
$file = $gSaveFileDialogPath;

if ($result != "") {
$fileID = `fopen $file`;
fprint $fileID $content;
print "file was written to\n\n";
fclose $fileID;
}
}
... and finally here is some of the mel that reads the written data:
$curSelected = `ls -sl`;
$project = `workspace -q -rd`;
$project = ($project + "*.mel");
$file = `fileDialog -dm $project`;
$fileID = `fopen $file "r"`;

if ($fileID > 0) {

$nextLine = `fgetline $fileID`;

// READ THE DEEPEST SUBD LEVEL
while ($nextLine != "// deepestLevel\n") {
$nextLine = `fgetline $fileID`;
}
$nextLine = `fgetline $fileID`;
$deepestLevel = `stripStringReturnLast $nextLine "|"`;

// READ THE POINT WORLD COORDS
while ($nextLine != "// setMems\n") {
$nextLine = `fgetline $fileID`;
}
while ($nextLine != "\n") {
$nextLine = `fgetline $fileID`;
if ($nextLine != ";\n") {
$coords = `stripStringReturnLast $nextLine "/"`;
$cleanCoords = `stripStringReturnFirst $coords "\n"`;
if ($cleanCoords != "") {
$writtenPts[size($writtenPts)] = $cleanCoords;
}
}
}

kiaran
07-23-2004, 04:09 AM
I'm having a strange problem. Whenever I open a file like this:

$fileID = `fopen $fileLocation "r"`;

in Maya 5 it works fine. But in Maya 6 I get this error message:

Invalid call to "fopen". Check number and types of arguments expected by the procedure.

Anyone else have this problem?

tymznd
07-23-2004, 05:26 AM
it appears that Maya 6 has a change in file I/O. Several of my scripts also did not work in 6.0..... and those were file/path reading. I believe the issue is with line breaks..... so my process was that Maya would open a txt file and read the file path contained within.... and the line break within the txt file was throwing things off.

.... so make sure that your $fileLocation doesn't have any hidden characters in it.
.... you could verify this by manually giving the command line a file path to open, i.e.:
fopen "Users/you/documents/maya/projects/testFile.txt" "r"

kiaran
07-23-2004, 06:47 AM
I figured it out. I was getting the variable $fileLocation by querying a fileDialog like this:

$fileLocation = `fileDialog`;

I guess the variable $fileLocation wasn't defaulting to a type 'string' like the fopen command requires. So I had to explicitly define it as a type 'string' like this:

string $fileLocation;

I guess I should be explicitly declaring all my variables. One can trust Maya for 99% of variable type assignments, but it's not worth the hassle.

Thanks for your help rythmone.

CGTalk Moderation
01-16-2006, 09:00 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.