Hello.
This is a collection of handlers, as found in the now so venerable Scripting Additions Guide, while you hopefully still can get it. I just dump this here, for the hope that anybody can use it.
The stuff is copyright Apple I guess, but they never copyrighted it, I take the full responsibilty for any faults I may have introduced, and there are no warranties, but I hope someone may find them useful, while they read the Scripting Additions Guide.
It is rather unpolished, but it did work for me.
--Listing 2-1 Reading a specific record from a text-based database file
--first choose data file to work with
set pathToUse to choose file
try
set x to open for access pathToUse
set z to ReadRecord(16, 1, tab, "
", x)
close access x
z --display requested record
on error errString number errNum
-- 72 Using Read/Write CommandsCHAPTER 2
-- Scripting Addition Commands
display dialog errString
close access x
end try
on ReadRecord(numberOfFields, whichRecord, fieldDelimiter, recordDelimiter, fileRefNum)
try
(*
if there's a record delimiter, read all fields except for last using field delimiter, then
read last field using record delimiter *)
if recordDelimiter is "" then
set readxTimes to numberOfFields
else
set readxTimes to numberOfFields - 1
end if
repeat whichRecord times
set recordData to {}
repeat (readxTimes) times
set recordData to recordData & {(read fileRefNum before fieldDelimiter)}
end repeat
if readxTimes is not numberOfFields then
set recordData to recordData & {(read fileRefNum before recordDelimiter)}
end if
end repeat
return recordData
on error errString number errNum
display dialog errString
return errString
end try
end ReadRecord
-- Listing 2-2 Deleting a record from a text-based database file
--choose data file to use
-- global startSize, idx, preRecordSize, accumulatedSize, readxTimes, fileBuffer, q
-- set q to 0
-- set startSize to 0
-- set preRecordSize to 0
-- set accumulatedSize to 0
-- set readxTimes to 0
-- Debugget MYE 3/6/2012 Tommy Bollman
-- A) sørget for at vi beholdt return på linja vi har lest inn.
-- B) Sørget for at den nye fil størrelse ble korrekt, med hensyn til beregning av EOF
-- C) Sørget for at vi ikke utfører ulovlige operasjoner ved purge. enten hele fra start, eller siste post.
set pathToUse to choose file
--74 Using Read/Write CommandsCHAPTER 2
-- Scripting Addition Commands
try
set x to open for access pathToUse with write permission
DeleteRecord(16, 1, ";", return, x)
close access x
on error errString number errNum
display dialog errString
close access x
end try
on DeleteRecord(numberOfFields, whichRecord, fieldDelimiter, recordDelimiter, fileRefNum)
try
--initialize variables
set startSize to get eof fileRefNum --current size
set idx to 1 --counter
set preRecordSize to 1 --offset of record to delete
set accumulatedSize to 0 --total size of records read
if recordDelimiter is "" then
set readxTimes to numberOfFields
else
set readxTimes to numberOfFields - 1
end if
repeat with idx from 1 to whichRecord
repeat (readxTimes) times
set q to read fileRefNum as text until fieldDelimiter
set accumulatedSize to accumulatedSize + (length of q)
end repeat
if readxTimes is not numberOfFields then
set q to read fileRefNum as text until recordDelimiter
set accumulatedSize to accumulatedSize + (length of q)
end if
-- Using Read/Write Commands 75
-- CHAPTER 2
--Scripting Addition Commands
(*
if record to delete is the first record in file or the next record that will be read,
set preRecordSize *)
if whichRecord is 1 or idx is whichRecord - 1 then
if whichRecord is 1 then
set preRecordSize to 0 -- var 1 BUG A korreksjon
else
set preRecordSize to accumulatedSize
end if
end if
end repeat
(* now that preRecordSize is determined, read the record to be deleted so file mark is
set to beginning of next record *)
if (startSize - accumulatedSize) is not 0 then
set fileBuffer to read fileRefNum from accumulatedSize + 1 -- BUG C korreksjon
--next, overwrite record to be deleted with remainder of file
write fileBuffer to fileRefNum as text starting at preRecordSize + 1 -- BUG A korreksjon
set eof fileRefNum to (startSize - (accumulatedSize - preRecordSize)) -- BUG B korreksjon
else
(*
if the file contains only the record to be deleted,
set the end of the file to 0 *)
if whichRecord is 1 then
set eof fileRefNum to 0 (*
if record to be deleted is last record in file, just shrink the file *)
else
set eof fileRefNum to preRecordSize -- BUG A korreksjon INGEN; recordskiller er med her
end if
end if
on error errString number errNum
display dialog errString
end try
end DeleteRecord
-- Listing 2-3 Inserting a record in a database file
--choose file to work with
set pathToUse to choose file
-- Using Read/Write Commands 77CHAPTER 2
-- Scripting Addition Commands
try
(* first put the record to be added into a variable; in this case the record to be added is actually an AppleScript list because the file on disk doesn't include label data *)
set newRecord to {"Granny", "Knutsen", "123 Potato Chip Lane", "Palo Minnow", "CA", "98761", "Snackable Computer", "888-987-0987", "978 -234-5432", "123-985-1122"}
set x to open for access pathToUse with write permission
AddRecord(newRecord, -1, tab, return, x) -- addrecord # 5 uheldig når det ikke er 5 records i fil...
close access x
on error errString number errNum
display dialog errString
close access x
end try
on AddRecord(recordToAdd, addWhere, fieldDelimiter, recordDelimiter, fileRefNum)
try
--initialize variables
set idx to 1 --counter
set preRecordSize to 1 --offset of byte at which to add file
set accumulatedSize to 0 --total size of records read
set numberOfFields to count of recordToAdd
if recordDelimiter is "" then
set readxTimes to numberOfFields
else
set readxTimes to numberOfFields - 1
end if
(* Addendum 9/6 2012 17:18 writing a record to the end of file, this can happen
when creating a file, or the item will be inserted at the end! *)
if addWhere is -1 then
set fileend to get eof of fileRefNum
write "" to fileRefNum starting at fileend + 1 --sets write pointer to point at eof.
WriteNewRecord(recordToAdd, fieldDelimiter, recordDelimiter, fileRefNum) --now add back the rest of the record
return
end if
(*
if the record is to be added at the beginning of the file, this
If statement adds the record *)
if addWhere is 1 then
--read from beginning of file and store in postBuffer
--offset of byte at which to add file 0 --total size of records read
-- 78 Using Read/Write Commands
--CHAPTER 2
-- Scripting Addition Commands
-- try
-- for det tilfelle at fila var tom!
set postBuffer to read fileRefNum from 1
-- on error
-- set postBuffer to ""
-- end try
(* before writing new record, file mark must be reset to beginning of file; to do this,
write an empty string to the beginning of file *)
write "" to fileRefNum starting at 0
WriteNewRecord(recordToAdd, fieldDelimiter, recordDelimiter, fileRefNum) --now add back the rest of the record
write postBuffer to fileRefNum
return
end if
(*
if the record is to be added somewhere other than at the beginning of the file, the rest of the AddRecord handler is executed *)
repeat with idx from 1 to addWhere - 1
repeat (readxTimes) times
set q to read fileRefNum until fieldDelimiter
set accumulatedSize to accumulatedSize + (length of q)
end repeat
if readxTimes is not numberOfFields then
set q to read fileRefNum until recordDelimiter
set accumulatedSize to accumulatedSize + (length of q)
end if
end repeat
(* read from beginning of file to the byte at which the new record is to be added *)
set postBuffer to read fileRefNum from accumulatedSize + 1
(* before writing new record,
set file mark to byte at which new record is to be added; to do this,
write an empty string to that byte *)
write "" to fileRefNum starting at accumulatedSize + 1
WriteNewRecord(recordToAdd, fieldDelimiter, recordDelimiter, fileRefNum)
-- Using Read/Write Commands 79
-- CHAPTER 2
--Scripting Addition Commands
--now add back the rest of the record
write postBuffer to fileRefNum
on error errString number errNum
display dialog errString
end try
end AddRecord
on WriteNewRecord(recordToAdd, fieldDelimiter, recordDelimiter, fileRefNum)
try
set numberOfFields to count of recordToAdd
if recordDelimiter is "" then
set readxTimes to numberOfFields
else
set readxTimes to numberOfFields - 1
end if
repeat with idx from 1 to numberOfFields
if idx ≤ readxTimes then
write item idx of recordToAdd & fieldDelimiter to fileRefNum
else
(*
if file uses a record delimiter,
write delimiter after the last field in the record *)
write item idx of recordToAdd & recordDelimiter to fileRefNum
end if
end repeat
on error errString number errNum
-- 80 Using Read/Write CommandsCHAPTER 2
--Scripting Addition Commands
display dialog errString
end try
end WriteNewRecord
script textDatabase
-- Start Clipping:
-- clippingsname: OpenFileIfItExists({hfsPathAsText;theFile,blnIfWritingAllowed;writePermission,forceCreation;blnIfMakeFileSilently,procnameAsText;scriptName,appBundleId;frontappId}) -- Returns Errnumber, or File Reference Number
-- clippingscontents: textDatabase's OpenFileIfItExists({hfsPathAsText:theFile,blnIfWritingAllowed:writePermission,forceCreation:blnIfMakeFileSilently,procnameAsText:scriptName,appBundleId:frontappId}) -- Returns Errnumber, or File Reference Number
-- End Clipping:
-- on OpenFileIfItExists({hfsPathAsText:theFile,blnIfWritingAllowed:writePermission,forceCreation:blnIfMakeFileSilently,procnameAsText:scriptName,appBundleId:frontappId}) -- Returns Errnumber, or File Reference Number
on OpenFileIfItExists(R) -- Returns Errnumber, or File Reference Number
-- R : {hfsPathAsText:theFile,blnIfWritingAllowed:writePermission,forceCreation:blnIfMakeFileSilently,procnameAsText:scriptName,appBundleId:frontappId}
local AlertStopIconFile, x, theFirstErrMsg, theSecondErrMsg, firstErrorNum, secondErrorNum, thethirdErrMsg, thirdErrnumber, btnResult, failed, thefourthErrMsg, fourthErrnumber
if not (forceCreation of R) then
set AlertStopIconFile to a reference to file ((path to library folder from system domain as text) & "CoreServices:CoreTypes.bundle:Contents:Resources:AlertStopIcon.icns")
-- set AlertStopIconFile to textDatabase's EnvironmentLIb's getResourceIconFile({icsFile:"AlertStopIcon.icns", appBundleId:(appBundleId of R)})
end if
set V to {emsg:"", num:0}
try
(*
if ( hfsPathAsText of R) doesn't exist, Info For returns error -43 *)
set x to info for file (hfsPathAsText of R)
if (blnIfWritingAllowed of R) is true then
set num of V to (open for access file (hfsPathAsText of R) with write permission)
else
--82 Using Read/Write CommandsCHAPTER 2
--Scripting Addition Commands
set num of V to (open for access file (hfsPathAsText of R))
end if
on error theFirstErrMsg number firstErrorNum
if not (forceCreation of R) then
try
--if error is -43, the user can choose to create the file
set btnResult to ""
tell application "SystemUIServer"
activate
set failed to false
try
set btnResult to button returned of (display dialog (my textDatabaseprivate's makePosixPath(hfsPathAsText of R) & "
Does Not Exist") with title (procnameAsText of R) buttons {"Create It For Me", "Cancel", "Ok"} default button 2 cancel button 2 with icon AlertStopIconFile)
on error theSecondErrMsg number secondErrorNum
if n is -128 then
set failed to true
else
set emsg of V to theSecondErrMsg
set num of V to secondErrorNum
return V
end if
end try
end tell
if failed is true then
set emsg of V to "User Aborted It"
set num of V to -60000
return V
end if
if btnResult is "Ok" then
set emsg of V to theFirstErrMsg
set num of V to firstErrorNum
return V
else
--create the file
if (blnIfWritingAllowed of R) is true then
set num of V to open for access file (hfsPathAsText of R) with write permission
else
set num of V to open for access file (hfsPathAsText of R)
end if
end if
on error thethirdErrMsg number thirdErrnumber
set emsg of V to thethirdErrMsg
set num of V to thirdErrnumber
end try
return V
else -- just force the creation
try
if (blnIfWritingAllowed of R) is true then
set num of V to open for access file (hfsPathAsText of R) with write permission
else
set num of V to open for access file (hfsPathAsText of R)
end if
on error thefourthErrMsg number fourthErrnumber
set emsg of V to thefourthErrMsg
set num of V to fourthErrnumber
end try
return V
end if
end try
return V
end OpenFileIfItExists
-- on OpenFileIfItExists(theFile, writePermission)
-- set AlertStopIconFile to my EnvironmentLIb's getResourceIconFile({icsFile:"AlertStopIcon.icns", appBundleId:frontappId})
-- try
-- (*
-- if theFile doesn't exist, Info For returns error -43 *)
-- set x to info for file theFile
-- if writePermission is true then
-- return (open for access file theFile with write permission)
-- else
-- --82 Using Read/Write CommandsCHAPTER 2
-- --Scripting Addition Commands
-- return (open for access file theFile)
-- end if
-- on error theErrMsg number errorNum
-- try
-- --if error is -43, the user can choose to create the file
-- set btnResult to ""
-- tell application "SystemUIServer"
-- activate
-- set failed to false
-- try
-- set btnResult to button returned of (display dialog theFile & "
-- Does Not Exist" with title "Open File If It Exists" buttons {"Create It For Me", "Cancel", "Ok"} default button 2 cancel button 2 with icon file AlertStopIconFile)
-- on error e number n
-- set failed to true
-- end try
-- end tell
-- if failed is true then error number -6000
-- if btnResult is "Ok" then
-- return errorNum
-- else
-- --create the file
-- if writePermission is true then
-- return open for access file theFile with write permission
-- else
-- return open for access file theFile
-- end if
-- end if
-- on error theErrMsg number theerrnumber
-- return theerrnumber
-- end try
-- end try
-- end OpenFileIfItExists
on writeheadOfFileReferenceAsUtf8BOM(fRef, stuff) -- Returns record, to store any error message in.
-- ! NB! det siste tegnet i stuff bør være en newline...
-- hakket mitt besørger at fil blir til ut f8 selv om det bare havner ascii i den
-- etterpå!, så tegnsettet kommer korrekt ut i preview!
local stuff, fRef, Msg, n, mybuffer, startsize, fsz, V
set V to {emsg:"", num:0}
try
set startsize to get eof fRef
if not startsize is 0 then
set mybuffer to read fRef from 1 to startsize as «class utf8»
else
write «data rdatEFBBBF» to fRef -- as «class utf8» -- BOM Thanks! to Nigel Garvey
end if
write stuff to fRef as «class utf8» starting at 4
if not startsize is 0 then
write mybuffer to fRef as «class utf8»
end if
set fsz to get eof fRef
close access fRef
set num of V to fsz
on error Msg number n
try
close access fRef
end try
set emsg of V to Msg
set num of V to n
end try
return V
end writeheadOfFileReferenceAsUtf8BOM
-- mark jfileLib¢writeTo<B
-- >> jfileLib¢writeTo
(*
writeTo
writes given data to given file as given mode, and returns an alias to the file
Parameters:
f: file path, alias, posix path (the file to be written, can exist or not)
stuff: stuff to write to the file
mode: how to write the data (text, list, record, «class utf8», C string, etc)
Example:
writeTo("path:to:file.txt", {1,2,3}, list) --> alias "path:to:file.txt"
*)
to writeToFileReferenceAsUtf8BOM(fRef, stuff, mode)
set V to {emsg:"", num:0}
local stuff, fRef, Msg, n, startsize, fsz, V
try
set eof of fRef to 0
write «data rdatEFBBBF» to fRef -- as «class utf8» -- BOM Thanks! to Nigel Garvey
write stuff to fRef as «class utf8» starting at 4
set fsz to get eof fRef
close access fRef
set num of V to fsz
on error Msg number n
try
close access fRef
end try
set emsg of V to Msg
set num of V to n
end try
return V
end writeToFileReferenceAsUtf8BOM
on writeheadOfFileReferenceAsUtf8(fRef, stuff)
-- ! NB! det siste tegnet i stuff bør være en newline...
-- hakket mitt besørger at fil blir til ut f8 selv om det bare havner ascii i den
-- etterpå! Virker i bbedit, ikke i preview!
local stuff, fRef, Msg, n, mybuffer, startsize, fsz
try
set startsize to get eof fRef
if not startsize is 0 then
set mybuffer to read fRef from 1 to startsize as «class utf8»
else
write "æøå" to fRef starting at 0 as «class utf8» --utf8 no bom!
end if
set eof fRef to 0
write stuff to fRef as «class utf8»
if not startsize is 0 then
write mybuffer to fRef as «class utf8»
end if
set fsz to get eof fRef
close access fRef
return fsz
on error Msg number n
try
close access fRef
end try
return n
end try
end writeheadOfFileReferenceAsUtf8
on writeTailOfFileReferenceAsUtf8(fRef, stuff)
-- Denne brukes til begge utf8 variantene.
local stuff, fRef, Msg, n, fsz
try
write stuff to fRef starting at eof as «class utf8»
set fsz to get eof fRef
close access fRef
return fsz
on error Msg number n
try
close access fRef
end try
return n
end try
end writeTailOfFileReferenceAsUtf8
on writeheadOfFileReference(fRef, stuff)
-- ! NB! det siste tegnet i stuff bør være en newline...
-- Skriver ikke u-tf 8 automatisk. på min maskin...
-- det avhenger vel av hva slags tegn som kommer inn der...
-- mac roman kan ofte bli resultatet
local stuff, fRef, Msg, n, mybuffer, startsize, fsz
try
set startsize to get eof fRef
if not startsize is 0 then
set mybuffer to read fRef from 1 to startsize
set eof fRef to 0
end if
write stuff to fRef starting at 0
if not startsize is 0 then
write mybuffer to fRef
end if
set fsz to get eof fRef
close access fRef
return fsz
on error Msg number n
try
close access fRef
end try
return n
end try
end writeheadOfFileReference
on writeTailOfFileReference(fRef, stuff)
local stuff, fRef, Msg, n, fsz
try
write stuff to fRef starting at eof
set fsz to get eof fRef
close access fRef
return fsz
on error Msg number n
try
close access fRef
end try
return n
-- error msg number n
end try
end writeTailOfFileReference
script textDatabaseprivate
----------------------------------------------------------------------------------
-- unixpath method:
-- Get the posix path (unix path).
-- Doesn't handle accented characters. I'm open to suggestions that are not based on shell wildcards (too dangerous when deleting file(s)).
----------------------------------------------------------------------------------
-- argument:
-- macpath: an alias or path string
-- return:
-- posix path string
----------------------------------------------------------------------------------
-- nicked from BBEdit lib
on makePosixPath(macpath)
set unixpath to POSIX path of macpath
set unixpathlist to every character of unixpath
repeat with i from 1 to length of unixpathlist
-- took badchars list from http://www.macosxhints.com/article.php?story=20011217040113759
set badchars to {" ", "'", "!", "$", "\"", "*", "(", ")", "{", "[", "|", ";", "<", ">", "?", "~", "`", "\\"}
set thisItem to item i of unixpathlist as text
if thisItem is in badchars then set item i of unixpathlist to ("\\" & thisItem)
end repeat
set unixpath to unixpathlist as string
return unixpath
end makePosixPath
end script
end script