Tips   >   Functions   >   FileOps

FileOps

FileOps

stands for File Operations.

In Omnis Studio you can do file operations using the FileOps functions or the FileOps external.

The FileOps external is use for reading and writing file contents. For information on the FileOps External section listed under the Externals subject.

This section provided explanations and demos of the various FileOps functions.

To view all of the FileOps functions:

  1. Press F9 to open the Catalog.
  2. Click the Functions tab.
  3. Click FileOps in column one. All of the FileOps functions are displayed in column two.

    If you hover or one of the FileOps functions a tooltip tip appears providing you with the syntax and a short description of the function.
Tip

You can drag and drop any of the functions into your code. Omnis Studio conveniently copies the function and parameter names into your code.

Many of the FileOps functions require FileOps contants values (e.g. kFileOpsInclFiles, kFileOpsInfoFullName).

To find the FileOps constants:

  1. Press F9 to open the Catalog.
  2. Click the Constants tab.
  3. Click FileOps in column one. A list of the available FileOps constants will be displayed in column 2.
Tip

If your are entering code in the code editor, you can drag and drop or double-click on any of the constants in the F9 Catalog. Omnis Studio will copy the constant to your code.

Error Codes

A number of the FileOps functions return an error code. If the error code is a non-zero value, an error has occurred.

Omnis Studio provides a list of the possible FileOps error codes in the F1 Help. For example:

However, Omnis Studio does not provide a way to get the error code text from within Omnis Studio.

I created a $retFileOpsErrorText method which returns the error text for each of the known FileOps error codes. The method code is as follows:

; $retFileOpsErrorCodeText method.

Switch pErrorCode
   Case kFileOpsOK ;; 0
      Quit method '' ;; No Error
   Case kFileOpsNoOperation ;; 999
      Quit method 'Operation not supported on this platform'
   Case kFileOpsUnknownError ;; 998
      Quit method 'Unknown error'
   Case kFileOpsOutOfMemory ;; 12
      Quit method 'Out of memory'
   Case kFileOpsParamError ;; 1
      Quit method 'Too few parameters passed'
   Case kFileOpsDirFull ;; -33
      Quit method 'File/Directory full'
   Case kFileOpsDiskFull ;; -34
      Quit method 'Disk full'
   Case kFileOpsVolumeNotFound ;; -35
      Quit method "Specified volume doesn't exist"
   Case kFileOpsDiskIOError ;; -36
      Quit method 'Disk I/O error'
   Case kFileOpsBadName ;; -37
      Quit method "Bad file name or volume name (perhaps zero-length)"
   Case kFileOpsFileNotOpen ;; -38
      Quit method "File not open"
   Case kFileOpsEndOfFile ;; -39
      Quit method "Logical end-of-file reached during read operation"
   Case kFileOpsPositionBeforeStart ;; -40
      Quit method "Attempt to position before the start of the file"
   Case kFileOpsTooManyFilesOpen ;; -42
      Quit method "Too many files open"
   Case kFileOpsFileNotFound ;; -43
      Quit method "File not found"
   Case kFileOpsHardwareVolumeLock ;; -44
      Quit method "Volume is locked by a hardware setting"
   Case kFileOpsFileLocked ;; -45
      Quit method "File is locked"
   Case kFileOpsSoftwareVolumeLock ;; -46
      Quit method "Volume is locked by a software flag"
   Case kFileOpsMoreFilesOpen ;; -47
      Quit method "One or more files are open"
   Case kFileOpsAlreadyExists ;; -48
      Quit method "A file with the specified name already exists"
   Case kFileOpsAlreadyWriteOpen ;; -49
      Quit method "Only one access path a file can allow writing"
   Case kFileOpsNoDefaultVolume ;; -50
      Quit method "No default volume"
   Case kFileOpsVolumeNotOnline ;; -53
      Quit method "Volume not on-line"
   Case kFileOpsPermissionDenied ;; -54
      Quit method "Permission denied"
   Case kFileOpsReadOnlyFile ;; -54? Error in F1 Help documentation?
      Quit method "Read only file"
   Case kFileOpsVolumeAlreadyMounted ;; -55
      Quit method "Specified volume is already mounted and on-line"
   Case kFileOpsBadDrive ;; -56
      Quit method "No such drive number"
   Case kFileOpsInvalidFormat ;; -57
      Quit method "Volume lacks Macintosh-format directory"
   Case kFileOpsExternalSystemError ;; -58
      Quit method "External file system error"
   Case kFileOpsProblemDuringRename ;; -59
      Quit method "Problem during rename"
   Case kFileOpsBadMasterBlock ;; -60
      Quit method "Master directory block is bad; must re-initialize volume"
   Case kFileOpsCantOpenLockedFile ;; -61
      Quit method "Cannot open a locked file"
   Case kFileOpsDirectoryNotFound ;; -120
      Quit method "Directory not found"
   Case kFileOpsTooManyDirOpen ;; -121
      Quit method "Too many working directories open"
   Case kFileOpsCantMoveToOffspring ;; -122
      Quit method "Attempted to move into offspring"
   Case kFileOpsNonHFSOperation ;; -123
      Quit method "Attempt to do HFS operation on a non-HFS volume"
   Case kFileOpsInternalSystemError ;; -127
      Quit method "Internal file system error"
   Default
      Quit method con("Undocumented FileOps error code ",pErrorCode)
