set thisFile to open for access aFilePath with write permission
write stuff to thisFile
-- do other stuff
close access thisFile I have no problems with this script, as long as “do other stuff” runs and “close access” is hit. BUT:
2. If there’s an error in “do other stuff” and “close access” is not hit, I end up with a worthless file, that pops an " . already open error" if I try to open it again.
3. So I try to close it:
set thisFile to file aFilePath
close access thisFile
and I get an error on the second line " … can’t make . [thisFile] . type file". If “thisFile” is a file on the line above, why is it no longer on the second?
4. I trash the file and same thing, the system remembers the file name and has flagged it as open (apparently). Ghost file.
Brief: I cannot close the file except as in 1 above, not afterwards. If 1 doesn’t run, I cannot use that file name again.
Question: How can I close or delete this file or tell the system it doesn’t exist?
standard procedure assuming aFilePath is a HFS path (colon separated)
try
set fileDescriptor to open for access file aFilePath with write permission
write stuff to fileDescriptor
-- do other stuff
close access fileDescriptor
on error
try
close access file aFilePath
end try
end try
What you might want to check is if the file was already opened. When you rerun the program if the file was already open then you’ll get errors and it needs to be closed.
StefanK’s example is indeed the standard procedure. But here some explanations to make it clear what happens.
First of all you open a file with write permission. The difference is that write permission can be opened once in the entire operating system while read permission can be opened as many times as you want. When opening a file with write permission you have to be more careful because leaving a file opened with write permission causes the file to not being editable.
Secondly AppleScript is not opening the file because it can’t, it’s handled by a scripting addition which lets the fileaccess commands be handled by the application running your script. When you quit an application, all opened files are automatically closed. But the problem is that when an AppleScript is finished, the application running your script doesn’t have to be closed at all (like script editor). That means that when you don’t properly close a file with write permission nobody can open that file with write permission afterwards (including removing it from your file system). File access commands are limited to current application you need to quit the application running your script when it keeps a file with write permission opened.
Again, you can avoid all these problems by using StefanK’s example code.
Thanks for the reply. Part of what I was asking is that if the file is gone and trashed, what does it mean to say the file is open, as the system apparently did.
Anyway, they’re behaving now but I’d sure like to understand what happened and why
set thisFile to file aFilePath
close access thisFile
wouldn’t work for me.
I got a “can’t make … [thisFile] … into type file” error on the second line, not the first. How can AS pass through the first line if “thisFile” is not a valid path? And why does it fail on line two?
I thought it was fixed, but now it’s doing the same thing again.
I pasted in Stefan’s code just in case I mistyped or something, and it no longer works.
New file, wrote to it once before OK., but now after error before closing the file, I get the “already open” error no matter what I do using my code or Stephan’s. Trashed the file - still same thing. This is getting weird.
OK., it works … Never noticed Finder do this before …
When I rewrote a text file before, I could see the update immediately in the file preview. This time however, that did not happen until I backed out of the folder, came back to it, and then the file preview showed the update. And it continues to update each time.
Not that it’s extremely important, but does anyone know why that happened?
I have seen this in the past. i.e. where you trash a file that was opened with ‘open for access’. Can’t remember what was the way to close it, but there was an easy trick to it. Let me think about it.
Use a handler to write to files - one that has a proper error-handler.
------------------------------------------------------------------------------------
--» writeFile()
------------------------------------------------------------------------------------
-- Task: Write to a file as a specific data-type.
-- dMod: 2012/10/26 20:00
------------------------------------------------------------------------------------
on writeFile(srcData, targetFile, startPosition, dataType)
try
set fileRef to open for access targetFile with write permission
if startPosition = 0 then
set eof of fileRef to 0
end if
write srcData to fileRef as dataType starting at startPosition
close access fileRef
on error errMsg number errNum
try
close access fileRef
end try
error "Error in handler: writeFile of library: gen.lib" & return & return & errMsg
end try
end writeFile
------------------------------------------------------------------------------------
--» writeUTF8()
------------------------------------------------------------------------------------
-- Task: Write text to a file and overwrite any content.
-- dMod: 2012/10/26 20:00
------------------------------------------------------------------------------------
on writeUTF8(_text, _file)
try
if _file starts with "~/" then
set _file to POSIX path of (path to home folder as text) & text 3 thru -1 of _file
end if
set fRef to open for access _file with write permission
set eof of fRef to 0
write _text to fRef as «class utf8»
close access fRef
on error e number n
try
close access fRef
on error e number n
error "Error in writeUTF8() handler!" & return & return & e
end try
end try
end writeUTF8
------------------------------------------------------------------------------------
Yes, as everyone has written, It’s better to write safe code. The thing is, sometimes you get into these situations and don’t know how to exit from it and the best way to do it as DJ wrote is to quit the app. If you are ever stuck, then force quit the app.
Man, I was sure there was a way to close the file by AppleScript. Still thinking about that.
BTW, this is an old problem when using the read/write scripting addition.
I think I was writing an example script by hand (no libs) for someone who preferred posix paths, and I had forgotten the exact syntax for write. So I looked it up in Script Debugger and saw the reference for to:
to required any the file reference number, alias, or file reference of the file to write to
File Reference caught my eye, and it occurred to me that I hadn’t tested in many years what formats it would tolerate ” so I made the example script into a test routine.
set testFldr to ((path to home folder as text) & "test_directory:TEST_FOLDER:")
try
alias testFldr
on error
do shell script "mkdir -p " & quoted form of (POSIX path of testFldr)
delay 0.1
end try
do shell script "open " & quoted form of (POSIX path of testFldr)
delay 1
set testHFSPath to testFldr & "test_file_1.txt"
set testPosixPath to (POSIX path of testFldr) & "test_file_2.txt"
set testPosixHomePath to "~/test_directory/TEST_FOLDER/test_file_3.txt"
set testPosixFile to POSIX file (POSIX path of testFldr & "test_file_4.txt")
writeMe("Test_File_01_HFS_Path", testHFSPath)
delay 0.2
writeMe("Test_File_02_Posix_Path", testPosixPath)
delay 0.2
writeMe("Test_File_03_Posix_Home_Path", testPosixHomePath)
delay 0.2
writeMe("Test_File_04_Posix_File", testPosixFile)
on writeMe(_text, _file)
try
set fileHandle to open for access _file with write permission
write _text to fileHandle as «class utf8»
close access fileHandle
on error e
try
close access fileHandle
end try
e
"" --» Stub for break-point in Script Debugger
end try
end writeMe
I was delighted to find out that Posix Paths were supported and disappointed that home-based-Posix-Paths were not, but the latter was an easy fix.
Well you shouldn’t close the file by reference Chris and should use StefanK’s example as I have mentioned earlier. If opening the file causes an error no file descriptor will be returned. So the rule is that In the error block you always close the file by using it’s path, never by it’s descriptor.
The AE framework did get some new features a few OS X versions back. As an scripting addition writer myself I don’t need to take posix files into consideration, the AE framework does that for me. It’s therefore not really a open for access feature but for many different commands as long as it allows implicit coercions. So when I want an AppleEvent descriptor as fileTypeUrl the AE framework will try to coerce the given argument if it’s of class string containing a POSIX or a HFS path. So you’re maybe glad to hear that it’s not only open for access that supports POSIX paths but a lot of more commands like deprecated info for and deprecated list folder
It is good to still learn something new, especially how file reference can be interpreted.
@ DJ Bazzie Wazzie: Thanks for the info, It is also nice to have learned that the correct way of trying to closing a file is to use its full path. Kudos to Stefan for bringing that onto the table. (It covers most cases, and is probably most convenient when you edit the code, espcecially when you are in an editor, that doesn’t take care of leaked file handles, or reference numbers. I see an advantage of writing code, so others can play with it, without being shot in the back, by suddenly having a file they can’t open.
By the way: I can’t see that list folder is deprecated.