my applescript to edit PS files works, but only for files up to 10 megs. anything over that, and a log file is created saying -108 OUT OF MEMORY. I did File → Get Info → Memory on the applescript droplet and maxed out it’s memory availability (as well, i maxed out the computer’s virtual memory capacity) yet it still won’t work. my script only looks for a line of text within the first 100 lines of each file, so I figure maybe there’s a way to get it to only edit the first portion of each file? As well, does this memory problem have anything to do with SimpleText (I maxed out it’s memory availability, too)?
btw, I have a 1.25GHZ Accelerated G4 with 256K RAM…didn’t figure I’d even have this problem.
I’ve never messed with reading and writing specific parts of files so I hope someone else offers a solution. In the meantime, if you can provide more info, I’ll likely experiment to see what I can come up with (a few sample files would be welcome - you can send them to robj@woh.rr.com or provide download links). For those who might be able to help, the script in question can be found in this thread.
Are the files fairly consistent within the first 100 lines? If so, do you have a guess as to how many bytes are contained in the first 100 lines of the average file?
I doubt that SimpleText is causing problems since it isn’t involved in the script (as far as I know).
Originally I though you could just read the first x bytes in, search and replace, then write that text back tot he file starting at 0 but the problem is that your new text is 1 character longer than the original text so this doesn’t work. So, here’s my next stab at it. Read the text in two chunks. Do your search and replace on the first, small chunk (since I think this is where you are having memory issues converting to lists & back to strings on such huge amounts of text), then write the whole thing back to the file. I also added a mechanism to have several search and replace routines if necessary. Hope this helps.
property search_strings : {"ORIGINX 0"} --add to these lists if there are more things to search & replace
property replace_strings : {"ORIGINX 32"}
property maximum_chunk : 512 -- this will read the first 512 characters of the file, if you need more, adjust as necessary.
on run
open {choose file of type {"TEXT"}}
end run
on open the_files
repeat with this_file in the_files
try
set the_content_start to read this_file from 1 to maximum_chunk
set the_content_end to read this_file from (maximum_chunk + 1) to -1
repeat with i from 1 to (count of search_strings)
set the_content_start to my replace_chars(the_content_start, (item i of search_strings), (item i of replace_strings))
end repeat
my write_to_file((the_content_start & the_content_end), this_file, false)
on error error_message number error_number
set error_string to "Error: " & error_number & ". " & error_message
activate
beep 3
set the_button to button returned of (display dialog error_string buttons {"Copy to Clipboard", "OK"} default button 1 with icon 0)
if the_button = "Copy to Clipboard" then set the clipboard to error_string
return
end try
end repeat
activate
beep
display dialog "The operation is complete." buttons {"OK"} default button 1 with icon 1
end open
to replace_chars(this_text, search_string, replacement_string)
set old_atid to AppleScript's text item delimiters
set AppleScript's text item delimiters to search_string
set this_text to text items of this_text
set AppleScript's text item delimiters to replacement_string
set this_text to this_text as string
set AppleScript's text item delimiters to old_atid
return this_text
end replace_chars
to write_to_file(this_data, target_file, with_appending)
try
set target_file to target_file as text
set open_target_file to open for access file target_file with write permission
if with_appending = false then set eof of open_target_file to 0
write this_data to open_target_file starting at eof
close access open_target_file
return true
on error
try
close access file target_file
end try
return false
end try
end write_to_file
Yep, that extra character is giving me fits, Jon. I don’t know if this will actually make a difference but here’s my attempt at reducing the script’s overhead. I’m working on a wild assumption so it may not help at all.
on open files_
repeat with file_ in files_
try
my write_to_file(my replace_chars(read file_, "ORIGINX 0", "ORIGINX 32"), file_, false)
on error error_message number error_number
set this_error to "Error: " & error_number & ". " & ¬
error_message & return
set the log_file to ((path to desktop) as text) & "Script Error Log"
my write_to_file(this_error, log_file, true)
activate
beep 3
display dialog "An error report (Script Error Log) has been placed on the desktop." buttons ¬
{"OK"} default button 1 with icon 0
end try
end repeat
activate
display dialog "The operation is complete." buttons ¬
{"OK"} default button 1 with icon 1
end open
to replace_chars(this_text, search_string, replacement_string)
set AppleScript's text item delimiters to the search_string
set the item_list to every text item of this_text
set AppleScript's text item delimiters to the replacement_string
set this_text to the item_list as string
set AppleScript's text item delimiters to ""
return this_text
end replace_chars
to write_to_file(this_data, target_file, append_data)
try
set the target_file to the target_file as text
set the open_target_file to ¬
open for access file target_file with write permission
if append_data is false then ¬
set eof of the open_target_file to 0
write this_data to the open_target_file starting at eof
close access the open_target_file
return true
on error
try
close access file target_file
end try
return false
end try
end write_to_file
neither of the scripts worked…they both said “out of memory”.
i really only have to edit the first 50 or 60 lines of text for the file, so possibly jon’s script (without the repeat) would work? i’ve been trying to turn the repeat off in that script, but can’t figure it out (i’m a newbie). jon, would you be able to make it so that there’s no repeat, and the script only looks to edit the first 50 or 60 lines of each file?
The second repeat in my script won’t add any overhead to the script, so don’t worry about, really. I have one last method to suggest but it’s ugly. If you were reading in a chunk from the beginning of a file and then doing a search and replace and the new text was less than or equal to the original chunk, you could just pad the beginning of new chunk with spaces so it was the same length as the original and then overwrite that new chunk to the beginning of the original file. Since this is not applicable (the new chunk turns out to be longer than the original), and reading most of the file into memory is causing problems, we have to be more creative. The solution is to read the original file completely in chunks, search and replace the chunks, and then write each chunk to the end of a new file until the original has been completely read, searched & replaced, and reconstructed. Here’s my code for this. It will rename the original file then rebuild it so you’ll be left with the original (“original_o.ext”) and the new file. Please let me know if this works (there’s probably a better way of doing this):
I ran your latest script on a 20 MB test file and it produced the desired result where the previous scripts failed. Here are some stats regarding the test.
Computer: PowerBook G4 667, 512 MB RAM
Chunk Size: 1024
Time to complete: approximately 7 minutes
Success!
Ryan,
On the renaming issue, if you were running OS X, I’d urge you to consider Jon’s Name those Files!, a powerful file renaming utility for a reasonable price. Jon is a master when it comes to renaming files and he’s a heck of a developer in general!
hey guys,
the script works (i just didn’t cut and paste properly the first time)…
everything is fine, even for very large files. the only problem is that it takes forever with a huge group of files. since i know that the line that i have to change in every file exists within the first 100 lines of text of each file, is there a way for the script to only examine the first part of each file?