End Switch

In StudioTips I have copied the above code to the oFunctions object which is instantiated using the task variable, fn, of the Startup_Task. I can then call the method from anywhere in my code as follows:

; Get the error text for the error code from oFunctions.
Do fn.$retFileOpsErrorText(ErrorCode) Returns ErrorText

You may want to do something similar in your own application. Instead of prompting the user with an error message that says "File operations error -48 occurred", you can provide a more informative prompt like, "File Operations error. A file with the specified name already exists.".

Platform Sensitive Path Delimiter

sys(9)

returns the platform sensitive path delimiter.

Use sys(9) where applicable can help make your FileOps code platform independent.

; Calculate the file path name.
Calculate Path as con('DriveName',sys(9),'FolderName',sys(9),'FileName','.txt')

Uppercase File Paths

The Windows platform really used uppercase file paths. You need to be aware of this when writing any file operations related methods.

Using the replace() function on a file name, file path, or folder path is not a good idea.

The following line of code might work on the Mac and Linux platforms, but it will likely fail on the Windows platform.

Calculate NewPath as replace(OldPath,"Modules","Libraries")

One work around for Windows is to include the upp() or low() function... but then the NewPath which you calculate might not work for the Linux platform which is case-sensitive with respect to file paths.

In the above example a better way to replace "Modules" with "Libaries" in the OldPath is to find the position of the text in the path, and then replace the "Modules" with "Libraries" using the mid() function.

$changeworkingdir

Change Working Directory

Do FileOps.$changeworkingdir(Path) Returns ErrorCode

Changes the current working directory to the directory specified by Path. $changeworkingdir() only switches between folders on the same drive, not between drives.

The function returns an error number, or zero if successful.

Warning

Applications on Mac OS X do not have a working directory. If you use this function on Mac OS X, it returns the error code kFileOpsNoOperation ('999').

$converthsfpathtoposix

Do FileOps.$converthfspathtoposixpath(HfsPath,PosixPath)

Converts an HFS file path to a unix file path. The function returns an error number, or zero if successful.

$convertposixpathtohfs

Do FileOps.$convertposixpathtohfspath(PosixPath,HfsPath)

Converts unix file path to an HFS file path. The function returns an error number, or zero if successful.

$copyfile

Do FileOps.$copyfile(PathFrom,PathTo) Returns ErrorCode

Copies the file specified in PathFrom to the new location in PathTo

You can use this function to copy and rename the specified file to the same folder or a different location. The file named in PathTo should not already exist.

The function returns an error number, or zero if successful.

$createdir

Do FileOps.$createdir(Path) Returns ErrorCode

Creates the folder specified in path. The folder named in path must not already exist. The function returns an error number, or zero if successful.

$createdir() does not create intervening folders, it only creates the last folder named in path, therefore the intervening folders should already exist.

The following sample code can be used to automatically create intervening folders for a specified path.

; Calculate a path to a new preferences/studiotips folder inside the Omnis folder.
Calculate Path as sys(115)
Calculate Path as con(Path,'preferences',sys(9),'studiotips',sys(9))

; Split the path and then loop through the folders path checking each directory.
Do FileOps.$splitpathname(Path,Drive,FoldersPath,FileName,Ext) Returns ErrorCode

; Loop through the folders path checking to make sure each directory exists.
Calculate CheckPath as Drive
Calculate FoldersPath as trim(FoldersPath,kTrue,kTrue,sys(9))
Calculate ErrorCode as 0 ;; Preset to zero.
While len(FoldersPath)
   
   Calculate NextDir as strtok('FoldersPath',sys(9))
   Calculate CheckPath as con(CheckPath,sys(9),NextDir)
   
   ; Does the directory exists?
   If not(FileOps.$doesfileexist(CheckPath))
      
      ; Create the intervening directory.
      Do FileOps.$createdir(CheckPath) Returns ErrorCode
      If ErrorCode
         Break to end of loop
      End If
      
   End If
