Adrian Nier Code

Back to overview

Write to file

Last modification: Friday, May 01, 2009 11:58 pm

Writes content to a file using AppleScript’s own ‘write’ command. Takes a single record as argument. Returns ‘true, if write was successful, raises an AppleScript error, if unsuccessful.

Required parameters
__hfsPath (string)
HFS style path to the file the content will be written to.

__content (string, list, etc.)
Content to write to the file.

Optional parameters
__overrideType (class)
Class name for the data type to write __content as [e.g. string, list, etc.].
 
__atomically (boolean)
Write atomically. First writes data to temporary file, then switches original file with temporary file. Default: false

__appending (boolean)
Append __content to current file contents. Default: false

__appendWithNewline (boolean)
Appends __content with a preceding new line character if the file was not empty. Ignored if __appending is set to false. Default: false

__creatorType (string)
Four character code for creator type.

__fileType (string)
Four character code for file type.

__silenceErrors (boolean)
Do not raise AppleScript errors, fail silently. Default: false

__logFilePath (string)
HFS style path to log file. Overrides gLOG_FILE_PATH. If only a file name is specified the default Logs folder inside the user’s Library is used. Default: false

__debugMode (boolean)
Log debug messages. Requires __logFilePath to be set. Overrides gDEBUG_MODE. Default: false

Optional Globals
gLOG_FILE_PATH (string)
If set, the value will be used for the path to the log file.

gDEBUG_MODE (boolean)
If set, the value will be used to enable debug messages.

gLAST_ERROR_MESSAGE (string)
Variable in which error message is stored.

gLAST_ERROR_NUMBER (integer)
Variable in which error number is stored.
 

Implementation

