Io 将两个文件收集到另一个文件

Io 将两个文件收集到另一个文件,io,prolog,swi-prolog,Io,Prolog,Swi Prolog,我有两个文件,file1.txt,file2.txt,我想在检查两个文件的行之后在file3.txt中收集它们 例如: file1.txt line 1 T line 2 F line 3 T line 4 T line 5 F line 6 F line 1 T line 2 T line 3 F line 4 T line 5 F line 6 T file1 *******************

我有两个文件,
file1.txt
file2.txt
,我想在检查两个文件的行之后在
file3.txt
中收集它们

例如:

file1.txt

line 1    T
line 2    F
line 3    T
line 4    T
line 5    F
line 6    F
line 1    T
line 2    T
line 3    F
line 4    T
line 5    F
line 6    T
    file1 
    ********************
    number of line  = 6
    number of true  = 3
    number of false = 3
    ********************
    line 1    T
    line 3    T
    line 4    T

    file2
    ********************
    number of line  = 6
    number of true  = 4
    number of false = 2
    ********************
    line 1    T
    line 2    T
    line 4    T
    line 6    T
file2.txt

line 1    T
line 2    F
line 3    T
line 4    T
line 5    F
line 6    F
line 1    T
line 2    T
line 3    F
line 4    T
line 5    F
line 6    T
    file1 
    ********************
    number of line  = 6
    number of true  = 3
    number of false = 3
    ********************
    line 1    T
    line 3    T
    line 4    T

    file2
    ********************
    number of line  = 6
    number of true  = 4
    number of false = 2
    ********************
    line 1    T
    line 2    T
    line 4    T
    line 6    T
file3.txt

line 1    T
line 2    F
line 3    T
line 4    T
line 5    F
line 6    F
line 1    T
line 2    T
line 3    F
line 4    T
line 5    F
line 6    T
    file1 
    ********************
    number of line  = 6
    number of true  = 3
    number of false = 3
    ********************
    line 1    T
    line 3    T
    line 4    T

    file2
    ********************
    number of line  = 6
    number of true  = 4
    number of false = 2
    ********************
    line 1    T
    line 2    T
    line 4    T
    line 6    T
对于每个文件,生成的文件应包含一个标题,显示行数、为真的行数(
T
)和为假的行数(
F
)。接下来只打印正确的行


有什么帮助吗?

您可以按如下方式执行此操作。我们首先定义一个谓词
merge/2
,第一项是必须读取的文件名列表(此处
[file1.txt,file2.txt]
),第二个参数是要写入的文件名(此处
file3.txt
)。现在我们将
merge/2
定义为:

merge(Inp,Outp) :-
    open(Outp,write,Outs),
    mergeS(Inp,Outs).
因此,我们打开一个名为
Outp
的文件,并获取相应的流
Outs
,然后调用
mergeS/2

合并/2有两种情况:

  • 所有输入文件都已处理,因此我们可以停止处理并关闭流:

    mergeS([],OutS) :-
        close(OutS).
    
  • 我们至少需要处理一个文件:

    mergeS([H|T],OutS) :-
        open(H,read,InS),
        atom_chars(FileN,H),
        process(FileN,InS,OutS),
        close(InS),
        mergeS(T,OutS).
    
    这个谓词的核心显然是
    process/3
    ,但是为了使事情更方便。我们已经在
    mergeS
    中进行了文件处理

接下来,我们的
进程/3
谓词如下:

process(Header,InS,OutS) :-
    get_lines(InS,Lin,NL,NT,NF),
    write(OutS,Header),nl(OutS),
    write(OutS,'********************'),nl(OutS),
    write(OutS,'number of line  = '),write(OutS,NL),nl(OutS),
    write(OutS,'number of true  = '),write(OutS,NT),nl(OutS),
    write(OutS,'number of false = '),write(OutS,NF),nl(OutS),
    write(OutS,'********************'),nl(OutS),
    print_lines(OutS,Lin),
    nl(OutS).
我们首先使用
get\u lines/5
收集文件内容。该谓词将同时计算统计信息,如行数、True数和false数。接下来,我们使用大量的
write/2
nl/1
语句将统计信息写入输出文件,然后使用谓词
print\u lines/2
,将文件内容写入
file3.txt

获取线路
获取线路

get_line/5
使用三个累加器计算统计数据。这是通过初始化三个累加器,然后调用
get\u lines/8

get_lines(Ins,Lin,NL,NT,NF) :-
    get_lines(Ins,Lin,0,0,0,NL,NT,NF).
