FileHelper module

Functions that write, append to and read a text file, test whether a file or folder exists, and take paths apart. A program uses them to save a report that a formatter made. They call the file statements of the runtime library (Open, Put, Get, Kill, MkDir, GetAttr), and need no other library.

The functions are called with the name of the module, as in FileHelper.WriteFile(report, path). Three of them, WriteFile, AppendFile and ReadFile, return a Variant and never raise an error. WriteFile and AppendFile return True, and when something fails, a String that describes the failure; a program tells the two apart with VarType. ReadFile returns a String in both cases, the content of the file or the description of the failure, and the description starts with the text Error . A file that does not exist is not a failure for ReadFile and GetFileSize: they create it. See Known problems.

Dim folder As String = Environ$("TEMP") & "\diag-filehelper"
Dim path As String = folder & "\report.txt"
FileHelper.DeleteFile path

Debug.Print FileHelper.WriteFile("Hello", path)
Debug.Print FileHelper.GetFileSize(path)
Debug.Print FileHelper.AppendFile(" world", path)
Debug.Print FileHelper.GetFileSize(path)
Debug.Print FileHelper.FileExists(path)
Debug.Print FileHelper.DirectoryExists(folder)
Debug.Print FileHelper.DeleteFile(path)
Debug.Print FileHelper.FileExists(path)
RmDir folder
' Output:
' True
' 8
' True
' 14
' True
' True
' True
' False

The files that WriteFile and AppendFile write are UTF-8 with a byte-order mark (the bytes EF BB BF at the start). The text is converted with StrConv and the constant vbUTF8.

Paths

A path that is not absolute is taken as relative to the folder of the program, App.Path, and not to the current folder. GetFullPath makes the full path, and the functions that open, test, read or delete a file call it first. EnsureDirectoryExists and the functions that take a path apart (GetDirectoryName, GetFileName, GetFileNameWithoutExtension, GetExtension, IsAbsolutePath and NormalizePath) use the text as it is given.

Debug.Print FileHelper.GetFullPath("x.txt") = App.Path & "\x.txt"
Debug.Print FileHelper.GetFullPath("sub\..\x.txt") = App.Path & "\x.txt"
Debug.Print FileHelper.GetFullPath("C:\a\..\b\x.txt")
' Output:
' True
' True
' C:\b\x.txt

Methods

AppendFile

Adds text to the end of a file.

Syntax: FileHelper.AppendFile ( content, filePath ) As Variant

content
required A String.
filePath
required A String, the path of the file, absolute or relative to App.Path.

Creates the file if it does not exist, and the folder that holds it when only that last folder is missing (see EnsureDirectoryExists). The file is written in UTF-8. The byte-order mark is written only when the file is empty or new. The content goes after the last byte of the file.

Returns True, or a String of the form Error and the number, a colon, the description, and (File: and the path as the caller gave it, and ). The function raises no error.

DeleteFile

Deletes a file.

Syntax: FileHelper.DeleteFile ( filePath ) As Boolean

filePath
required A String, the path of the file, absolute or relative to App.Path.

Calls Kill and returns True. Returns False for any error, a file that does not exist included. The path may hold the wildcards * and ? that Kill accepts, and then every file that matches is deleted.

Dim folder As String = Environ$("TEMP") & "\diag-wild"
FileHelper.EnsureDirectoryExists folder
FileHelper.WriteFile "a", folder & "\a.tmpd"
FileHelper.WriteFile "b", folder & "\b.tmpd"

Debug.Print FileHelper.DeleteFile(folder & "\*.tmpd")
Debug.Print FileHelper.FileExists(folder & "\a.tmpd") Or FileHelper.FileExists(folder & "\b.tmpd")
Debug.Print FileHelper.DeleteFile(folder & "\a.tmpd")
RmDir folder
' Output:
' True
' False
' False

DirectoryExists

Tests whether a folder exists.

Syntax: FileHelper.DirectoryExists ( dirPath ) As Boolean

dirPath
required A String, the path of the folder, absolute or relative to App.Path.

Returns True when GetAttr succeeds and reports a folder. A file, or a path that does not exist, gives False.

EnsureDirectoryExists

Creates a folder.

