saving text to a file

Folks,

I’ve been trying to get text saved to a file without any success and thought someone might be able to identify where I’m going wrong. I have looked at other threads and don’t see anything that I’m doing wrong. The dialog displays but when select a file that it can write to (or specify a new file) nothing is getting written to the file. In the case of a new file it’s not even being created. Here’s what I’m doing.

I’ve got a button on a window to click to save the file. When that button is clicked, it runs a procedure that opens a save dialog:

on saveMapping()
	tell save panel
		set title to "Save mapping as..."
		set can choose directories to false
		set can choose files to true
		set prompt to "Save"
		set required file type to "txt"
		set treat packages as directories to false
	end tell
	display save panel attached to window "mappedWindow"
end saveMapping

And I have checked off that the mappedWindow in IB should process an event for panel ended.

Then in the panel ended process I have the result of the save dialog used as the location that the data is written to:

on panel ended theObject with result withResult
	global irisLocation, saveMappingLocation
	-- The Preferences window IRIS location choose button was clicked and a directory location was chosen.
	if theObject is the open panel and withResult is 1 then
		set irisLocation to (item 1 of (path names of open panel as list)) & "/" as text
		set contents of text field "irisLocationField" of tab view item "irisTabFields" of tab view "prefWindowTabs" of window "prefWindow" to irisLocation as text
	else if theObject is the save panel then
		if withResult is 1 then
			set saveMappingLocation to (path name of save panel)
			my writeToFile(saveMappingLocation, "This is a test. This is just a test.", false)
			--log saveMappingLocation
		end if
	end if
end panel ended

When I have the log feature enabled, the value of the saveMappingLocation variable does contain a Unix style path and filename specification of the desired file.

The writeToFile function looks like this:

on writeToFile(theFile, theString, appending)
	--set theFile to theFile as string
	set theFile to theFile as file specification
	try
		open for access file theFile with write permission
		if (appending = false) then
			set eof of theFile to 0
		end if
		write theString to theFile starting at eof
		close access theFile
	on error
		try
			close access theFile
		end try
	end try
end writeToFile

As you can see I’ve tried it with theFile as both type string and file specification. Neither appears to work.

Anybody have any suggestions or ideas?

On a related issue, when my save dialog appears, I can not have it choose a file and have it be the file name that displays in the text box that a file name gets typed into. Is this possible? If so, is there an option I need to set for that to happen?

Thanks in advance,
Jack

Try:

my writeToFile(saveMappingLocation as POSIX file, "This is a test. This is just a test.", false)

JJ,

Thanks so much for the suggestion. That worked great after I got rid of the first line in my writeToFile function that “set theFile … as file specification”.

Thanks so much,
Jack

Folks,

Now that I can save to a file, I’ve discovered another issue with my code. It will only write to an existing file. If I specify a file that does not exist, nothing gets created/written.

Any suggestions?

Thanks in advance,
Jack

I have the same problem.
so I thought of using “do shell script”
one to specify the destination and the second one to create a new text file at the location.
I use the “cd” command to set the destination and “touch” command to create the file.
then I save the text into the file
My only problem now is how to set the path to the location without the files name at the end of it.
I get the path from the save panel result, which contain the file name at the end, so I get an error massage that the file or folder does not exist.

can any one help as with that?

on panel ended theObject with result withResult
	global saveMappingLocation
	if theObject is the save panel then
		if withResult is 1 then
			set saveMappingLocation to (path name of save panel)
			my writeToFile(saveMappingLocation, saveMappingLocation as POSIX file, txt, false)
		end if
	end if
end panel ended

on writeToFile(theUFile, theFile, theString, appending)
	set cd to cd & theUFile
	do shell script cd -- theUFile
	set touch to touch & theFile
	do shell script touch

The only reason I see that may be causing you to run into problems is that you may be trying to write to protected directories, or directories that you do not have write permissions in (like system directories or other users’). Otherwise, the code you posted looks fine to me. I took the following code from a project of mine, so the var names in the sub are different, but that shouldn’t matter. I’m not sure I see the value of declaring your variable as global if they’re only being passed to the sub… and unless you want to check for file contents and append to existing data, you can dispense with the append flag in your subroutine.

on panel ended theObject with result withResult
	if theObject is save panel then
		if withResult is 1 then
			set saveMappingLocation to (POSIX file (path name of save panel))
			writeToFile(saveMappingLocation, "This is a test. This is just a test.")
		end if
	end if
end panel ended

to writeToFile(the_file, the_data)
	try
		open for access the_file with write permission
		set eof of the_file to 0
		write (the_data) to the_file starting at eof
		close access the_file
	on error
		try
			close access the_file
		end try
	end try
end writeToFile

If you must write to a protected directory, you might have to: write a temporary file (perhaps to the /tmp directory or to the desktop) in a location without any access restrictions, copy it using ditto and your admin password in a shell script to the restricted directory, delete the tmp file (if applicable). When trying to simply write the file with touch or just “>”, I couldn’t get the permissions to be accepted, so I used this method instead. The following will copy the contents of the file ‘test.txt’ on my desktop to a file of the same name in a random protected directory. It should work for

set the_tmp_file to "/Users/jed/Desktop/test.txt"
set the_file to "/System/Library/Caches/test.txt"

set theScript to ("ditto -rsrc " & the_tmp_file & " " & the_file)
do shell script theScript password "**YourPassword**" with administrator privileges

Note that the user executing this must have admin priveledges, and must have the password passed in the shell script. So…you might need to ask for this in your app for every user.

Have fun,
j

I finally got it working.
I set the touch command wright now.
instead of using the cd command and after that the touch command.
I simply set the touch to the return path from the save panel.

on panel ended theObject with result withResult
	if theObject is the save panel then
		if withResult is 1 then
			set saveMappingLocation to (path name of save panel)
			my writeToFile(saveMappingLocation, saveMappingLocation as POSIX file, txt)
		end if
	end if
end panel ended

on writeToFile(theUFile, theFile, theString)
	set touch to "touch " & theUFile
	do shell script touch
	try
		open for access file theFile with write permission
		set eof of theFile to 0
		write (theString) to theFile starting at eof
		close access theFile
	on error
		try
			close access theFile
		end try
	end try
end writeToFile

Yarnin,

Thanks. Applying the Unix touch feature resolved the ability to write to a new file. So in the immediate need, I’ve got the problem resolved…

Jobu,

Thanks also. The code I am using I’ve found from searching around this site and figured it would work without problem. Unfortunately, it doesn’t work without Yarnin’s suggestion about touch. In fact if I try to use the line

set saveMappingLocation to (POSIX file (path name of save panel))

I get an error during execution. In fact the only way I can get the POSIX file type casting to work in my code is to have

set theFile to theFile as POSIX file

in my writeToFile function. Go figure!

Thanks again guys for the help. - Jack

The only thing crossing my mind is that I’ve got problems with my Mac OS X developer tool installation (I’ve got OS 10.3.5 with Xcode 1.2 (IDE 309.0, Core 310.0, ToolSupport 307.0). Or that by selecting the droplet template as the starting source of my application does not give me full panel functionality. Anyone have any thoughts on this?