歡迎您光臨本站 註冊首頁

魯班編程語言 文件讀寫,網路傳輸及解釋器使用指南

←手機掃碼閱讀     火星人 @ 2014-03-12 , reply:0
  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(『\n』); // 將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」);
ESC\ENTER
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




[火星人 ] 魯班編程語言 文件讀寫,網路傳輸及解釋器使用指南已經有508次圍觀

http://coctec.com/docs/program/show-post-71898.html