I expanded the routine which was published once to be able
to write selectively text, UTF8 and UTF16 data to a file with AppleScript’s Standard OSAX
set myTestfile to ((path to desktop) as string) & "write_to_file_test"
write_to_file from "Hallo World" into myTestfile by 3 without append -- parameter notes: target=path string; textClass 1=text, 2=UTF8, 3=UTF16
on write_to_file from |data| into target by textClass given append:append
script t
property textClassList : {string, «class utf8», Unicode text}
end script
try
set datastream to open for access file target with write permission
if append is false then set eof of datastream to 0
-- write BOM if text class is Unicode text
if (get eof of datastream) = 0 and textClass = 3 then write (ASCII character 254) & (ASCII character 255) to datastream
write |data| to datastream as (item textClass of t's textClassList) starting at eof
close access datastream
return true
on error
try
close access file target
end try
return false
end try
end write_to_file
I’ve added this to my script library recently (it’s based on yours, Stefan):
(* `writeFile` parameters
---------------------
someData [anything] The data to be written.
someFile [mixed] The file to write to; Must be an alias, file, or text.
textClass [class] The class the data should be saved as; Should be either Unicode text, «class utf8», or string.
bom [bool] Add a BOM to new or overwritten files for Unicode text or «class utf8».
append [bool] Add to the existing data or overwrite it?
*)
on writeFile from someData into someFile given class:textClass, bom:includingBOM, append:append
try
tell (someFile's class) to if it is not file or it is not alias then set someFile to file specification someFile
open for access someFile with write permission
set fileRef to result
if not append then set eof of fileRef to 0
if includingBOM and ((get eof of fileRef) is 0) then
if textClass is Unicode text then write (ASCII character 254) & (ASCII character 255) to fileRef
if textClass is «class utf8» then write (ASCII character 239) & (ASCII character 187) & (ASCII character 191) to fileRef
end if
write someData to fileRef as textClass starting at eof
close access fileRef
return true
on error errMsg number errNum
try
close access fileRef
end try
--error errMsg number errNum
return false
end try
end writeFile
Edit: Example usage:
set theFolder to (path to home folder as Unicode text)
writeFile from "Hello, World!" into (theFolder & "Test UTF-8.txt") without bom and append given class:«class utf8»
writeFile from "Hello, World!" into (theFolder & "Test UTF-8 BOM.txt") with bom without append given class:«class utf8»
writeFile from "Hello, World!" into (theFolder & "Test UTF-16.txt") with bom without append given class:Unicode text
writeFile from "Hello, World!" into (theFolder & "Test String.txt") without bom and append given class:string
Nice handlers! Interestingly, although it’s still necessary to specify ‘as Unicode text’ or 'as «class utf8» when reading the files with the File Read/Write ‘read’ command, the BOMs are recognised for what they are and aren’t included in the result.
More for interest than for any great improvement, here are a couple of alternative ways to write the BOMs, in case they appeal to you:
if includingBOM and ((get eof of fileRef) is 0) then
if textClass is Unicode text then write -257 as short to fileRef -- Short integer with hex value FEFF
if textClass is «class utf8» then write -272908544 for 3 to fileRef -- First 3 bytes of integer with hex value EFBBBF00!
end if
Or:
if includingBOM and ((get eof of fileRef) is 0) then
if textClass is Unicode text then write «data rdatFEFF» to fileRef
if textClass is «class utf8» then write «data rdatEFBBBF» to fileRef
end if
-- someData : Data (anything) to be written
-- someFile : File to write to; An alias, file, file specification, or text is expected
-- dataClass : Class the data should be written as (e.g. text, Unicode text, or «class utf8»)
-- appending : Should new data be appended to existing data?
--
on writeFile for someData into someFile given class:dataClass, appending:appending
try
if class of someFile is not in {alias, file, file specification} then ¬
set someFile to file specification someFile
open for access someFile with write permission
set fileRef to result
if not appending then set eof of fileRef to 0
if appending and dataClass is Unicode text then write «data rdatFEFF» to fileRef
write someData to fileRef as dataClass starting at eof
close access fileRef
on error errMsg number errNum
try
close access fileRef
end try
error errMsg number errNum
end try
end writeFile
writeTempFile:
-- someData : Data (anything) to be written
-- dataClass : Class the data should be written as
--
on writeTempFile for someData given class:dataClass
try
do shell script "/usr/bin/mktemp -t writeTempFile"
set tempFile to result as POSIX file
open for access tempFile with write permission
set fileRef to result
if dataClass is Unicode text then write «data rdatFEFF» to fileRef
write someData to fileRef as dataClass starting at 0
close access fileRef
return tempFile as alias
on error errMsg number errNum
try
close access fileRef
end try
error errMsg number errNum
end try
end writeTempFile
Oy. I really should have learned to read the whole thread before posting by now! Oh well, I’ll leave it here.
I have a similar bit of code. Perhaps it’s interesting to you.
set parameters to {theData:{"hello"}, toFile:"titan:Users:paulskin:Desktop:bob"}
WriteData(parameters)
on WriteData(parameters)
set previousTIDs to AppleScript's text item delimiters --Store the TIDs' initial value.
try
----------------SingleArgumentCore---------------
set AppleScript's text item delimiters to ""
try
set theData to theData of parameters
on error
if class of parameters is string then
set theData to parameters
else
WriteData()
end if
end try
try
set toFile to toFile of parameters
tell application "Finder"
if class of toFile is alias then set toFile to toFile as text
if ((class of toFile) is document file) then set toFile to (toFile as alias) as text
end tell
on error
try
set toFile to ((path to desktop folder) as text) & (datetimeStamp of DateAndTime({}))
on error
set toFile to ((path to desktop folder) as text) & ((time of (current date)) as text)
end try
end try
try
set asClass to asClass of parameters
on error
set asClass to class of theData
end try
try
set target to open for access file toFile with write permission
on error
end try
try
write theData to target as asClass
on error
end try
try
close access target
on error
end try
return toFile
--------------------------------------------------
set AppleScript's text item delimiters to previousTIDs --Restore the TIDs to their initial value.
return the output
on error errorMessage number errorNumber partial result errorResult from errorFrom to ErrorTo
set AppleScript's text item delimiters to "" --Modify unhandled errors to include the class and name of this object.
set errorMessage to ("The " & (class of WriteData) & " '" & "WriteData" & "' generated an error." & return & the errorMessage) as text
set AppleScript's text item delimiters to previousTIDs
error errorMessage number errorNumber partial result errorResult from errorFrom to ErrorTo
end try
end WriteData
--Documentation for WriteData.
--These properties can be referenced for documentation and for version and dependency checking.
property name : "WriteData" --The name of this script object. <TEXT>
property objects : {WriteData} --A list of objects that are within this script object. <LIST>
property version : 1.0 --A version code for this object. <REAL>
property dependencies : {asDependencies:{}, osDependencies:{}, osaxDependencies:{}, handlerDependencies:{}, applicationDependencies:{}} --<RECORD>
property documentation : "WriteData Object.
WriteData will write the passed data to a file. The file can be specified or allowed to default to the desktop. A name for the file can be specified or allowed to default to a Date & Time stamp.
Parameters: STRING or
RECORD {theData:theData,toFile:toFile,asClass:asClass}
theData: Anything.
toFile: A file path, file reference or ALIAS.
asClass: The class to try to write theData as.
Output: An ALIAS to the written file.
Error Handling: Errors that are not handled by WriteData internally will be modified to contain the name and class of WriteData before being thrown.
Paul Skinner 2002
paulskinner@mac.com
" --<TEXT>