Syntax: FileHelper.EnsureDirectoryExists ( path )

path
required A String, the path of the folder.

Removes one trailing backslash and calls MkDir. It ignores every error, so a folder that exists is not an error, and neither is a folder that cannot be created. MkDir creates the last level only. When the folder above it does not exist, nothing is created and no error is reported: WriteFile then returns the error text of Open, which is Error -2147467259: Unspecified error and the path. VB6 raises error 76, Path not found, for the same Open statement.

Dim root As String = Environ$("TEMP") & "\diag-new"
Dim result As Variant = FileHelper.WriteFile("x", root & "\sub\a.txt")
Debug.Print VarType(result) = vbString
Debug.Print Left$(result, InStr(result, " (File: ") - 1)
result = FileHelper.AppendFile("x", root & "\sub\a.txt")
Debug.Print Left$(result, InStr(result, " (File: ") - 1)
Debug.Print FileHelper.DirectoryExists(root)
' Output:
' True
' Error -2147467259: Unspecified error
' Error -2147467259: Unspecified error
' False

FileExists

Tests whether a file exists.

Syntax: FileHelper.FileExists ( filePath ) As Boolean

filePath
required A String, the path of the file, absolute or relative to App.Path.

Returns True when GetAttr succeeds and the path is not a folder. A folder, or a path that does not exist, gives False.

GetDirectoryName

Returns the folder part of a path.

Syntax: FileHelper.GetDirectoryName ( path ) As String

path
required A String.

Removes the spaces at both ends and one trailing slash or backslash, and returns the text before the last backslash, or, when there is none, before the last slash. A path with no separator gives an empty string. The root of a drive is returned without its backslash: C:\a\b.txt gives C:\a, and C:\a\ and C:\a.txt give C:.

GetExtension

Returns the extension of a file name.

Syntax: FileHelper.GetExtension ( path ) As String

path
required A String.

Returns the part of the file name from its last period, with the period: .gz for b.tar.gz. An empty string when the name has no period. A name that starts with a period, such as .gitignore, is all extension.

GetFileName

Returns the file name of a path.

Syntax: FileHelper.GetFileName ( path ) As String

path
required A String.

Removes the spaces at both ends and returns the text after the last backslash, or, when there is none, after the last slash. A path with no separator is returned as it is.

GetFileNameWithoutExtension

Returns the file name without its extension.

Syntax: FileHelper.GetFileNameWithoutExtension ( path ) As String

path
required A String.

Returns the file name of path up to its last period: b.tar for b.tar.gz.

GetFileSize

Returns the size of a file in bytes.

Syntax: FileHelper.GetFileSize ( filePath ) As LongLong

filePath
required A String, the path of the file, absolute or relative to App.Path.

Opens the file in binary mode and returns the result of LOF. Returns -1 when an error occurs, such as a folder that does not exist. The function opens the file with For Binary, and that mode creates a file that does not exist, so a missing file in a folder that exists is not an error: it is created with no content and the function returns 0. See Known problems.

Dim path As String = Environ$("TEMP") & "\diag-missing.bin"
FileHelper.DeleteFile path
Debug.Print FileHelper.FileExists(path)
Debug.Print FileHelper.GetFileSize(path)
Debug.Print FileHelper.FileExists(path)
FileHelper.DeleteFile path
Debug.Print FileHelper.GetFileSize(Environ$("TEMP") & "\diag-no-folder\x.bin")
' Output:
' False
' 0
' True
' -1

GetFullPath

Returns the full path for a path.

Syntax: FileHelper.GetFullPath ( path ) As String

path
required A String.

Removes the spaces at both ends. An empty path becomes .\. A path that IsAbsolutePath rejects gets App.Path and a backslash in front. The result is then passed through NormalizePath.

IsAbsolutePath

Tests whether a path is absolute.

Syntax: FileHelper.IsAbsolutePath ( path ) As Boolean

path
required A String.

Returns True when the second character, after the spaces at both ends are removed, is a colon, as in C:\a, or when the path starts with two backslashes, as in \\server\share. Any other path gives False, including \a (a path from the root of the current drive) and //server/share (with slashes).

NormalizePath

Cleans up the separators of a path.

