I’m working on an AppleScript that reads the first four bytes of a file to determine whether or not it is a WordPerfect, then reads the thirteenth byte to determine whether the file is encrypted, then reads the eleventh byte to determine which WordPerfect version created the file.
As the script stands now, I read the file three times, like this:
set wpBytes to ((read file (checkItem as text) from 1 to 4 as data) is «data rdatFF575043»)
if wpBytes is true then
set isReadable to ((read file (checkItem as text) from 13 to 13 as data) is «data rdat00»)
if isReadable is false then
set cryptVer6 to ((read file (checkItem as text) from 11 to 11 as data) is «data rdat02»)
if cryptVer6 is true then
display dialog (the name of checkItem) & return & return & "is an encrypted (password-protected) file created by WordPerfect 6 or later." & return & return & "I cannot convert this file." buttons {"OK"} with icon stop
end if
end if
end if
Obviously, this is hopelessly inefficient. But I have not been able to figure out how to read all the bytes I need in a single operation. I would be very grateful for any advice on how to do this in one operation rather than three.
Thank you!
It’s not so much reading the file three times which is inefficient but opening and closing it three times in the process. Also, to judge from the ‘name’ keyword in the middle of it all, your code’s inside a tell block to some application other than the one running the script. Consequently, that other application’s being told to do the reading, with all that implies for inter-application communication overheads. Less significantly, the ‘if is true’ construction is twice the work of ‘if ’.
One possibility for speeding up the three data reads would be:
end tell -- Stop telling the other application. (The Finder?)
set fRef to (open for access file (checkItem as text)) -- Open the file just once and use the returned access reference for the three reads.
try
set cryptVer6 to (((read fRef for 4 as data) is «data rdatFF575043») and ((read fRef from 13 for 1 as data) is not «data rdat00») and ((read fRef from 11 for 1 as data) is «data rdat02»))
end try
close access fRef -- Close the file again.
if (cryptVer6) then tell application "Finder" to display dialog (the name of checkItem) & return & return & "is an encrypted (password-protected) file created by WordPerfect 6 or later." & return & return & "I cannot convert this file." buttons {"OK"} with icon stop
Or you could read the first fourteen byes in one go as short integers and analyse the resulting list:
end tell -- Stop telling the other application. (The Finder?)
tell (read file (checkItem as text) for 14 as short) to set cryptVer6 to ((it begins with {-169, 20547}) and (((item 7) + 65536) mod 65536 div 256 is not 0) and (((item 6) + 65536) mod 65536 div 256 is 2))
if (cryptVer6) then tell application "Finder" to display dialog (the name of checkItem) & return & return & "is an encrypted (password-protected) file created by WordPerfect 6 or later." & return & return & "I cannot convert this file." buttons {"OK"} with icon stop
Nigel,
Both of those are exactly the kind of lucid and efficient advice (and explanations!) that I had hoped someone would be kind enough to offer. Thank you.
You’re right - this is in a tell-application-“Finder” block. Your suggestions will make this far more efficient.
Thank you again - and thank you especially for the deeper understanding of how Applescript works.