Reading binary files, byte-wise, in AppleScript 2.x ?

Thanks again, Chris.

The original (a = b) test at the end was compromised by the adjustments to a and b in the new code for reading as integer. Fix: count the output list instead or use your slightly more efficient idea of performing the equality test immediately after the initial parameter analysis.

It’s not supposed to. But it does return too many values! Fix: perform the range parameter zero adjustments before the negative ones. Seems to work.

The “overlap” logic doesn’t work for ((a in {-3, -2}) and (b in {-3, -2})). Fix: special-case (a >= -4). (Read the last four bytes and shift the result mathematically.)

Probably something to do with the overrun correction for reading the last integer in the file. Fix: don’t correct if (a > fileLength).

Your test script looks interesting. I’ll be getting to grips with it later on today.

Yes, I was confused about how a negative endpoint worked when combined with a zero endpoint. I should have been testing for 0 to -(fileLength +2) to generate an error (as it does with a bare read . as data). I fleshed out the zero-based testing to check for past-end errors (0 to -1), before-start errors (0 to (-fileLength+2)), full-file reads (0 to -2), first-byte only reads (0 to -(fileLength+1)), past-end with eof (0 to eof, and eof to 0).

Your latest version passes all the updated tests. I have re-published the test script in my previous message. The testing code is still a mess, but having automated testing that is a bit messy is (in my opinion) much preferable to not having any automated testing at all.

As far as speed goes, your original version (“v0”) finishes the latest test in as little as 20 seconds on my machine. Your latest version (“v1.3.2”) finishes in as little as 12 seconds, for a 40% time reduction for the reads done by the tests. I “ported” the endpoint calculations from your latest version to the original version to let it pass all the tests, too. The fixed original version (“v0.1”) finished in 18 seconds, so the time reduction for the latest version is only 33% as compared to a fully-passing original version.

Thank you for all your work on this. I have definitely enjoyed working on it!

My own attempt at a test script has just revealed that one of the bugs was only partially cured. Happily, it’s just a matter of changing one letter in the code and the comment above it. :slight_smile:

Here’s the test script, for the curious:

on main()
	set t to (GetMilliSec)
	set testScript to (load script file ((path to desktop as Unicode text) & "Scripts:Read As Unsigned Byte.scpt"))
	set testFile to prepareFile((path to desktop as Unicode text) & "Test.dat")
	set logFile to prepareFile((path to desktop as Unicode text) & "Results.log")
	set logRef to (open for access logFile with write permission)
	
	set astid to AppleScript's text item delimiters
	try
		set AppleScript's text item delimiters to ", "
		repeat with len from 0 to 10
			if (len > 0) then write (len * 16777216) as unsigned integer to testFile for 1 starting at eof
			repeat with a from -10 to 10
				repeat with b from -10 to 10
					try
						tell testScript to set r to (readAsUnsignedByte out of testFile from a to b)
					on error msg
						set r to msg
					end try
					if (r's class is list) then
						set r to " --> {" & r & "}"
					else if (r's class is integer) then
						set r to " --> " & r
					else
						set r to " --> "" & r & """
					end if
					write ("eof=" & len & ": " & a & " to " & b & r & return) as string to logRef starting at eof
				end repeat
			end repeat
		end repeat
		set AppleScript's text item delimiters to astid
	end try
	close access logRef
	set t to ((GetMilliSec) - t) / 1000
	
	tell application "TextEdit"
		activate
		open logFile
		set b to bounds of front window
		set item 3 of b to 800
		set bounds of front window to b
	end tell
	
	return t
end main

on prepareFile(thePath)
	set fRef to (open for access file thePath with write permission)
	try
		set eof fRef to 0
	end try
	close access fRef
	
	return thePath as alias
end prepareFile

main()

So have I! Thanks for your suggestions and comments. :slight_smile: