Stack Overflow -2706

Seems that I’ve hit on a known limitation with AS in Script Editor. I came accross this article in the FAQ @ MS

http://macscripter.net/faq/get_the_faq.php?id=139_0_10_0_C

Does anybody have a good workaround for the “delimiter” issue as used below?


	tell application "Finder"
		set handle to open for access file ((Path2Me & "PrimeTargets.txt") as string)
		set PrimeTargetsRead to (read handle as {list} using delimiter {return})
		close access handle
	end tell

It seems that any use of the delimiter (ASTID) on a large file will cause the -2706 on exit. The weird part is, the rest of the code plays with the parsed file/data and writes the data back out to disk upon exit. Only then does the dreaded -2706 pop up “ requiring attention to continue. So it seems mostly innocous, but . . . :confused:

What’s a good (quick) way to parse up a large file otherwise? Would this go away if I were in AS Studio?

TIA
Jeff

Operating System: Mac OS X (10.3.9)

Hi, ByteJockey.

With regard to the code you’ve posted:

  1. The Finder has nothing to do with the file read/write commands, so you don’t need the ‘tell’ block.
  2. The ‘as list’ parameter of the ‘read’ command is the expression ‘as list’. The ‘list’ shouldn’t be bracketed and neither should the ‘return’.
  3. If you’re using a delimiter, you’re probably reading text ” in which case you should read the file ‘as text’ (or ‘as string’). The result will be a list anyway if a delimiter’s specified. The ‘as list’ parameter is properly used (without ‘using delimiter’ ) to read back an AppleScript list that has been written to file using the ‘write’ command. Lists have a special format in such files and the ‘as list’ parameter tells ‘read’ to interpret it as an AppleScript list rather than as text.
  4. If an operation on an open file fails, the script will error without closing the file unless you make arrangements to catch the error. This can cause problems on subsequent reads and is often a cause of puzzlement during the development of a script. The immediate cure is to quit the application running the script (say Script Editor), which closes the file(s).

If you want to read in an entire file that isn’t already open for access, you can simply write:

set PrimeTargetsRead to (read file (Path2Me as Unicode text & "PrimeTargets.txt") as text using delimiter return)

If you have enough memory, it’s faster simply to read in the entire file and then sort out the delimited sections:

set PrimeTargetsText to (read file (Path2Me as Unicode text & "PrimeTargets.txt") as text)
set PrimeTargetsRead to paragraphs of PrimeTargetsText

You’ll still get a stack overflow if you try to get more than about 4000 paragraphs at once, but it’s easy to peel off and deal with, say, 3900 at a time.

In fact, testing with a 10659-paragraph text file, I don’t get an error if I read it ‘using delimiter return’. Taking this in conjunction with your statement that the script mostly works, are you sure the problem’s occurring at the read stage?

Thanks Nigel.

As usual, your insights are truly pearls! My solution went much deeper than I understood at first. It appears that when I saved the script as an application bundle, the stack overflows when a delimiter is used on opening a big text file “ and NOT if it is saved as a plain script. My fix was to save the engine script as a plain script format and put a run handler in there to pass a couple of parameters. Then I made a shell script that passes a couple of startup parameters to the engine script and saved as an application bundle. Then I placed the engine script inside the Contents:Resources:Scripts folder inside the application bundle package, so it can travel inside and with the “app”. It’s kinda like AS Studio, but not quite - it just feels like it. But that’s what it took to work “ hacking of course.

So there is something about a Script Editor application bundle that is involved here. As one script, it won’t work if it’s saved as an application bundle. But as a called script, the same basic code will run without the dreaded “2706. I’d like to know what’s about. If you (or anybody else) have some in depth stuff on that, I’m all ears.

Jeff

I wonder if it’s the old global/property thing? “Top level” variables (ie. those that are set in the run handler) are treated like globals and properties, in that they and their values are saved back into the script file when the script quits. They then start out with those values the next time the script’s run.

If the value of such a variable is a very bulky item like a list of thousands of strings, that will cause problems when the script quits. (Sorry. I should have thought of it before.) You could try setting PrimeTargetsRead to something short like “” at the end of the script. Alternatively, you could make it a local variable ” either by declaring it as such before you first set it, or by putting the top level code into a regular handler:

local PrimeTargetsRead

set PrimeTargetsRead to (read file (Path2Me as Unicode text & "PrimeTargets.txt" ) as text using delimiter return )
-- etc.

-- Or:
doTheBusiness()

on dotheBusiness()
	set PrimeTargetsRead to (read file (Path2Me as Unicode text & "PrimeTargets.txt" ) as text using delimiter return )

	-- etc.
end dotheBusiness

Thanks again Nigel. I didn’t realize global variable data was saved back into the script file. I’ll surf this aspect more in depth.

Jeff