Read a file line by line in Prolog

后端 未结 3 1991

I\'d like to read a plain text file and apply a predicate to each line (the predicates contain write which does the output). How would I do that?

相关标签:
3条回答
  • 2020-11-29 09:42

    There are kind of more possible in number and more reasonable in performance solutions, to get uninterpreted i.e plain text lines from a file:

    SWI-Prolog:

    read_line(S, X) :- 
       read_line_to_codes(S, L), 
       read_line2(L, X).
    
    read_line2(end_of_file, _) :- !, fail.
    read_line2(L, X) :-
       atom_codes(X, L).
    

    Jekejeke Prolog:

    :- use_module(library(stream/console)).
    

    Here are some timings, reading a file of 655 lines:

    test :-
       open('<path>', read, Stream),
       test(Stream),
       close(Stream).
    
    test(Stream) :-
       read_line(Stream, _), !,
       test(Stream).
    test(_).
    

    SWI-Prolog:

    ̀?- time((between(1,100,_), test, fail; true)).
    % 328,300 inferences, 0.125 CPU in 0.143 seconds (88% CPU, 2626400 Lips)
    true.
    

    Jekejeke Prolog:

    ?- time((between(1,100,_), test, fail; true)).
    % Up 121 ms, GC 2 ms, Thread Cpu 94 ms (Current 05/07/19 17:19:05)
    Yes
    

    I guess a SWI-Prolog solution that reads into a string instead into an atom could be faster. But in the above we compare atom against atom reading.

    0 讨论(0)
  • 2020-11-29 09:57

    In SWI-Prolog, the cleanest solution is to write a DCG that describes what a "line" is, then call a predicate for each line. Use library(pio) to apply the DCG to a file.

    EDIT: As requested, consider:

    :- use_module(library(pio)).
    
    lines([])           --> call(eos), !.
    lines([Line|Lines]) --> line(Line), lines(Lines).
    
    eos([], []).
    
    line([])     --> ( "\n" ; call(eos) ), !.
    line([L|Ls]) --> [L], line(Ls).
    

    Sample usage: ?- phrase_from_file(lines(Ls), 'your_file.txt').

    0 讨论(0)
  • 2020-11-29 10:00

    You can use read to read the stream. Remember to invoke at_end_of_stream to ensure no syntax errors.

    Example:

    readFile.pl

    main :-
        open('myFile.txt', read, Str),
        read_file(Str,Lines),
        close(Str),
        write(Lines), nl.
    
    read_file(Stream,[]) :-
        at_end_of_stream(Stream).
    
    read_file(Stream,[X|L]) :-
        \+ at_end_of_stream(Stream),
        read(Stream,X),
        read_file(Stream,L).
    

    myFile.txt

    'line 0'.
    'line 1'.
    'line 2'.
    'line 3'.
    'line 4'.
    'line 5'.
    'line 6'.
    'line 7'.
    'line 8'.
    'line 9'.
    

    Thus by invoking main you will recieve the output:

    ?- main.
    [line 0,line 1,line 2,line 3,line 4,line 5,line 6,line 7,line 8,line 9]
    true 
    

    Just configure main. The output here is an example by using write, of course. Configure to match your request.

    I assume that this principle can be applied to answer your question. Good luck.

    0 讨论(0)
提交回复
热议问题