can I work with files as I used to do in Java. Suppose I have a file with 3 lines as follows:
This is hello world.
This is not hello world.
This is a story of
First a comment: if you program in Prolog, it is probably best to try to work with files like you work with files in Prolog, and not like you used to do this with Java.
And a suggestion: Read the documentation. It hurts the first time, but you will learn to like it. SWI-Prolog has a very complete and easy to search documentation available on its web site.
Now: you really need to know a bit better what it is that you are actually trying to do with these files. It matters for the approach you will use for reading them, and representing them inside your program.
Specifically: you can represent "text" in Prolog as:
The list goes on, but these are the most obvious ones at the beginning. Every approach has its strengths, and which one you use really depends on your application.
This is only the first step, anyway. Depending on what you want to do with the contents of the file, it might be useful to first tokenize it to atoms, or more complex terms.
The rest of this answer is SWI-Prolog specific, to a certain extent.
If you are reading from a file, it might be useful to use Pure I/O library, and DCGs. Two issues with this approach: you need to learn what DCGs are; it does not work nicely if you try to read from a non-repositioning stream (it does not work with standard input, for example). You can always read the whole file, however, and use DCGs, if you need to actually parse. This is the most general approach, without any doubt. You can look here for efficient reading of a whole file.
If you are reading actual Prolog terms, you might be needing the term reading and writing predicates.
If you are reading line-wise, it is helpful to use library(readutil).
You can always fall back to using input/output primitives, but this is very tedious and usually unnecessary.
Once you are done reading, you can convert to atoms or lists of one-char atoms, or maybe strings. Keep in mind that if you decide to use strings, you will be stuck with SWI-Prolog (at least for the time being), but you'll be able to use some nifty predicates for reading directly from streams to strings.
Reading and writing means you need to open and close files. You also have immediate access to the standard input and output streams with the aliases user_input
, user_output
, etc. These, or the streams/files you have opened, are the arguments to many of the reading and writing predicates linked above.
Now, a small example: to read a file, and collect each line in a list of character codes, using library(readutil)
:
file_to_lines(Filename, Lines) :-
setup_call_cleanup(
open(Filename, read, In),
stream_to_lines(In, Lines),
close(In)
).
stream_to_lines(In, Lines) :-
read_line_to_codes(In, Codes),
stream_to_lines_rest(Codes, In, Lines).
stream_to_lines_rest(end_of_file, _In, []) :- !.
stream_to_lines_rest(This, In, [This|Rest]) :-
read_line_to_codes(In, Next),
stream_to_lines_rest(Next, In, Rest).
If you save this in a file called rf.pl
:
?- [rf].
true.
?- file_to_lines('rf.pl', Lines), forall(member(L, Lines), format("~s~n", [L])).
file_to_lines(Filename, Lines) :-
setup_call_cleanup(
open(Filename, read, In),
stream_to_lines(In, Lines),
close(In)
).
stream_to_lines(In, Lines) :-
read_line_to_codes(In, Codes),
stream_to_lines_rest(Codes, In, Lines).
stream_to_lines_rest(end_of_file, _In, []) :- !.
stream_to_lines_rest(This, In, [This|Rest]) :-
read_line_to_codes(In, Next),
stream_to_lines_rest(Next, In, Rest).
Lines = [[102, 105, 108, 101, 95, 116, 111, 95|...], [32, 32, 32, 32, 115, 101, 116|...], [32, 32, 32, 32, 32, 32|...], [32, 32, 32, 32, 32|...], [32, 32, 32, 32|...], [32, 32, 32|...], [], [115|...], [...|...]|...].