on writeToFile(_args)
   try
      set _functionName to "writeToFile"
      
      -- Find out if debug mode needs to be enabled
      try
         set _debugMode to (__debugMode of _args)
      on error
         try
            set _debugMode to gDEBUG
         on error
            set _debugMode to false
         end try
      end try
      
      -- Set the path to the log file
      try
         set _logFilePath to (__logFilePath of _args)
         if _logFilePath does not contain ":" then
            set _logFilePath to (path to home folder as string) & "Library:Logs:" & _logFilePath
         end if
      on error
         try
            set _logFilePath to gLOG_FILE_PATH
         on error
            set _logFilePath to false
         end try
      end try
      
      -- Debug message
      if _debugMode and (_logFilePath is not false) then do shell script "echo " & quoted form of ((do shell script "date +\"%F %T %Z\"") & tab & "[Debug] " & _functionName & "(): Checking arguments") & " >> " & quoted form of (POSIX path of _logFilePath) & " 2>/dev/null &"
      
      
      -- Check arguments
      try
         set _silenceErrors to (__silenceErrors of _args)
      on error
         set _silenceErrors to false
      end try
      
      try
         set _hfsPath to (__hfsPath of _args)
      on error
         set _hfsPath to ""
         error "No path to write to specified."
      end try
      
      if class of _hfsPath is not in {string, text, Unicode text, «class utf8»} then error "Wrong data type for path to write to."
      if _hfsPath is "" then error "Empty string for path to file to write to."
      if _hfsPath does not contain ":" then error "No valid path to write to specified."
      
      
      try
         set _content to (__content of _args)
      on error
         error "No content to write specified."
      end try
      
      try
         set _overrideType to (__overrideType of _args)
      on error
         set _overrideType to false
      end try
      
      if _overrideType is false then set _overrideType to class of _content
      
      try
         set _atomically to (__atomically of _args)
      on error
         set _atomically to false
      end try
      
      try
         set _appending to (__appending of _args)
      on error
         set _appending to false
      end try
      
      if _appending then
         try
            set _appendWithNewline to (__appendWithNewline of _args)
         on error
            set _appendWithNewline to false
         end try
      end if
      
      if _overrideType is list then set _appending to false
      
      try
         set _creatorType to (__creatorType of _args)
      on error
         set _creatorType to false
      end try
      
      try
         set _fileType to (__fileType of _args)
      on error
         set _fileType to false
      end try
      
      
      set _originalContent to "ANFileHadNoContent"
      
      if _atomically is false then
         
         set _writeToPath to _hfsPath
         
      else
         
         -- Debug message
         if _debugMode and (_logFilePath is not false) then do shell script "echo " & quoted form of ((do shell script "date +\"%F %T %Z\"") & tab & "[Debug] " & _functionName & "(\"" & _hfsPath & "\"): Determining file name and directory") & " >> " & quoted form of (POSIX path of _logFilePath) & " 2>/dev/null &"
         
         -- Determine file name and directory
         -- Create file path for atomical writing  
         set _pDlmt to AppleScript's text item delimiters
         try
            set AppleScript's text item delimiters to ":"
            set _fileName to text item -1 of _hfsPath
            set _fileDirectory to text items 1 thru -2 of _hfsPath as string
            set AppleScript's text item delimiters to ""
            set _writeToPath to (_fileDirectory & ":" & (random number from 100000 to 999999) & _fileName) as string
            set AppleScript's text item delimiters to _pDlmt
         on error _eMessage number _eNumber
            set AppleScript's text item delimiters to _pDlmt
            error "Error while determining file name and directory: " & _eMessage number _eNumber
         end try
         
         
         
         -- Read original file content if necessary
         if _appending then
            
            try
               tell application "System Events"
                  if (exists file _hfsPath) is false then error 1
               end tell
               set fileExists to true
            on error
               set fileExists to false
            end try
            
            if fileExists then
               -- Debug message
               if _debugMode and (_logFilePath is not false) then do shell script "echo " & quoted form of ((do shell script "date +\"%F %T %Z\"") & tab & "[Debug] " & _functionName & "(\"" & _hfsPath & "\"): Reading current content") & " >> " & quoted form of (POSIX path of _logFilePath) & " 2>/dev/null &"
               
               try
                  open for access file _hfsPath
               on error _eMessage number _eNumber
                  error "Could not open file for reading: " & _eMessage number _eNumber
               end try
               
               try
                  set _originalContent to read file _hfsPath as _overrideType
               on error _eMessage number _eNumber
                  try
                     close access file _hfsPath
                  end try
                  error "Could not read original file: " & _eMessage number _eNumber
               end try
               
               try
                  close access file _hfsPath
               end try
               
               if _debugMode and (_logFilePath is not false) then do shell script "echo " & quoted form of ((do shell script "date +\"%F %T %Z\"") & tab & "[Debug] " & _functionName & "(\"" & _hfsPath & "\"): Current content: " & ((count of characters of _originalContent) as string) & " characters") & " >> " & quoted form of (POSIX path of _logFilePath) & " 2>/dev/null &"
               
            end if -- fileExists
         end if -- _appending
      end if -- _atomically is false
      
      
      -- Debug message
      if _debugMode and (_logFilePath is not false) then do shell script "echo " & quoted form of ((do shell script "date +\"%F %T %Z\"") & tab & "[Debug] " & _functionName & "(\"" & _hfsPath & "\"): Opening file with write permission") & " >> " & quoted form of (POSIX path of _logFilePath) & " 2>/dev/null &"
      
      -- Open file to write to
      try
         open for access file _writeToPath with write permission
      on error _eMessage number _eNumber
         error "Could not open file with write permission: " & _eMessage number _eNumber
      end try
      
      -- Write to file 
      try
         -- Debug message
         if _debugMode and (_logFilePath is not false) then do shell script "echo " & quoted form of ((do shell script "date +\"%F %T %Z\"") & tab & "[Debug] " & _functionName & "(\"" & _hfsPath & "\"): Writing to file") & " >> " & quoted form of (POSIX path of _logFilePath) & " 2>/dev/null &"
         
         -- Determine end of file and data to write
         if _appending is false then
            
            set eof of file _writeToPath to 0
            set _fileEnd to 0
            set _writeData to _content
            
         else
            try
               set _fileEnd to (get eof of file _writeToPath) + 1
            on error
               set _fileEnd to 0
            end try
            
            if _originalContent is not "ANFileHadNoContent" then
               if _appendWithNewline then
                  set _writeData to _originalContent & return & _content
               else
                  set _writeData to _originalContent & _content
               end if
            else
               if _fileEnd > 1 then
                  if _appendWithNewline then
                     set _writeData to return & _content
                  else
                     set _writeData to _content
                  end if
               else
                  set _writeData to _content
               end if
            end if
            
         end if
         
         if _debugMode and (_logFilePath is not false) then do shell script "echo " & quoted form of ((do shell script "date +\"%F %T %Z\"") & tab & "[Debug] " & _functionName & "(\"" & _hfsPath & "\"): Content to write: " & ((count of characters of _writeData) as string) & " characters") & " >> " & quoted form of (POSIX path of _logFilePath) & " 2>/dev/null &"
         
         write _writeData to file _writeToPath starting at _fileEnd as _overrideType
         
      on error _eMessage number _eNumber
         try
            close access file _writeToPath
         end try
         error "Error while writing to file: " & _eMessage number _eNumber
      end try
      
      -- Debug message
      if _debugMode and (_logFilePath is not false) then do shell script "echo " & quoted form of ((do shell script "date +\"%F %T %Z\"") & tab & "[Debug] " & _functionName & "(\"" & _hfsPath & "\"): Closing file") & " >> " & quoted form of (POSIX path of _logFilePath) & " 2>/dev/null &"
      
      try
         close access file _writeToPath
      end try
      
      
      -- Option: Atomically - Delete original file and rename backup file
      
      if _writeToPath is not _hfsPath then
         
         -- Debug message
         if _debugMode and (_logFilePath is not false) then do shell script "echo " & quoted form of ((do shell script "date +\"%F %T %Z\"") & tab & "[Debug] " & _functionName & "(\"" & _hfsPath & "\"): Replacing original file with file written to") & " >> " & quoted form of (POSIX path of _logFilePath) & " 2>/dev/null &"
         
         -- Try to delete the original file if it exists
         try
            tell application "System Events"
               if (exists file _hfsPath) then
                  do shell script "rm -f " & quoted form of (POSIX path of _hfsPath)
               end if
            end tell
         end try
         
         -- Rename backup file
         try
            do shell script "mv " & quoted form of (POSIX path of _writeToPath) & " " & quoted form of (POSIX path of _hfsPath)
         on error _eMessage number _eNumber
            error "Error wile renaming backup file: " & _eMessage number _eNumber
         end try
      end if
      
      if _creatorType is not false and _fileType is not false then
         -- Debug message
         if _debugMode and (_logFilePath is not false) then do shell script "echo " & quoted form of ((do shell script "date +\"%F %T %Z\"") & tab & "[Debug] " & _functionName & "(\"" & _hfsPath & "\"): Setting creator or type") & " >> " & quoted form of (POSIX path of _logFilePath) & " 2>/dev/null &"
      end if
      
      try
         if _creatorType is not false then
            tell application "System Events" to set creator type of file _hfsPath to _creatorType
         end if
      end try
      try
         if _fileType is not false then
            tell application "System Events" to set file type of file _hfsPath to _fileType
         end if
      end try
      
      return true
      
   on error _eMessage number _eNumber
      
      set gLAST_ERROR_MESSAGE to _eMessage
      set gLAST_ERROR_NUMBER to _eNumber
      
      try
         if _writeToPath is not _hfsPath then
            tell application "System Events" to delete file _writeToPath
         end if
      end try
      
      -- Log to file if a path has been specified
      if _logFilePath is not false then
         try
            set _logMessage to "[Error] " & _functionName & "(\"" & _hfsPath & "\"): " & _eMessage & " (" & (_eNumber as string) & ")"
            do shell script "echo " & quoted form of ((do shell script "date +\"%F %T %Z\"") & tab & _logMessage) & " >> " & quoted form of (POSIX path of _logFilePath) & " 2>/dev/null &"
         end try
      end if
      
      -- Raise an error if silencing errors is disabled
      if (_silenceErrors is false) then
         set _eMessage to _functionName & "(\"" & _hfsPath & "\"): " & _eMessage & " (" & (_eNumber as string) & ")"
         error _eMessage number _eNumber
      end if
      
      return false
   end try
   
   
end writeToFile