Syntax: FileHelper.NormalizePath ( path ) As String

path
required A String.

Changes every slash to a backslash and every run of backslashes to one. It then goes through the parts between the backslashes: it removes the spaces at both ends of a part, drops an empty part and a part ., and lets a part .. remove the part before it. A .. with nothing before it is dropped. The parts are joined with a backslash, and the result has no backslash at the start or at the end.

Because an empty first part is dropped, a path from the root, such as \a\b, loses its first backslash, and so does a UNC path: \\server\share\f.txt becomes server\share\f.txt, which is a relative path. GetFullPath treats such a path as absolute and does not add App.Path, so a file in a UNC path is opened as the relative path server\share\f.txt. See Known problems.

Debug.Print FileHelper.NormalizePath("C:/a//b/./c/../d.txt")
Debug.Print FileHelper.GetDirectoryName("C:\a\b.txt")
Debug.Print FileHelper.GetDirectoryName("C:\a\")
Debug.Print FileHelper.GetFileName("C:\a\b.tar.gz")
Debug.Print FileHelper.GetFileNameWithoutExtension("C:\a\b.tar.gz")
Debug.Print FileHelper.GetExtension("C:\a\b.tar.gz")
Debug.Print FileHelper.IsAbsolutePath("C:\a") & " " & FileHelper.IsAbsolutePath("a\b")
Debug.Print FileHelper.NormalizePath("\\server\share\f.txt")
Debug.Print FileHelper.GetFullPath("\\server\share\f.txt")
' Output:
' C:\a\b\d.txt
' C:\a
' C:
' b.tar.gz
' b.tar
' .gz
' True False
' server\share\f.txt
' server\share\f.txt

ReadFile

Reads a whole file as text.

Syntax: FileHelper.ReadFile ( filePath ) As Variant

filePath
required A String, the path of the file, absolute or relative to App.Path.

Returns the content of the file as a String, and an empty string for an empty file. When an error occurs, such as a folder that does not exist, it returns an error text in the form that AppendFile describes. A file that does not exist is not an error: it is created with no content, as for GetFileSize, and the function returns an empty string, so a missing file and an empty file look the same. See Known problems.

The function reads the bytes of the file into a string as characters, and does not decode UTF-8 or remove a byte-order mark. A file that WriteFile wrote therefore starts with the three characters of its byte-order mark, and a character above 127 is several characters.

Dim path As String = Environ$("TEMP") & "\diag-readfile.txt"
FileHelper.DeleteFile path
FileHelper.WriteFile "caf" & ChrW$(233), path

Dim text As Variant = FileHelper.ReadFile(path)
Debug.Print VarType(text) = vbString
Debug.Print Len(text)
FileHelper.DeleteFile path

Debug.Print VarType(FileHelper.ReadFile(path)) = vbString
Debug.Print Len(FileHelper.ReadFile(path))
Debug.Print FileHelper.FileExists(path)
FileHelper.DeleteFile path
' Output:
' True
' 8
' True
' 0
' True

WriteFile

Writes text to a file.

Syntax: FileHelper.WriteFile ( content, filePath ) As Variant

content
required A String.
filePath
required A String, the path of the file, absolute or relative to App.Path.

Creates the file, and the folder that holds it when only that last folder is missing (see EnsureDirectoryExists). It writes the byte-order mark and then the text in UTF-8, from the start of the file. Returns True, or an error text as AppendFile describes.

WriteFile opens the file in binary mode and does not shorten it. When the file exists and is longer than the new content, the bytes after the new content stay in the file. See Known problems.

Dim path As String = Environ$("TEMP") & "\diag-writefile.txt"
FileHelper.DeleteFile path

FileHelper.WriteFile "0123456789", path
Debug.Print FileHelper.GetFileSize(path)
FileHelper.WriteFile "ab", path
Debug.Print FileHelper.GetFileSize(path)
FileHelper.DeleteFile path

Debug.Print FileHelper.WriteFile("", path)
Debug.Print FileHelper.GetFileSize(path)
FileHelper.DeleteFile path
' Output:
' 13
' 13
' True
' 3

An empty string is not an error: the file holds the three bytes of the byte-order mark.

See Also