get_lines/8
是一个递归函数,一次处理一行,确定该行是
T
还是
F
,更新累加器,并解析下一行。然而,我们有可能得到一个空文件。为了使我们的方法更加稳健,我们这样写道:

get_lines(InS,[],NL,NT,NF,NL,NT,NF) :-
    at_end_of_stream(InS),
    !.
以及递归情况:

get_lines(InS,[H|T],NL0,NT0,NF0,NL,NT,NF) :-
    get_line(InS,HCs),
    inspect(HCs,NL0,NT0,NF0,NL1,NT1,NF1),
    atom_chars(H,HCs),
    get_lines(InS,T,NL1,NT1,NF1,NL,NT,NF).
get_line/2
只需读取文件的下一行,并返回一个字符流。它终止于
'\n'
(包括在内,但不在结果中)

检查/7

现在我们仍然需要使用
inspect/7
检查我们的生产线。我们再次使用三个累加器(根据
get\u lines/8
的实现,您可能已经猜到了)。首先,我们获取行的最后一个字符。如果不存在这样的字符,统计信息就不会改变(可能在某个地方引入了空行)。否则,我们使用
last/2
获取最后一个字符,并使用
inspect\u last/7
检查它:

inspect(L,NL0,NT0,NF0,NL,NT,NF) :-
    last(L,LL),
    !,
    NL is NL0+1,
    inspect_last(LL,NT0,NF0,NT,NF).
inspect(_,NL0,NT,NF,NL1,NT,NF) :-
    !,
    NL1 is NL0+1.
get_lines(InS,[],NL,NT,NF,NL,NT,NF) :- at_end_of_stream(InS), !. get_lines(InS,Res,NL0,NT0,NF0,NL,NT,NF) :- get_line(InS,HCs), inspect(HCs,NL0,NT0,NF0,NL1,NT1,NF1), atom_chars(H,HCs), ( NT1 > NT0 -> Res =[H|T] ; Res = T ), get_lines(InS,T,NL1,NT1,NF1,NL,NT,NF).
inspect\u last
确定最后一个字符是
T
F
还是其他字符,并相应地更新累加器:

inspect_last('T',NT0,NF,NT1,NF) :-
    !,
    NT1 is NT0+1.
inspect_last('F',NT,NF0,NT,NF1) :-
    !,
    NF1 is NF0+1.
inspect_last(_,NT,NF,NT,NF).
打印行/2

最后,我们仍然需要将文件打印到输出。这是使用非常简单的
打印行/2
完成的:

print_lines(_,[]) :-
    !.
print_lines(OutS,[H|T]) :-
    write(OutS,H),
    nl(OutS),
    print_lines(OutS,T).
完整代码 完整代码:

merge(Inp,Outp) :-
    open(Outp,write,Outs),
    mergeS(Inp,Outs).

mergeS([],OutS) :-
    close(OutS).

mergeS([H|T],OutS) :-
    open(H,read,InS),
    atom_chars(FileN,H),
    process(FileN,InS,OutS),
    close(InS),
    mergeS(T,OutS).

process(Header,InS,OutS) :-
    get_lines(InS,Lin,NL,NT,NF),
    write(OutS,Header),nl(OutS),
    write(OutS,'********************'),nl(OutS),
    write(OutS,'number of line  = '),write(OutS,NL),nl(OutS),
    write(OutS,'number of true  = '),write(OutS,NT),nl(OutS),
    write(OutS,'number of false = '),write(OutS,NF),nl(OutS),
    write(OutS,'********************'),nl(OutS),
    print_lines(OutS,Lin),
    nl(OutS).

get_lines(Ins,Lin,NL,NT,NF) :-
    get_lines(Ins,Lin,0,0,0,NL,NT,NF).

get_lines(InS,[],NL,NT,NF,NL,NT,NF) :-
    at_end_of_stream(InS),
    !.
get_lines(InS,[H|T],NL0,NT0,NF0,NL,NT,NF) :-
    get_line(InS,HCs),
    inspect(HCs,NL0,NT0,NF0,NL1,NT1,NF1),
    atom_chars(H,HCs),
    get_lines(InS,T,NL1,NT1,NF1,NL,NT,NF).

get_line(InS,[]) :-
    at_end_of_stream(InS),
    !.
get_line(InS,[H|T]) :-
    get_char(InS,H),
    H \= '\n',
    !,
    get_line(InS,T).
get_line(_,[]).

