File Built-ins ¶
File Built-ins provide methods for file system access. A list of compatible charsets is available via Github - Class Charsets.
File From Project ¶
This function returns the file from the current execution context's project folder.
Syntax
1 | <file File> := File.fromProject(<path String>) |
Returns
The specified file.
Parameter
- path - The relative path to the project root folder
Example
1 2 3 | stepdef "assert file {} exists in Project" / fileName / assert File.fromProject("../TestProject01/" + fileName) end |
File From System ¶
This function creates a new file instance by converting the specified path name string into an abstract path name. If the specified string is empty, then the result is an empty abstract path name.
Syntax
1 | <file File> := File.fromSystem(<pathname String>) |
Returns
The new file instance.
Parameter
- pathname - The path's name
Example 1 - Allocating the File with Its Global Path from the System
1 2 3 | stepdef "assert file {} exists in the Project root folder" assert File.fromSystem("/home/user/intaQt-Projects/TestProject01/" + fileName) end |
Example 2 - Creating a File with a Temporary Path
1 2 3 4 | stepdef "create temporary file {} in a temporary directory" / fileName / tempDir := File.createTempDir() testFile01 := File.fromSystem(tempDir.getPath() + File.separator() + fileName) end |
File Relative to Test ¶
This function returns the file from the current execution context's feature folder.
Syntax
1 | <file File> := File.relativeToTest(<path String>) |
Returns
The specified file.
Parameter
- path - The relative path to the feature folder
Example
1 2 3 4 | stepdef "assert test directory" assert File.relativeToTest("x").toString() .endsWith("../projects/builtins-tests/01_features/file-builtin/x") end |
File Relative to User ¶
This function returns the file from the user home folder.
Syntax
1 | <file File> := File.relativeToUser(<path String>) |
Returns
The specified file.
Parameter
- path - The relative path to the user home folder
Example
1 2 3 4 | stepdef "assert user directory" assert File.relativeToUser("x").toString() .equals("/Users/QiTASC/x") end |
Simplify Path ¶
Returns the lexically cleaned form of the path name, usually (but not always) equivalent to the original.
Syntax
1 | <result String> := File.simplifyPath(<pathname String>) |
Returns
The lexically-cleaned form of the path name.
Parameter
- pathname - The file path
The following heuristics are used:
-
Empty string becomes
.
-
.
remains as /.
-
Fold out
./
-
Fold out
../
when possible -
Collapse multiple slashes
-
Delete trailing slashes (unless the path is just
/
)
These heuristics do not always match the file system's behavior. For example, simplifyPath
will change the path a/../b
to b
. If a
is a symlink to x
, a/../b
may refer to a sibling of x
, rather than the sibling of a
referred to by b
.
Example
1 2 3 | stepdef "assert simplified path of {} equals to {}" / path, simplifiedPath / assert simplifiedPath = File.simplifyPath(path) end |
Create¶
Create Parent Directories ¶
This function creates any necessary but nonexistent parent directories of the specified file.
Syntax
1 | File.createParentDirs(<file (String or File)>) |
- file - The input file's identifier
Example
1 2 3 4 | stepdef "create parent directories for {}" / fileName / fromFile := File.fromProject("../TestProject01/" + fileName) File.createParentDirs(file) end |
Note: If this operation fails, it may have succeeded in creating some (but not all) of the necessary parent directories.
Create Temporary Directory ¶
This function automatically creates a new directory somewhere beneath the system's temporary directory. Use this method instead of File.createTempFile(String, String)
when creating a directory instead of a file.
Note: This method assumes that the temporary volume is writable, has free inodes and free blocks, and that it will not be called thousands of times per second.
Syntax
1 | <dir File> := File.createTempDir() |
Returns
The new temporary directory.
Example
1 2 3 4 | stepdef "create a temporary directory and print its path" tempDir := File.createTempDir() println(tempDir.getPath()) end |
Create Temporary File ¶
This method creates a temporary file in either the default directory or a specified directory. In both cases, the specified prefix and suffix are used to generate the file's name.
Important! A common mistake is to call createTempFile
, delete the file and create a directory in its place. This leads a race condition, which can be exploited to create security vulnerabilities, especially when executable files written into the directory.
Syntax
1 | <tempFile File> := File.createTempFile(<prefix String>, <suffix String>, <directory (String or File)>) |
Returns
An abstract pathname, representing a newly-created empty file.
Parameters
-
prefix - The prefix to be used in generating the file's name
- It must be at least three characters long
- If it is too long, it will be truncated
-
suffix - The suffix to be used in generating the file's name
- If null,
.tmp
will be used - If the suffix is too long, it will be truncated
- If null,
-
directory (Optional) - The directory where the file is to be created, or null if the default temporary file directory is to be used
Example
1 2 3 4 | stepdef "create a temporary file with prefix {} in folder of the file {}" / prefix, fileName / projectFile := File.fromProject("../TestProject01/" + fileName) tempFile := File.createTempFile(prefix, ".txt", projectFile.getParentFile()) end |
Note:
If the directory argument is null then the system-dependent default temporary file directory will be used. The default temporary file directory is specified by the system property, java.io.tmpdir
.
-
On Unix systems, the default value of this property is typically
/tmp
or/var/tmp
. -
On Windows systems, it is typically
C:\\WINNT\\TEMP
. -
A different value may be specified to this system property when the Java virtual machine is invoked. Programmatic changes to this property are not guaranteed to have any influence upon the temporary directory used by this method.
Touch File ¶
This method creates an empty file or updates the last updated timestamp with the Unix command of the same name.
Syntax
1 | File.touch(<file (String or File)>) |
Parameter
- file - The file to create or update
Example
1 2 3 4 5 6 7 | stepdef "assert modified timestamp of touched file {} changed" / fileName / file := File.fromProject("../TestProject01/" + fileName) oldTimestamp := file.lastModified() delay(1) File.touch(file) assert oldTimestamp < file.lastModified() end |
Delete File ¶
The following function deletes a file or a directory from the file system using intaQt languages.
Syntax
1 | <isDeleted Boolean> := File.delete(<dir String>) |
Returns
true
if a file or a directory is successfully deleted, false
otherwise.
Parameter
- dir - An identifier to a path or a directory
In the following example, the File.delete
method searches for a string, which can either represent a directory or a path and deletes it.
Example
1 2 3 4 | stepdef "delete file {}" / fileName / myFile := File.fromProject("/externalFiles/" + fileName) File.delete(myFile) end |
Note:
Even if the file or the directory does not exist, fromProject()
will create a File instance. This will force the return value of the delete()
function to be true even there is no directory or file in the first place.
Equals File ¶
This checks if two files contain the same amount of bytes.
Syntax
1 | <isEqual Boolean> := File.equal(<file1 (String or File)>, <file2 (String or File)>) |
Returns
true
if files contain the same amount of bytes as each other, false
otherwise.
Parameters
-
file1 - The first file to compare
-
file2 - The file to compare the first file to
Example
1 2 3 4 5 6 | stepdef "assert file {} equals to {}" / fileName1, fileName2 / file1 := File.fromProject("/TestProject01/" + fileName1) file2 := File.fromProject("/TestProject01/" + fileName2) isEqual := File.equal(file1, file2) assert isEqual end |
File Extension ¶
This function returns the file extension of the specified file name, or an empty string if the file has no extension. The extension's dot (.
) is not included in the result.
Syntax
1 | File.getFileExtension(<fileName String>) |
Parameters
-
extension - The object that holds the extension
-
fileName - The name of the file
Example
1 2 3 4 5 6 | stepdef "assert extension of configuration file {} equals to conf" / confFileName / myFile := File.fromProject("../TestProject01/" + confFileName) // Using getName() to get the String name of the file instance 'myFile' extension := File.getFileExtension(myFile.getName()) assert "conf" = extension ! "The extensions do not match" end |
File Separator ¶
This function returns the system-dependent name separator character as a string. For example, "/"
or "\"
.
Syntax
1 | File.separator() |
Example
1 2 3 4 | stepdef "create platform independent filepath {}" / fileName / dir := File.createTempDir() file := File.fromSystem(dir.getPath() + File.separator() + fileName) end |
Get Name Without Extension ¶
This method retrieves a file's name without its extension or path. This is similar to the basename
Unix command. The result does not include the ".
".
Syntax
1 | <name String> := File.getNameWithoutExtension(<file String>) |
Returns
The file name without its file extension or path.
Parameter
- file - The name of the file to trim the extension from
- This can be a fully qualified file name (including a path) or a file name
Example
1 2 3 | stepdef "assert name of file {} without extension equals to {}" /fileName, fileNameWOE/ assert fileNameWOE = File.getNameWithoutExtension(fileName) end |
Move File ¶
This function can rename a file and/or move it to a different directory.
Syntax
1 | File.move(<from (String or File)>, <to (String or File)>) |
Parameters
-
from - The source file
-
to - The destination file
- This must be the target path for the moved file itself
Example
1 2 3 4 5 6 | stepdef "move file to another folder" fromFile := File.fromProject("testProject.conf") toFile := File.fromProject("/externalFiles/newText.txt") File.move(fromFile.getPath(), toFile.getParentFile() + File.separator() + fromFile.getName()) end |
Path Separator ¶
This function returns the system-dependent path separator character. For example, :
or ;
.
Syntax
1 | <pathSeparator String> := File.pathSeparator() |
Returns
The path separator.
Example
1 2 3 | stepdef "print path separator" println(File.pathSeparator()) end |
Read First Line ¶
This function reads the first line from a file by either using the specified charset or the default charset. It returns the first line, or null if the file is empty. With both methods, the line does not include line termination characters, but does include other leading and trailing whitespaces.
Syntax
1 | <result String> := File.readFirstLine(<file (String or File)>, <charset String>) |
Returns
The line read by the given method.
Parameters
-
file - The file to read from
-
charset (Optional) - The charset used to decode the input stream
Example 1 - Using the Specified Charset
1 2 3 4 | stepdef "assert first line in {} equals to {}" / fileName, firstLine / file := fromProject(fileName) assert firstLine := File.readFirstLine(file, "UTF-8") end |
Example 2 - Using the Default Charset
1 2 3 4 | stepdef "assert first line in {} equals to {}" / fileName, firstLine / file := fromProject(fileName) assert firstLine := File.readFirstLine(file) end |
Read All Lines ¶
This function reads all lines from a file by either using the specified charset or the default charset and returns a mutable List containing all the lines. In both cases, the lines do not include line-termination characters, but do include other leading and trailing whitespace.
Syntax
1 | <lines List<String>> := File.readLines(<file (String or File)>, <charset String>) |
Returns
The list containing all read lines.
Parameters
-
file - The file to read from
-
charset (Optional) - The charset used to decode the input stream
Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | stepdef "assert lines in {} equals to {}" / fileName, linesSeparatedByHash / file := File.fromProject(fileName) setContextObject("myFile", file) retrievedFile:= getContextObject("myFile", "UTF-8") expectedLines := linesSeparatedByHash.split("#") newLines := [] for line in expectedLines newLines.add(line) end lines := File.readLines(file) assert lines.size() = newLines.size() for lineIndex, line in expectedLines assert line = lines[lineIndex] end end |
Read To String ¶
This function reads all lines from a file and returns a string containing all the characters from the file. This can be done by either using the specified charset or the default charset. It returns a string containing all the characters from the file.
Syntax
1 | <result String> := File.readToString(<file (String or File)>, <charset String>) |
Returns
A string containing all the characters from the file.
Parameters
-
file - The file to read from
-
charset (Optional) - The charset used to decode the input stream
Example 1 - Using the Specified Charset
1 2 3 4 | stepdef "Read content in file {}" / fileName / file := File.fromProject(fileName) fileContent = File.readToString(file, "UTF-8") end |
Example 2 - Using the Default Charset
1 2 3 4 | stepdef "Read content in file {} using default charset" / fileName / file := File.fromProject(fileName) fileContent = File.readToString(file) end |
Write ¶
The write()
function provides the functionality to replace all characters in a file using the specified charset or the default charset.
Syntax
1 | File.write(<from String>, <to (String or File)>, <charset String>) |
Parameters
-
from - The characters being written to a file
-
to - The destination file
-
charset (Optional) - The specified charset
Example 1 - Using the Specified Charset
1 2 3 | stepdef "write {} to {}" / content, fileName / file := File.fromProject("../TestProject01/" + fileName) File.write(content, file, "UTF-8") |
Example 2 - Using the Default Charset
1 2 3 4 | stepdef "write {} to {} using the default charset" / content, fileName / file := File.fromProject("../TestProject01/" + fileName) File.write(content, file) end |
Append ¶
There are two append methods. The first method appends a character sequence to a file using the specified charset. The second method appends a character sequence to a file using the default charset.
Note: The default charset is determined during virtual machine startup and typically depends upon the locale and charset of the underlying operating system.
Syntax
1 | File.append(<from String>, <to (String or File)>, <charset String>) |
Parameters
-
from - The character sequence to append
-
to - The destination file or its path
-
charset (Optional) - The charset used to encode the output stream
Example 1 - Using the Specified Charset
1 2 3 4 5 6 | stepdef "append text {} to the file {}" / text, fileName / // Get a file with the name "fileName" located in the main TestProject01 folder testFile := File.fromSystem("/home/user/intaQt-Projects/TestProject01/" + fileName) // Append the file with the predefined text File.append(text, testFile, "UTF-8") end |
Example 2 - Using the Default Charset
1 2 3 4 5 | stepdef "append another text {} to the file {}" / text, fileName / // Using the double dot indicates the parent directory testFile := File.fromProject("../TestProject01/" + fileName) File.append(text, testFile) end |
Note: More information is available in Execution and Language Context Built-ins.
Copy ¶
This function copies all bytes from one file to another. It only works with local files. To copy files to or from remote machines, use Copy Built-ins.
Syntax
1 | File.copy(<from (String or File)>, <to (String or File)>) |
Parameters
-
from - The source file
-
to - The destination file
Example
1 2 3 4 5 | stepdef "copy {} to {}" / from, to / fromFile := File.fromProject("../TestProject01/" + from) toFile := File.fromProject("../TestProject01/" + to) File.copy(fromFile, toFile) end |
Text File Chunking ¶
The chunk
method parses text files of any size into chunks. This consists of:
-
The file to chunk.
-
A function that takes a string (a line from the file) and returns
true
if the string is a line that matches the start of a chunk. -
A callback function that has the chunks of the file passed to it as they are encountered.
Syntax
1 2 | File.chunk(<inputFile File>, <chunkStart FunctionRef(String)>, <forEachChunk FunctionRef(List<String>)>) |
Parameters
-
inputFile - The file to be parsed
-
chunkStart - The function that marks the start of the chunk
-
forEachChunk - The function that passes each chunk of lines from the file
Example
1 2 3 4 5 6 7 8 9 10 11 | stepdef "check that log file {} has correct number of chunks" / f1 / inputFile := File.fromProject(f1) LogFileReactor.init(regex(" \\[[\\w\\d]+\\] ")) File.chunk(inputFile, LogFileReactor::startOfChunk, LogFileReactor::forEachChunk) assert LogFileReactor.theCount = 3 end |
In the example stepdef above, a file is opened. Next, reactor calls a Regex, using Regex Built-ins. Then, the File.chunk
method is called, passing the input file and interpreting whether or not the specified string matches the start of a chunk. Finally, an assertion is made to check the count of the chunks.
Reactor Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | reactor LogFileReactor func init(regex) LogFileReactor.theCount := 0 LogFileReactor.startOfChunkRegex := regex end func startOfChunk(line) return startOfChunkRegex.containsMatchIn(line) end func forEachChunk(lines) theCount := theCount + 1 end end |
In the example above, the init
method sets up the count and internally stores the regex. The startOfChunk
function checks that there is at least one match for the regex in the line. Alternatively, the [Regex Built-ins](Regex matches
function can check that the Regex matches the entire line.
When the Stepdef invokes the chunk
method, the startOfChunk
method is called for each line, and chunks are collected together. Once a complete chunk has been found, it will be passed to the forEachChunk
method, where assertions (or storage of data for later assertions as in this case) may take place.
Note:
Creating the regex a single time and passing it is more efficient than creating it each time a line is read: The startOfChunk
will be called for each line.
File Walking ¶
File walking allows users to recursively visit all files in a directory and perform filtering and other operations via callbacks on specified files.
Syntax
1 2 | File.walk(<directory File>, <onEach FunctionRef>, <fileWalkDirection Boolean>, <shouldEnter File>, <onLeave File>) |
Parameters
-
directory - The directory within which the files will be walked
-
onEach - The function that will be called for each file
-
fileWalkDirection (optional) - Specifies the direction to walk through the files in
- Default is set to
topDownDirection
, which searches depth-first where the directory is visited before its files bottomUpDirection
searches breadth-first, where the directory is visited after its files
- Default is set to
-
shouldEnter (optional)
true
if the file should be walkedfalse
otherwise
-
onLeave (optional) - This allows operations to be performed on every directory once it and its files have been visited
Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | stepdef "list files in directory {}" / q2 / directoryFile := File.fromProject(q2) setContextObject("files", []) File.walk(directoryFile, FileMatcher::onEach, File.topDownDirection) files := getContextObject("files") end model FileMatcher func onEach(file) if file.name.contains("product_list") and file.name.endsWith(".xml") then getContextObject("files").add(file) end end end |
The example above gets a list of XML files with a "product_list"
string in their names from a directory.
File Walking - Sorted Walk ¶
The sortedWalk
function walks the directory, using a comparator to specify the order in which the files are passed to the callback. sortedWalk
may compare by name, or apply a customizable order in which files are provided to the callback. Customization allows for, for example:
-
Defining which directories to enter, and in what order.
-
Defining the order in which files will be walked within each directory, e.g., sorting
myMusic123.mp3
andmyMusic567.mp3
in numerical order first, then by alphabetical order.
Syntax
1 | file.sortedWalk(<directory File>, <comparatorFunction (File, File) → Number>, <direction FileWalkDirection>, <shouldEnter (File) → Boolean>, <onlyFiles Boolean>) |
Parameters
-
directory - The directory within which the files will be walked
-
comparatorFunction - A comparator function, which takes two files, and returns an Integer result
- The result should be a negative integer, zero or a positive integer for the cases where the first file should be considered less than, equal to, or greater than the second
- Two convenience constructors are provided:
- compareByName, which is a simple comparator based on the file name
- compareByNameParts, which allows greater control over sorting by parts of filenames
-
direction - The direction in which to walk the directory, which may be one of:
File.topDownDirection
- Starts from the top-levelFile.bottomUpDirection
- Starts from the bottom level
-
shouldEnter (optional)
true
if the directory should be walkedfalse
otherwise
-
onlyFiles (optional)
true
(default) only retrieves filesfalse
also retrieves directories
Example 1 - Sort by Name
1 2 3 4 5 6 7 8 9 10 | stepdef "test of file walking" file := File.fromSystem("/Users/user/Desktop/files") File.sortedWalk(file, File.compareByName(File.ascending), Filewalktest::onFileFound) end model Filewalktest func onFileFound(file) println(file.name) end end |
Example 2- Customized Sorting
1 2 3 4 5 6 7 | stepdef "test of sorted file walking" file := File.fromSystem("/Users/user/Desktop/files") File.sortedWalk(file, File.compareByNameParts(regex("(\\w)(\\d+).*"), [ File.namePart(2, true, File.ascending), File.namePart(1, false, File.descending)]), Filewalktest::onFileFound) end |
In the above example, a comparator is created that sorts ascending by the second group of a regex expression. If this is equal between files, then it will sort by the first group in a descending order.
Sorted Walk - Compare By Name ¶
compareByName
compares the files by name.
Syntax
1 | File.compareByName(File.<order FileSortingOrder> ) |
Parameter
- order - One of
File.ascending
orFile.descending
Example
1 | File.sortedWalk(file, File.compareByName(File.ascending), Filewalktest::onFileFound) |
Sorted Walk - Compare By Name Parts ¶
ComparebyName
takes a namePart, and a RegexWrapper
, which splits the file/directory names according to the defined pattern.
Syntax
1 | File.CompareByNameParts(<regex RegexWrapper>,[<List <NamePart>, ...]) |
Parameters
-
regex - The Regex pattern used to split the files/directories by name
-
List - The list of
namePart
s
Example
1 2 3 4 | File.compareByNameParts(regex("(\\w)(\\d+).*"), [ File.namePart(2, true, File.ascending), File.namePart(1, false, File.descending)]), Filewalktest::onFileFound) |
Sorted Walk - Name Parts ¶
namePart
parses the Regex group, created in the compareByNameParts
function, by its assigned index. It is then converted into a number and sorted in ascending or descending order.
Syntax
1 | File.namePart(<index Number>, <isNumeric Boolean>, <fileSortingOrder Order>) |
Parameters
-
index - A user-assigned number that indicates the Regex group
-
isNumeric
true
for to parse the Regex group as an integerfalse
otherwise
-
fileSortingOrder - The order in which to sort the files/directories
FileSortingOrder.ASC
- Sorts in ascending order (default)FileSortingOrder.DES
- Sorts in descending order
Example
1 | File.namePart(2, true, File.ascending), File.namePart(1, false, File.descending) |
Note:
The list of namePart
s are sorted by the order in which they appear within the function. In the example above, the namePart
with index 2
is sorted first.