鲁班编程语言 文件读写,网络传输及解释器使用指南(转)
http://project.soft114.com/lubankit/index_chinese.html
9. 输入输出对象类型及部件
Men have become the tools of their tools.
- Henry David Thoreau
在鲁班软件包里包括一些常用的对象类型和部件用于文件和网络的数据输入和输出. 虽然严格说来这些常用工具并不是鲁班语言的组成部分, 就象printf函数不是C语言的一部分一样. 但是所有C语言的书都会讲printf. 我们在这里也专用一章讲这些实用的类型和部件.
9.1 终端, 文件和网络SOCKET
这三个对象类型都用于数据输入输出, 而且它们的界面基本一样. 以下讲述它们的应用细节及举例.
鲁班类型名:
终端: std::console
文件: std::file
网络Socket: net::socket
以上三个对象类型共同的成员函数列举如下.
write(obj1,obj2…)
将对象逐个转化成字符串然后印出或传出
返回空值null, 如果操作失败则返回错误类型
writeline(obj1,obj2…)
将对象逐个转化成字符串然后印出或传出, 每个对象后附加一个换行符.
返回空值null, 如果操作失败则返回错误类型
read( int n=1 )
读入指定数量(n)的字符. 如果n没有指定则读一个字符.
返回读取的字符串. 如果操作失败则返回错误类型.
readline()
逐个读取字符一直到碰到一个换行符.
返回读取的字符串. 如果操作失败则返回错误类型.
writeobj(obj1,obj2…)
将对象逐个转化成独立于硬件及操作系统的串行流然后写出或传出
返回空值null, 如果操作失败则返回错误类型
readobj()
读取串行流内容, 并将串行流恢复成数据对象. 一般情况是串行流是
以前的writeobj操作产生.返回所恢复的数据对象.
一般来说, write和writeline用来把对象写成字符串显示来给人读. 而writeobj和readobj用来在程序或机器之间传递数据. 不管简单或复杂的数据对象, 鲁班语言保证用writeobj写出的对象一定可以用readobj来读回来. 而且写和读可以在不同的程序甚至机器上.
9.2 文件读写举例
一个一般文字处理的例子:
linecount = 0;
wordcount = 0;
txtfile = std::file(“mydatafile”, ‘r’); // 打开一个叫”mydatafile”的文件
alldata = txtfile.readall(); // 读取全部文件内容到alldata变量
lines = alldata.split(‘ ’); // 将alldata分行到变量lines
foreach( line in lines ) // 枚举在lines里的每一行
{
++linecount; //增加行数
words = line.split(); // 将每行分成单词数组words
wordcount += words.size(); // 增加单词数
}
//下面打印结果
std::println(obj=”lines: “+string(linecount)+” words:“+string(wordcount));
以上程序打开一个叫”mydatafile”的文件, 将文件全部内容读到一个叫”alldata”的变量里. 然后将内容分行, 将每行再分成单词, 数行数和单词数. 最后将结果打印在屏幕上. 请注意以上代码用了一个新的成员函数readall()这个函数一次将文件的所有内容读出成一个字符串返回.
下面例子代码演示怎样将数据对象以串行流格式写入文件, 然后怎样再从文件恢复数据对象.
fw = std::file(“objfile”, ‘w’); // 打开文件准备写
fw.writeobj([1,2,3]); // 一次将一个数组转化成串行流写入文件
fw.close(); // 关闭文件
fr = std::file(“objfile”, ‘r’); // 打开文件准备读
vec = fr.readobj(); // 将以前写入的数组串行流读出并恢复成对象
std::println(obj=vec); // 打印 [1,2,3]
一个文件可以用三种状态打开, 读状态, 写状态和添加状态, 分别由三个字符’r’, ‘w’, ‘a’ 表示. 读状态只能打开已经存在的文件. 试图用读状态打开一个不存在的文件会返回错误. 写状态会创建文件, 如果文件已经存在, 其内容会被清除. 添加状态也会创建文件, 但如果文件已经存在, 其内容不会被清除, 新的内容被添加到文件尾.
9.3 网络读写举例
以下鲁班例子代码演示怎样使用网络SOCKET来实现一个简单的客户-服务器之间的数据传输. 以下例子使用了一个新的数据类型net::listener. 这个数据类型用于网络通讯的服务器一边. net::listener的对象创建时的输入参数是一个TCP端口号.它的主要成员函数是accept(). 这个成员函数会在TCP端口等待客户从网络上来的连接请求, 收到后返回一个net::socket对象. 用这个SOCKET对象就可以象读写文件那样和客户对话.
服务器脚本:
// 此服务器问候客户并告状客户排号是第几
listener = net::listener(6500); // 服务器的TCP端口号是6500
clientcount=0;
while( true ) // 循环
{
socket = listener.accept(); // 等待接收新的客户连接
name = socket.readobj(); // 读客户名字
socket.writeobj(“Hello, ”+name); // 问侯客户
++clientcount; // 序号加一
socket.writeobj(clientcount); // 将序号送给客户
}
客户脚本:
socket = net::socket(“localhost”, 6500); // 连接服务器端口6500
socket.writeobj(“Chinese”); // 告诉服务器自己名字
msg = socket.readobj(); // 接收服务器发的问候
std::console().writeline(“The server says: “, msg); // 打印问候
mynumber = socket.readobj(); //接收服务器发的序号
std::console().writeline(“My number is “, mynumber); // 打印序号
以上两个鲁班程序, 一个是服务器程序, 一个是客户程序. 服务器程序打开一个TCP端口6500, 然后等待客户连接. 收到连接后先读客户送来的名字, 然后发送问候字符串, 最后将客户连接的序号发给客户. 客户程序的读写顺序则相反. 客户先创建一个SOCKET连接到服务器的6500 TCP端口. 然后将自己名字发给服务器. 再读问候字符串并打印出来. 最后读服务器发来的序号也打印出来.
这个例子程序里服务器和客户在同一个机器上运行. 在客户程序里写的服务器名字是”localhost”. 运行时先启动服务器程序, 然后启动客户程序. 如果服务器和客户在不同的机器上, 只需修改客户程序, 将”localhost”改为服务器机器的名字就好.
9.4 标准屏幕打印部件: std::println std::print
为了客户方便, 鲁班软件包包括标准打印部件std::println std::print 这两个部件把输入的对象打印到屏幕上. 它们都是用鲁班语言写成. 内部用的是std::console 对象类型. 以下是它们的源代码.
namespace std;
struct println( input obj;)
as process
{ std::console().writeline(input.obj); }
struct print( input obj;)
as process
{ std::console().write(input.obj); }
9.5 标准对象恢复部件std::des
所有的鲁班数据对象或部件都可以转换成串行流字符串. std::des是鲁班的一个标准部件用来从串行流字符串恢复原来的数据对象. 以下是代码例子.
x = {“one”:1, “two”:2}; //创建一个字典对象
xguts = x.serialize();// 转换成串行流字符串
xback = std::des(stream=xguts).obj; // 调用std::des恢复对象
truth = xback == x; // truth = true
以上代码创建一个字典对象然后转换成串行流字符串, 再调用std::des部件来从串行流恢复原来的对象. 最后比较恢复的对象和原本对象看它们是否一样.
12. 鲁班命令行解释器使用说明
Simplicity in character, in manners, in style;
in all things the supreme excellence is simplicity.
- Henry Wadsworth Longfellow
鲁班代码是用鲁班命令行解释器来启动解释执行. 鲁班命令行解释器可以从文件里读鲁班源程序并解释执行. 鲁班命令行解释器也可以接受从操作系统命令行来的短鲁班脚本, 或者接受用户当时打入的鲁班代码立即执行并显示结果.
12.1 运行鲁班程序文件
运行鲁班脚本文件很简单, 只需要将脚本文件名放在命令行即可. 鲁班解释器会按它们在命令行的顺序逐个运行. 就如如下举例.
在文件 saygood.lbn 里写入如下鲁班代码:
std::println(obj=”World is good”);
在文件 saybad.lbn 里写入如下鲁班代码:
std::println(obj=”World is bad”);
然后在你的操作系统命令行启动鲁班解释器运行这两个鲁班脚本文件.
Mycomputer > luban saygood.lbn saybad.lbn
World is good
World is bad
上例子可以看出怎样运行鲁班脚本文件. 鲁班程序文件除了脚本文件外, 还有鲁班部件定义文件. 鲁班部件定义文件只定义部件, 但没有可立即执行的脚本代码. 部件的运行要由其他的脚本调用. 部件定义文件和脚本文件一样可以放在命令行由鲁班解释器读入并执行. 鲁班解释器会先处理所有的部件定义文件将部件登记到鲁班命名空间, 然后再解释执行脚本文件. 部件定义文件在命令行的顺序可以任意调换而不影响它们的处理. 如下是例子.
在文件 saygood.lbn 里写入如下鲁班代码:
namespace demo;
struct SayGood()
as process
{
std::println(obj=”World is good”);
}
在文件 saybad.lbn 里写入如下鲁班代码:
namespace demo;
struct SayBad()
as process
{
std::println(obj=”World is bad”);
}
在文件 start.lbn 里写入如下鲁班代码:
demo::SayGood(=);
demo::SayBad(=);
然后在你的操作系统命令行启动鲁班解释器运行这三个鲁班文件.
Mycomputer > luban saybad.lbn start.lbn saygood.lbn
World is good
World is bad
可以看出以上运行结果和上一个例子一样. 但是程序结构不同. 这个例子里有两个鲁班部件定义文件saygood.lbn和saybad.lbn. 这两个文件定义了两个部件 demo::SayGood 和 demo::SayBad. 可真正启动执行这两个鲁班部件的是叫start.lbn的鲁班脚本文件.
从上面命令行的鲁班文件顺序saygood.lbn, start.lbn, saybad.lbn 可以看出一是鲁班部件文件的顺序不是执行顺序, 二是部件文件总是先得处理, 所以脚本文件start.lbn虽然在部件文件saygood.lbn 之前, 它还是能够调用saygood.lbn所定义的部件demo::SayGood.
另外需要指出的是, 在鲁班解释器的命令行, 鲁班部件定义文件的顺序可以任意排列, 不用考虑它们之间的有互相依赖关系. 鲁班解释器会自动处理.
12.2 交互式执行鲁班脚本或部件定义程序
打入以下命令会启动鲁班解释器进入交互式状态.
Mycomputer > luban –i
6 imported types
script/s - to start scripting
edit/e - to edit script using $EDITOR or vi
list/l - to browse name space
quit/q - to quit
Luban> _
-i参数会让解释器进入交互状态. 在交互状态, 你可以用打入鲁班程序, 查看鲁班名字空间内容或者启动编辑器编辑鲁班程序(BETA1.2或更高). 以下是举例说明.
Mycomputer > luban –i
> list std
std::console std::console
std::deserializer std::deserializer
std::file std::file
std::print std::print(input readwrite obj;)
std::des std::des(input readwrite string stream;output readonly obj;)
std::printline std::printline(input readwrite obj;)
std::println std::printline(input readwrite obj;)
以上例子用了”list”命令来查看鲁班名字空间里的’std”子空间的内容. 鲁班解释器列举了所有”std”含有的数据类型和部件类型.
Mycomputer > luban –i
Luban > script
std::console().writeline(“Hello, world”);
ESCENTER
Hello, world
以上例子用了”script”命令来打入鲁班脚本程序并执行. 敲ESC键然后ENTER会让鲁班解释器接受你打入的鲁班脚本程序并执行. 上例的脚本程序简单在屏幕上打印”Hello, world”.
Mycomputer > luban –i
Luban > edit
如果你用鲁班BETA1.2或更高, 以上命令会启动一个外部编辑器来编辑鲁班程序并执行. 你可以用环境变量”EDITOR”来指明你想用的外部编辑器. 比如:
Mycomputer > export EDITOR=xemacs
如果没有指定的外部编辑器, 鲁班会用”vi”. 如果不能启动外部编辑器, 鲁班会报错. 还有需要指出的是, “edit”功能只在Linux和有Cygwin安装的WINDOWS上使用. 如果你只安装了鲁班的WINDOWS执行文件包没有安装CYGWIN, “edit”功能不工作.
12.3 其他命令行参数
-s 参数, 可以用来在命令行直接输入鲁班程序. 如下例:
Mycomputer > luban –s “std::console().writeline(100);”
100
如果命令行里有其他鲁班程序文件. -s 参数里的程序会在鲁班程序文件处理后执行.
-t 参数, 指定数据类型定义文件名
鲁班软件包有一个鲁班数据类型定义文件”imports”里面含有鲁班的外部数据类型和它们对应的函数库文件名. 如有必要, 你可以用自己的数据类型定义文件, 只需要用-t参数告状鲁班它的名字. 如下例:
Mycomputer > luban –t myimports
http://project.soft114.com/lubankit/index_chinese.html
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10797429/viewspace-101673/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/10797429/viewspace-101673/