End While
If ErrorCode
   OK message (Icon) {The error code [ErrorCode] occurred when attempting to create the following directory:////[CheckPath]}
End If

$deletefile

Do FileOps.$deletefile(Path) Returns ErrorCode

Deletes the file or folder named in path. Files deleted are not moved into the Recycled bin or Trash can, they are deleted irreversibly. You can delete a folder with $deletefile(), but only if the directory is empty.

The function returns an error number, or zero if successful.

See the topic deleteDirectory in this section for code which drills down and deletes all the files and subdirectories of a directory and then delete the directory.

$doesfileexist

Does File or Directory Exist

Do FileOps.$doesfileexist(Path) Returns bFileExists

Returns true if the file or folder named in path exists.

$filelist

File List

Do FileOps.$filelist(kFileOpsInclConstants,TargetPath[,kFileOpsInfoConstants]) Returns List

Returns a list of files and/or directories inside the specified target path.

The kFileOpsInclConstants begin with kFileOpsIncl...

The kFileOpsInfoConstants begin with kFileOpsInfo...

; Get a list of the files in the target directory.
Do FileOps.$filelist(kFileOpsIncludeFiles,TargetPath) Returns List

; Get list of the files in the target directory. Include the date created & size.
Do FileOps.$filelist(kFileOpsIncludeFiles,TargetPath,kFileOpsInfoCreated+kFileOpsInfoSize) Returns List

; Get a list of the folders in the target directory.
Do FileOps.$filelist(kFileOpsIncludeDirectories,TargetPath) Returns List

; Get a list of the files and directories in the directory specified by Path
Do FileOps.$filelist(kFileOpsIncludeFiles+kFileOpsIncludeDirectories,TargetPath) Returns List

; Get a list of the volumes (drives) on the startup drive by Path
Do FileOps.$filelist(kFileOpsIncludeVolumes,TargetPath) Returns List

$getfileinfo

Get File Info

FileOps.$getfileinfo(Path,kFileInfoConstants) Returns FileInfoList

The kFileOpsInfoConstants begin with kFileOpsInfo...

Do FileOps.$getfileinfo(Path,kFileOpsInfoName+kFileOpsInfoCreated+kFileOpsInfoSize) Returns List

$getfilename

Get File Name

FileOps.$getfilename(Path[,Prompt,Filter,InitialDirectory]) Returns bFileSelected

Prompts the user to select a file and sets the Path variable to the selected file path. Returns true if the user selected a file.

The following sample code is used for the demo for this tip.

Calculate Title as 'Select an Omnis Studio library'
Calculate Filter as 'Omnis Studio (*.lbs)|*.lbs'

; $getfilename(Path[,Prompt,Filter,InitialDirectory])
Do FileOps.$getfilename(Path,Title,Filter) Returns bFileSelected
If bFileSelected
   OK message (Icon) {The path to the file you selected is:////[Path]}
Else
   OK message (Icon) {No file was selected.}
End If

Quit method kTrue

You can have multiple filters. The filter consists of a pipe delimited string.

Calculate Title as 'Select an xlv, txt, or csv file'
Calculate Filter as 'Excel (*.xlv)|*.xlv|Text (*.txt)|*.txt|CSV (*.csv)|*.csv'

; $getfilename(Path[,Prompt,Filter,InitialDirectory])
Do FileOps.$getfilename(Path,Title,Filter) Returns bFileSelected
If bFileSelected
   OK message (Icon) {The path to the file you selected is:////[Path]}
Else
   OK message (Icon) {No file was selected.}
End If

Quit method kTrue

$getunixpermissions

Do FileOps.$getunixpermissions(Path) Returns Path

Returns the Unix permissions string for the file identified by the specified path.

$getworkingdir

Get Working Directory

Do FileOps.$getworkingdir() Returns Path

Returns the current working directory.

Warning

Applications on Mac OS X do not have a working directory. If you use this function on Mac OS X, it returns an empty path.

$movefile

Move File

Do FileOps.$movefile(PathFrom,PathTo) Returns ErrorCode

Moves the file specified at PathFrom to the new location at PathTo. The file named in PathTo should not already exist. The function returns an error number, or zero if successful

You can use this function to move and rename the specified file.

$parentdir

Parent Directory

Do FileOps.$parentdir(Path) Returns ParentDirPath

Returns the path to the parent directory of the specified file path or folder path.

$putfilename

Put File Name

FileOps.$putfilename(Path[,PromptTitle,Filter,InitialPath]) Returns bFileSpecified

Opens the Save dialog with the specified file name and the file name as the value of Path.

If the user clicks Save, FileOps calculates Path as the full path including the file name and extension as entered by the user, and returns true. If the user clicks Cancel false is returned.

The following sample code is used for the demo for this tip.

Calculate Title as 'Save file as'
Calculate Path as 'FileOpsDemo.txt'
Do FileOps.$putfilename(Path,Title) Returns bFileSpecified
If bFileSpecified
   OK message (Icon) {You specified to save a file at:////[Path]}
Else
   OK message (Icon) {You did not specify a file path.}
End If

Tip

The prompt window defaults the Save As entry field to the value of Path so if you want to suggest a file name and extension to the user, calculate the file name and extension to Path before the $putfilename.

$readentirefile

Do FileOps.$readentirefile(Path,BinVar) Returns ErrorCode

Reads the entire file identified by path into the binary variable. The function returns an error code, or zero if successful.

When called on Mac OS, the data read into variable includes the Mac OS resource fork and file type information. On return, the value in variable has the following format:

  1. 12 byte header containing the Type (4 bytes), Creator (4 bytes), and Data fork size (4 bytes).
  2. Data fork information.
  3. Resource fork information.

The size of the data fork determines where the resource fork data is stored.

Under Windows and Unix, the Type defaults to ÔTEXTÕ, the Creator to ÔmdosÕ, and the resource fork is empty.

$rename

Rename File or Directory

Do FileOps.$rename(OldPath,NewPath) Returns ErrorCode

Renames the file or directory specified by the paths. The function returns an error number, zero if successful.

$selectdirectory

Select Directory

Do FileOps.$selectdirectory(Path[,Title,InitialDirectory]) Returns bDirSelected

Opens the select directory dialog with the specified title. Returns true and calculates Path as the full path of the directory selcted by the user. Returns false if the user click the Cancel button.

The following sample code is used for the demo for this tip.

Calculate Title as 'Select a folder'
Do FileOps.$selectdirectory(Path,Title) Returns bDirSelected
If bDirSelected
   OK message (Icon) {Path to the directly selected is:////[Path]}
Else
   OK message (Icon) {Directory not selected.}
End If
Quit method kTrue

$setfileinfo

Set File Info

Do FileOps.$setfileinfo(FilePath,kFileInfoConstant,Value,...) Returns ErrorCode

Sets the file info for the specified file and kFileInfo... constant to the specified value. You can include a series of constants and values.

Not all kFileOpsInfo... constants can be set. e.g. kFileInfoCreated, kFileInfoModified, kFileInfoSize can not be set.

; Set the file to read-only.
Do FileOps.$setfileinfo(Path,kFileOpsInfoReadOnly) Returns ErrorCode

; Sets the file to hidden.
Do FileOps.$setfileinfo(kFileOpsInfoHidden,kTrue) Returns ErrorCode

; Set the file to read-only and hidden.
Do FileOps.$setfileinfo(Path,kFileOpsInfoReadOnly,kTrue,kFileOpsInfoHidden,kTrue) Returns ErrorCode

$setunixpermissions

Calculate Permissions as '-rw-r--r--'
Do FileOps.$setunixpermissions(Path,Permissions) Returns Path

Sets the Unix permissions for the specified file.

$splitpathname

Split Path Name

Do FileOps.$splitpathname(Path,Drive,FolderPath,FileName,Ext) Returns ErrorCode

Splits the specified path into drive-name, directory-name, file-name, and file-extension. The path can be to a file or a directory.

The FolderPath includes preceeding and trailing path delimiters. The function returns an error number, or zero if successful.

Warning

If the path is a directory it must include the trailing path delimiter for $splitpathname to work correctly. If the trailing path delimiter is missing, the last directory in the path will be parsed as the FileName.

$writeentirefile

Do FileOps.$writeentirefile(Path,BinVar) Returns ErrorCode

Creates and writes the entire file identified by path, using the data supplied in the binary variable. The function returns an error code, or zero if successful.

If the file already exists, $writeentirefile() replaces it. The value in variable must have the following format:.

When called on Mac OS, the data read into variable includes the Mac OS resource fork and file type information. On return, the value in variable has the following format:

  1. 12 byte header containing the Type (4 bytes), Creator (4 bytes), and Data fork size (4 bytes).
  2. Data fork information.
  3. Resource fork information.

The size of the data fork determines where the resource fork data is stored.

Under Windows and Unix, the resource fork is not written.

deleteDirectory

See the topic deleteDirectory in this section for code which will drill down and delete all the files and subdirectories and then delete the directory.

The following sample code can be used to delete a directory which is not empty. The method will drill down deleting enclosed files and folders. Be careful with this method, it could be used to irreversibly delete all folder and files from a drive.

; This sample code is for a custom 'deleteDirectory' method.
; The method deletes a directory including all the contained files and subdirectories.

; The target directory path is passed in as the parameter 'pTargetDirPath'

; Make a list of any files inside the target directory.
Do FileOps.$filelist(kFileOpsIncludeFiles,pTargetDirPath,kFileOpsInfoFullName) Returns FilesList

; Loop through the list deleting each file.
For FilesList.$line from 1 to FilesList.$linecount step 1
   
   Calculate Path as FilesList.fullname
   Do FileOps.$deletefile(Path) Returns ErrorCode
   If ErrorCode
      OK message (Icon) {Error code [ErrorCode] occured while attempting to delete the file at:////[Path]}
      Break to end of loop
   End If
   
End For
If not(ErrorCode)
   
   ; Make a list of any directories inside the target directory.
   Do FileOps.$filelist(kFileOpsIncludeDirectories,pTargetDirPath,kFileOpsInfoFullName) Returns FilesList
   
   ; Loop through the list deleting directory and contents by calling this method.
   For FilesList.$line from 1 to FilesList.$linecount step 1
      
      Calculate Path as FilesList.fullname
      Do method deleteDirectory (Path) Returns ErrorCode
      If ErrorCode
         ; The called method already reported the error.
         Break to end of loop
      End If
      
   End For
   If not(ErrorCode)
      
      ; Delete the specified target directory.
      Do FileOps.$deletefile(pTargetDirPath) Returns ErrorCode
      If ErrorCode
         OK message (Icon) {Error code [ErrorCode] occured while attempting to delete the directory at:////[Path]}
      End If
   End If
End If
Quit method ErrorCode

kFileOpsInfoCreatorCode

The file creator code is a MacInstosh operating system only property. The creator code specifies the which application opens the file if the user double-clicks on the file to open it. It also affects the icon displayed for the file in the Finder.

Mac OS 9 does not require file extensions so the creator code is important to Mac OS 9 if the file does not have an extension.

Common creator codes are as follows:

  1. Adobe Acroat: CARO
  2. Excel : XCEL
  3. Word: MSWD
Tip

For cross-platform compatability (Win/Mac OS 9, Mac OS X) having the correct the file extension is the most important thing to do. Windows and Mac OS X set the file's icon and application based on the file extension. Mac OS 9 sets the application based on the file extension.

On Mac OS X the creator code can override the file extension mapped application. The file extension .pdf might be mapped to Preview, but if the creator is set to CARO the file's icon and application will point to Adobe Acrobat.

On Mac OS 9 if the creator code is not set the file's icon is will not be set, even if the file extension is set and mapped to an application.

kFileOpsInfoTypeCode

The file type code is a MacIntosh operating system only property. The type code controls which application opens the file if the user double-clicks on the file to open it.

Mac OS 9 does not require file extensions so the type code is important to Mac OS 9 if the file does not have an extension.

If the file has an extension that is listed in the Mac OS 9 Apple menu > Control Panels > File Exchange > PC Exchange tab, and Open unmapped files is checked, the application mapped to the file extension will be used to open the file.

On Mac OS X if the file has a recognizable extension the file will be opened with the application that is mapped to the extension. If the file does not have an extension, or one that is not recongnized by Mac OS X, then the file is opened with the application mapped to the type code if one is found.

Common type codes are as follows:

  1. PDF: 'PDF ' (Excluding the single quotes. Note the trailing space character!)
  2. Text: TEXT
  3. Tif: TIFF

The type codes for Word and Excel files seem to include the application version. (e.g. W8BN, XLS8) It is better to set the creator code than the type code for Word and Excel files.

Setting the type code on Mac OS 9 files is less important than setting the file extension and creator code.

On Mac OS X setting the type code and leaving the creator code blank lets the file be opened by the user's preferred application for the file type. (e.g. Setting the type code to 'PDF ' and leaving the creator code blank allows the Mac OS X to open the PDF in the user's preferred PDF viewer - Preview or Adobe Acrobat. The only reason for setting the type code on Mac OS X is so that the file type isn't lost if the user removes the file extension or doesn't include a file extension when the file is created.)