Write to File

Many people don’t realize that you can write to a text file using Standard Additions but even more don’t realize you can write files that store more than just text. In this example, I create a list of records, write it to a file, then read the file back in and the records and all of their labels and values (including value classes) are retained. This is a very useful feature and makes it a snap to save and load preferences for your scripts. You can also save other types of data such as images.

OS version: OS X

set the_file to (((path to desktop) as string) & "test.txt") as file specification

set record_1 to {record_name:"Record A", record_value:{"This", "is", "a", "list.", 1, 2, 3}}
set record_2 to {record_name:"Record B", record_value:"A string."}
set record_3 to {record_name:"Record C", record_value:1.0 as real}
set the_data to {record_1, record_2, record_3}

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 as list
	close access the_file
on error
	try
		close access the_file
	end try
end try

set read_data to read the_file as list

When I try this script out, it adds in some extra text garbage like “LIST” and “TEXT” in between the elements. Is there a way have AS not put that in there when converting a list to text?

Hi, Byron.

If an AppleScript list has been written to file, as in Trash Man’s script, “LIST” and “TEXT” are there in the file along with some other stuff as part of the stored list structure. In ‘read the_file as list’, the ‘as list’ is a parameter (not a coercion) that tells ‘read’ to interpret the data as a list. If instead you use ‘read the_file as text’, or just ‘read the_file’, the ‘read’ command assumes that the file just contains text and interprets the data as such “ and you see things you’re not meant to see. :slight_smile:

So: if you have a file containing list data, and you want to coerce the list to text, you have to read it first as a list and then coerce the list to text:

set read_data to (read the_file as list) as text

Note that:

  1. The first ‘as’, not separated from ‘read’ by parentheses, is a labelled parameter of ‘read’. The second ‘as’ is an AppleScript coercion.
  2. This won’t work with Trash Man’s list as it contains records, which can’t be coerced to string.
  3. Incidentally, ‘path to’ too has an optional ‘as’ parameter, whose use is slightly more efficient than an AppleScript coercion:
((path to desktop) as string) -- 'path to' returns an alias, which AppleScript then coerces to string.
(path to desktop as string) -- 'path to' returns a string directly.

-- However, the received wisdom nowadays is to use Unicode text for paths:
(path to desktop as Unicode text) -- 'path to' returns Unicode text directly.

I am looking to add a list of filenames from a folder to a text file as a list. I am pretty new at this and thought I’d start with the script you posted above. I’m having problems with it though, I’m not sure if it’s because I’m on snow leopard or what, but the first line is failing at “file specification”:

error “Can’t make "Macintosh HD:Users:prepress:Desktop:test.txt" into type file specification.” number -1700 from “Macintosh HD:Users:prepress:Desktop:test.txt” to file specification

Hi,

the original script is very old, meanwhile file specification is deprecated.

Change the first line into


set the_file to ((path to desktop as text) & "test.txt")

and the open for access line into


open for access file the_file with write permission

I never New that records could be stored to a file and read back in as records.

If I read this correctly, the new script could resemble this.

set the_file to ((path to desktop) & "test.txt")

set the_data to {1, 2, 3, 4, 5, 6}

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

set read_data to (read the_file as list) as text

I’ve eliminated the records to keep it simple.
Yet this code still gives a -1700 error under OS X 10.6.2. What else needs to be changed to write a list to file?

thanks for your help.

Hi,

the main problem is, that the result of

set the_file to ((path to desktop) & "test.txt")

is a list {alias “MacHD:Users:myUser:Desktop:”, “test.txt”}, not a string path.

If the path is a string path, you should add the keyword file to define a file specifier.
And it’s preferable to use the data pointer instead of the file itself to write the data to


set the_file to ((path to desktop as text) & "test.txt")

set the_data to {1, 2, 3, 4, 5, 6}

try
	set dataStream to open for access file the_file with write permission
	set eof of dataStream to 0
	write the_data to dataStream starting at eof as list
	close access dataStream
on error
	try
		close access file the_file
	end try
end try

set read_data to (read file the_file as list) as text

Hi,
How do I get the information out of the file?

If you should have read the post right above your post, and if you should have read the last line of StefanK’s script, you should know the answer

Yes but individual variables.

If you can’t figure out that the_file is an alias, I guess you should read a basic tutorial about AppleScript

set chosenFile to (choose file with prompt "Choose an AppleScript list file.")
set myList to (read chosenFile as list)

