Watch out
Getting an
Arguments are not sufficiently instantiated
error?
Note that there are two tmp_file_stream/3 predicates which take parameters with different semantics! (Yes! But ... why?)
This one is detected if first argument is an atom:
% tmp_file_stream(+Encoding, -FileName, -Stream) ?- tmp_file_stream(utf8,Filename,Stream). Filename = '/tmp/swipl_10582_0', Stream = <stream>(0x1de5680).
Otherwise this one is used and argument 3 must be a list:
% tmp_file_stream(-FileName, -Stream, +Options) ?- tmp_file_stream(Filename,Stream,[encoding(utf8)]). Filename = '/tmp/swipl_10582_1', Stream = <stream>(0x1e00020).
(10582 is the current process id of swipl
btw.)
Just always use
tmp_file_stream(-FileName, -Stream, +Options)
for consistency.
After the call, these files exist (they are also secure against any process not of this user reading or writing them):
[david@nostromo ~]$ ls -l /tmp/swipl_10582_0 -rw-------. 1 david david 0 Nov 29 18:55 /tmp/swipl_10582_0
Reference
Pretty sure this one results in a call to mkstemp
:
- https://linux.die.net/man/3/mkstemp
- https://pubs.opengroup.org/onlinepubs/009695399/functions/mkstemp.html
Changing the temporary directory
By default directory `/tmp` (or some other system-usual default) is used. You can change the temporary directory to be used with set_prolog_flag/2:
?- set_prolog_flag(tmp_dir,'/home/dumpster').
That directory must exist. From that point on:
?- tmp_file_stream(Filename,Stream,[encoding(utf8)]). Filename = '/home/dumpster/swipl_11133_1', Stream = <stream>(0xaab730).
Example: write lines to a temporary file
write_file(FileName,Lines,Options) :- must_be(var,FileName), must_be(list,Lines), must_be(list,Options), setup_call_cleanup( tmp_file_stream(FileName, OutputStream, [encoding(utf8)]), write_all_lines(Lines,OutputStream,Options,0), close(OutputStream)). write_all_lines([L|Lines],OutputStream,Options,LineCount) :- ( (LineCount > 0) -> format(OutputStream,"~n",[]) ; true ), ( (is_list(L);string(L)) -> format(OutputStream,"~s",[L]) % able to print String, Atom, CharList, CodeList ; (is_number(L)) -> format(OutputStream,"~a",[L]) % able to print Atom, but also numbers ; format(OutputStream,"~k",[L]) % "write canonical" ), LineCountP is LineCount + 1, write_all_lines(Lines,OutputStream,Options,LineCountP). write_all_lines([],OutputStream,Options,_) :- (memberchk(finalize(eol),Options) -> format(OutputStream,"~n",[]) ; true).
Then
?- write_file(FileName,["Hello","World"],[]). FileName = '/tmp/swipl_21045_0'.
The file '/tmp/swipl_21045_0' exists with the expected content, as can be checked on the command line, as long as the SWI-Prolog process swipl
is live (but maybe stopped):
$ hexdump --canonical /tmp/swipl_21045_0 00000000 48 65 6c 6c 6f 0a 57 6f 72 6c 64 |Hello.World| 0000000b
When the SWI-Prolog process swipl
ends, the file is removed.
With the option finalize(eol)
you get an additional EOL:
?- write_file(FileName,["Hello","World"],[finalize(eol)]). FileName = '/tmp/swipl_21107_0'.
Then, on the command line, a final LF has been added.
$ hexdump --canonical /tmp/swipl_21107_0 00000000 48 65 6c 6c 6f 0a 57 6f 72 6c 64 0a |Hello.World.| 0000000c
On Windows, the LF should all be CR+LFs (I haven't tested this).