inspect(L,NL0,NT0,NF0,NL,NT,NF) :-
    last(L,LL),
    !,
    NL is NL0+1,
    inspect_last(LL,NT0,NF0,NT,NF).
inspect(_,NL0,NT,NF,NL1,NT,NF) :-
    !,
    NL1 is NL0+1.

inspect_last('T',NT0,NF,NT1,NF) :-
    !,
    NT1 is NT0+1.
inspect_last('F',NT,NF0,NT,NF1) :-
    !,
    NF1 is NF0+1.
inspect_last(_,NT,NF,NT,NF).

print_lines(_,[]) :-
    !.
print_lines(OutS,[H|T]) :-
    write(OutS,H),
    nl(OutS),
    print_lines(OutS,T).
如果现在有人提出疑问:

?- merge(["file1.txt","file2.txt"],"file3.txt").
true.
名为
file3.txt
的文件由以下内容构成:

file1.txt
********************
number of line  = 6
number of true  = 3
number of false = 3
********************
line 1    T
line 2    F
line 3    T
line 4    T
line 5    F
line 6    F

file2.txt
********************
number of line  = 6
number of true  = 4
number of false = 2
********************
line 1    T
line 2    T
line 3    F
line 4    T
line 5    F
line 6    T
这或多或少是你想要的。如果出现进一步的错误,请发表评论

编辑

不知怎的,我没有明白你想过滤这些行,只显示那些是真的(
t
)。只需修改
获取行/7
即可:

inspect(L,NL0,NT0,NF0,NL,NT,NF) :-
    last(L,LL),
    !,
    NL is NL0+1,
    inspect_last(LL,NT0,NF0,NT,NF).
inspect(_,NL0,NT,NF,NL1,NT,NF) :-
    !,
    NL1 is NL0+1.
get_lines(InS,[],NL,NT,NF,NL,NT,NF) :- at_end_of_stream(InS), !. get_lines(InS,Res,NL0,NT0,NF0,NL,NT,NF) :- get_line(InS,HCs), inspect(HCs,NL0,NT0,NF0,NL1,NT1,NF1), atom_chars(H,HCs), ( NT1 > NT0 -> Res =[H|T] ; Res = T ), get_lines(InS,T,NL1,NT1,NF1,NL,NT,NF).
这里有一个粗略的草图,让您开始使用和

我们采用相关问题“”中my@mat定义的
行//1
。使用,然后我们写:

?- set_prolog_flag(double_quotes , codes), set_prolog_flag(toplevel_print_anon, false). true. ?- phrase_from_file(lines(_Ls), 'file1.txt'), maplist(reverse, _Ls, _Rs), tpartition(prefix_of_t("T"), _Rs, _Ts0, _Fs), maplist(reverse, _Ts0, _Ts), forall(member(X,_Ts), format('~s~n',[X])). line 1 T line 3 T line 4 T true. ?-(,代码), 设置prolog标志(顶层打印,false)。 对。 ?-((_Ls),“file1.txt”), (,_Ls,_Rs), (“T”)、“Rs”、“Ts0”、“Fs), 地图列表(反向,_Ts0,_Ts), ((X,_Ts),('~s~n',[X])。 1号线T 3号线T 4号线T 对。
F
T
将始终是行中的最后一个字符?是的,但保留空白并不重要。行本身是“T”、“F”等,还是“第1t行”、“第2f行”等?@WillemVanOnsem,Boris,到目前为止,我所做的是实现一个谓词
文件到列表(文件,列表)
结果:列表=['line-1-T','line-2-F,…]@AnsPiter:你想缩进
file3
还是打字错误?我有个问题:
merge(['file1','file2','file3')!权限错误:无法打开文件'c:/users/coper/file3'!不可写!目标:open(file3,write,_201)
@AnsPiter:这本身就说明了问题:不知何故,你的操作系统阻止了对该目录的访问。我不知道如何为Windows解决这个问题:Linux只运行了7年。@Willem Van Onsem thnx无论如何,我会安装它linux@AnsPiter:文件是否已存在?可能是您的操作系统阻止了文件被覆盖。。@WWillem Van Onsem file.txt或prolog(SPIDER plugin)中的相同文件?它与PDT eclipse(SWI)一起工作,但到目前为止,我必须使用SICStus prologSWI。它比SICStus好吗?@AnsPiter。两者都有优点和缺点,所以我的答案是双重的:(1)这取决于。(2)YMMV!:)我认为这在很大程度上取决于库的精髓,所以RMV。