--set chosenItem to choose from list myList
  1. I started using Apple Script today.
  2. I couldn’t find any good tutorials.
  3. I haven’t done much programming before.(No experience with Perl, but some with C++(very basics)

Well then. Here at MacScripter there are some very good tutorials. I have learned everything I needed to make my scripts and applications in applecript. It can be accessed thru the unScripted category or just click the link below. There are also some very good tutorials about applescript studio.

http://macscripter.net/viewtopic.php?id=25631

Thanks. But I can’t seem to download the developer tools fro the Apple website. Any help?

If you have Leopard or tiger, you can install them with the installation-DVD you were given when you bought your Mac. For Snow Leopard I don’t know.

You can get some quite useful information from The applescript scripting additions guide as well. The standard additions are described there. Thought I’d just mention it, as this post reminded me of the subroutines of reading and writing files of records because I remembered the stuff about files and records in that guide as an exceptionally good read up. Having said that I think the documentation from the source held a good standard, even the Applescript finder guide though it is a bit outdated.

The url to the Scripting Additions guide is here: http://download.info.apple.com/Apple_Support_Area/Manuals/software/0305098AASADDGENG.PDF

McUsr

OK. I have an issue that really stumps me, and I could use some help. Picture this:

Two Machines. One at home. One at office.
Home machine is Intel machine running Snow Leopard (10.6.4).
Office machine is PPC G5 machine running Leopard (10.5.8)

I run the IDENTICAL code on each (below).

When I write the file from office and read it from office, no problem.
When I write the file from home and read it from home, no problem.

When I write the file from office and read it from home, no problem.
HOWEVER, when I write the file from home and read from office. I get an error.
Seems the data files should be identical, but they are apparently not.

The error I get at office while reading the file created at home is: Can’t get pName of {|pName|:“Created At Home”}.

Note that when the home machine saves the record and that data is read at the office the label has a vertical bar on each side of it. Vertical bar is not present with data files created at office. Is this a difference between Leopard and Snow Leopard somehow? Any ideas on fixing this problem are appreciated.

–Script starts here

set ourRawData to {pName:“Created At Home”} --Simple Record for test purposes. Actual record has many properties.

display dialog “What do you want to do?” buttons {“Read”, “Write”}
set ourResult to button returned of result

if ourResult is “Read” then
set theData to ReadLatestData()
display dialog pName of theData
else if ourResult is “Write” then
WriteLatestData(ourRawData)
end if

–***************************************************
on WriteLatestData(LatestData) --Write a datafile called “LatestData” that is stored in application. “LatestData” will contain the current “LatestData” array
set fileName to (path to desktop folder as Unicode text) & “LatestData”
set outFile to open for access fileName with write permission
write LatestData as record to outFile
close access outFile
end WriteLatestData

–***************************************************
on ReadLatestData() --Read a datafile called “LatestData” to be stored in application. “LatestData” contains last used information
set fileName to (path to desktop folder as Unicode text) & “LatestData”
set ourFile to open for access fileName
set LatestDataFromFile to read ourFile as record
close access ourFile
return LatestDataFromFile
end ReadLatestData

–***************************************************

Hi, Boberino.

It’s to do with the upper-case “N” in your pName label.

Before Snow Leopard, user labels in records had to be all-lower-case. if you wanted to use upper-case characters, you had to put “bars” round the labels in the source code: eg. |pName|. As from Snow Leopard, this isn’t necessary.

Your Leopard machine writes the unbarred pName label to the file as pname to satisfy the “lower case” rule. It reads this back as an unbarred, lower-case label and ” since the case of labels doesn’t matter within the script itself ” disregards the case of the label in the script code. If you were to use the barred label |pName|, it would be written to the file as pName (mixed case, no bars) and would be interpreted as a barred label when read back

Your Snow Leopard machine interprets the lower-case label in the Leopard file in exactly the same way as the Leopard one does, so the result is the same on both machines.

However, since the “lower case” rule doesn’t apply to user labels in Snow Leopard, that machine writes the mixed-case label to the file exactly as it is. It also reads it back exactly as it is. But the Leopard machine interprets the mixed-case data as a barred label, which doesn’t match the unbarred label in the script. Hence the error you’re getting.

For practical purposes, you should should humour the Leopard machine and use either lower-case labels or barred ones.

Hello.

I wonder if this and similar “quirks” are mentioned somewhere.
-This one was obviously a tricky one.

Best Regards

McUsr