Read or write file

Syntax

s.getfile(file [from] [nbytes])
s.setfile(file [from] [nbytes] [flags])

 

Parameters

s - str variable.

file - file.

from - offset in file. Default: 0.

nbytes - number of bytes to read or write. Default: -1.

flags (used only with setfile):

1 Append new line characters.
2 When writing to existing file (OPEN_ALWAYS), set end of file where writing ends. Read more in remarks.
4

QM 2.3.2. Create new or open existing file. Read more in remarks.

0x100 QM 2.4.0. Safe/atomic saving. The file will never be corrupted on power failure etc. Writes to a temporary file, flushes its buffers, and renames the temporary file to file, replacing if exists.
0x200 QM 2.4.0. Safe saving and backup. Same as 0x100, but also creates a backup file, named file-backup.

 

Remarks


getfile loads file content to s.

 

Error if the file does not exist.

 

If from and nbytes are not used or are 0 and -1, loads whole file.

If from is >0 and nbytes not used or -1, loads whole file starting from from.

Not error if from+nbytes is more than file length. Then s will contain less than nbytes or will be empty.

 

QM 2.4.1. getfile supports macro resources. If file is resource name (eg "resource:data.bin"), gets resource data. When creating exe, QM adds the macro resource to exe resources, and in exe getfile gets data from the exe resource. Don't use from and nbytes.

 

QM 2.3.0. getfile supports exe resources. If file begins with : and an integer number 1 to 0xffff (eg ":5 c:\data.bin"), in exe getfile gets data from exe resource whose id is the number and type is RT_RCDATA (10). When the macro runs in QM, it gets data from the file. When creating exe, if "Auto add files ..." is checked, QM adds the file to exe resources. Don't use from and nbytes.

 

Don't use this function to load large files, because then may fail to allocate memory for s. Instead read parts of the file. It is more efficient with Windows API functions; you can use class __HFile. Or use a database, for example Sqlite class.

 


setfile writes s to file.

 

If the file does not exist, creates. Uses Windows API function CreateFile with creation mode CREATE_ALWAYS or OPEN_ALWAYS.

 

If from is -1, appends.

If nbytes is < 0 or > s.len, writes whole s.

 

Safe saving is slower, mostly because immediately writes to disk (else Windows would write later). Then just renames file, which is fast. However if OPEN_ALWAYS used, copies old file to the temporary file, which can be slow if the file is big.

 

Some possible setfile errors:

The filename contains invalid filename characters. To avoid it, you can use str function ReplaceInvalidFilenameCharacters.

The file is opened for exclusive access by another process or some QM function.

QM is running not as administrator and the file is in Program Files, Windows, or some other protected folder.

The file has read-only attribute. When using safe saving, the function removes this attribute and does not fail.

 

QM 2.3.5. Creates parent folder if does not exist. In older QM would be error.

 


Note: In Unicode mode, other string functions interpret text as UTF-8. If you use getfile to load an ANSI text file that contains non ASCII characters, and pass the text to other string functions, you may have to convert ANSI to UTF-8. You also may have to do conversions in some other cases.

 

Tips

You can use the My QM folder (in My Documents) to save various files used by your macros. Use special folder string $my qm$.

These functions open the file, write/read, and close. To perform multiple write/read operations without reopening, instead use Windows API functions; you can use class __HFile.

If it is possible that several threads (running functions) access the same file simultaneously, use lock to prevent it. If several processes or computers write to the file simultaneously, use CFileInterlocked class, it is in the forum.

You can use functions rget and rset to write to or read from ini files.

 

See also: CSV, XML, Sqlite class, other file category functions and classes.

 

Example

str s1 s2 f
f="$my qm$\test.txt"
s1="test data"
s1.setfile(f)
s2.getfile(f)
out s2