Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

精通 Ruby StringIO:理解功能與實際應用

你在找一個表現得像 IO 物件(檔案、socket 等)但可以像字串一樣控制的物件嗎?

那麼 StringIO 就是為你準備的。

讓我展示一些例子和要注意的事項!

基本範例

建立 StringIO 物件可以這樣做:

io = StringIO.new("abc") 

然後你可以用 gets, read, each_line 等方法從這個物件讀取。

我為你做了一個方便的表格,列出最有用的方法:

Method Description
gets 讀取一行輸入
read 讀取特定位元組數(預設全讀)
each_line 給定區塊,逐行迭代
each_char 給定區塊,逐字元迭代
<< 附加資料
rewind 重設內部位置指標
string 從 stringio 物件回傳實際字串

注意 StringIO 有位置指標。

這個指標追蹤你讀了多少位元組,就像檔案物件一樣。

所以每次呼叫 gets 或 read 之類的方法,它會給你那麼多資料並推進指標。

甚至 Enumerable 方法像 map 或 each_line 也會推進位置指標,記住這點。

io.each_line { |line| puts line } 

你可以用 rewind 方法將位置指標重設到開頭:

io.pos # 45 io.rewind io.pos # 0 

這就是基本部分。

我要展示一些 StringIO 的實際用途,但先讓我展示另一件事。

那 StringScanner 呢?

現在你看過 StringIO 能做什麼,但 Ruby 標準函式庫還有另一個字串相關的類別。

那個類別是 StringScanner。

它可能會讓人困惑,因為名字和方法相似,但讓我幫你看出差別。

主要重點是這個:

StringIO 物件可以取代另一個 IO 物件(如 File 或 Socket),但 StringScanner 是為了做解析(將文字拆解成一組 tokens)這類事。

這兩個類別除了名字都有「String」,還共用一樣東西:它們都使用內部 位置指標。

替換標準輸入與輸出

假設你在寫命令列應用程式,用 Kernel#gets 詢問使用者輸出……

……如果你想測試這段代碼,你每次都得手動輸入。

所以自動化測試不可能了?

不,不是!

這就是 StringIO 派上用場的地方。你可以用測試輸入初始化 StringIO 物件,然後取代 $stdin 指向的標準輸入物件(Ruby 在你呼叫 gets 時會看這裡找使用者輸入)。

例子:

io = StringIO.new("input") $stdin = io gets # input 

這項技術也可以用來捕獲 puts 等方法的輸出。

顯示方法列印到預設輸出裝置,稱為「標準輸出」。在 Ruby 中這是用 IO 物件表示,你可以用你的 StringIO 物件取代它。

例子:

io = StringIO.new("") $stdout = io # 列印到 $stdout puts "Jesus Castello is from Spain & likes to help people learn Ruby." # 還原原始值 $stdout = STDOUT io.rewind io.read # "Jesus Castello is from Spain & likes to help people learn Ruby." 

這比輸入版本複雜,因為我們要確保還原原始 STDOUT 物件並 rewind 我們的 StringIO 以便讀取輸出。

注意大多數測試框架包含做這事的方法(Minitest 的 assert_output 和 RSpec 的 output matcher),但知道背後發生什麼總是很棒 🙂

總結

你學到了 StringIO 類別,它模擬真實的 IO 物件,所以可以作為那種物件的替代品。

這對測試寫入螢幕輸出或需要透過終端機使用者輸入的類別很有用。

如果你知道 StringIO 的有趣用法在留言告訴我們,別忘了 分享這篇 文章讓更多人享受!