Learn Prolog Now 翻译 - 第十二章 - 文件相关操作 - 第二节, 文件的读写

从文件中读取内容



本节将学习如何从文件中读取内容。如果文件中的内容是以Prolog的语句形式存在的,那么在Prolog中读取这样的文件内容是很容易的。比如文件houses.txt的内容如下:

gryffindor.
hufflepuff.
ravenclaw.
slytherin.

下面是Prolog打开文件,读取内容,并且将内容显示在屏幕上的代码:

main :-
    open('houses.txt', read, Str),
    read(Str, House1),
    read(Str, House2),
    read(Str, House3),
    read(Str, House4),
    close(Str),
    write([House1, House2, House3, House4]), nl.

上面代码将会以只读模式打开文件,然后使用Prolog内置谓词read/2读取Prolog语句,然后关闭流,最后打印信息到屏幕上去。

这种方式是很直接和简单的。但是,read/2谓词需要谨慎地使用。首先,它只能处理Prolog的语句(我们将会在后面讨论更多这方面的内容),第二,如果流没有任何内容了,它可能会导致运行时错误。有没有一种更加优雅的方式可以克服第二个问题呢?

当然有的。内置谓词at_end_of_stream/1能够检查stream是否已经到达了尾端,而且是以一种安全的方式进行使用。对于一个流X,at_end_of_stream(X)当流X已经到达了其尾端时为真(换种说法,文件中所有的语句都已经被读取了)。

下面的代码是经过修改后的版本,展示了如何使用at_end_of_stream/1这个谓词:

main :-
    open('houses.txt', read, Str),
    read_houses(Str, Houses),
    close(Str),
    write(Houses), nl.

read_houses(Stream, []) :-
    at_end_of_stream(Stream).

read_houses(Stream, [X|L]) :-
    \+ at_end_of_stream(Stream),
    read(Stream, X),
    read_houses(Stream, L).

现在来解决更加麻烦的问题。上面提及read/2只能读取Prolog语句。如果你想要读取任意文件内容,情况可能会变得比较复杂,因为Prolog会迫使读入的内容以字符级别来进行,内置的谓词get_code/2从流中读取下一个存在的字符。字符在Prolog中是使用其整数数字来代替的。比如,get_code/2将会在流中读取字符a,然后返回结果是97。

通常,我们不会关心这些整数,而是关心字符本身——或者,由这些字符组成的列表,来表示的原子。我们如何处理这些字符呢?一种方式是使用内置谓词atom_codes/2,可以将整数列表转换为对应的原子。我们将使用下一个例子介绍这种方式,例子展示了如何从流中读取单词:

readWord(InStream, W) :-
    get_code(InStream, Char),
    checkCharAndReadRest(Char, Chars, InStream),
    atom_codes(W, Chars).

checkCharAndReadRest(10, [], _) :- !.
checkCharAndReadRest(32, [], _) :- !.
checkCharAndReadRest(-1, [], _) :- !.
checkCharAndReadRest(end_of_file, [], _) :- !.
checkCharAndReadRest(Char, [Char|Chars], InStream) :-
    get_code(InStream, NextChar),
    checkCharAndReadRest(NextChar, Chars, InStream).

代码是如何工作的?它读取一个字符然后检查这个字符是否是空白(整数为32),是否为分行符(整数为10),或者是流的结尾(整数为-1),以上任意一种情况下都会被当成一个完整单词的结束,否则的话下一个字符将会进行读取。


将内容写入文件



许多的应用程序都需要将输出写入到文件中进行保存,而不仅仅是显示在屏幕上。本节我们将学习如何在Prolog中将输出内容写入到文件中。

为了写文件,我们必须创建一个(或者打开一个)文件并且将一个流与其相关联。你可以认为流就是文件的连接。在Prolog中,流的表现形式很不友好,名字都是类似“$stream(1833680)”这样可读性很差的。幸运的是,你不会直接使用流的名字,虽然Prolog在内部为其分配了名字,你可以通过使用Prolog的合一去匹配流名字和一个变量,然后使用变量操作流,而不是Prolog中内部分配给流的名字。

如果你想要输出字符串“Hogwarts”到文件hogwarts.txt中,可以这么做:

...
open('hogwarts.txt', write, Stream),
write(Stream, 'Hogwarts'), nl(Stream),
close(Stream),
...

如何理解上面的代码?首先,内置的谓词open/3将会创建新的文件:hogwarts.txt;open/3的第二个参数指出我们想要打开一个新的文件(或者覆盖任何已经存在的,相同名字的文件);open/3的第三个参数返回流的名字。其次,我们将“Hogwarts”写入到流中,并且加入新的一行。最后,我们使用内置谓词close/1关闭掉流。

这就是写文件的操作。正如之前承诺的,我们对流的名字不感兴趣——我们使用合一的变量操作流。还有需要注意的是,谓词write/2是一个更加基础的版本,因为在第九章中使用了write/1将内容输出到屏幕。

如果你不希望复写已经存在的文件,而是在已经存在的文件中添加新的内容呢?可以选择打开文件的方式(不再是write方式)来做到,使用append作为open/3的第二个参数。如果给定名字的文件还不存在,这种模式将会创建一个新的文件。

posted on 2015-08-10 13:33  seaman.kingfall 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/seaman-h-zhang/p/4717157.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值