2011-01-25 22 views
72

在大多數編程語言中,用於處理文件的流程是open-close-close,這是常識。然而,我看到了許多次紅寶石碼無與倫比File.open調用,而且我發現在Ruby文檔this gem of knowledgeRuby的File.open和f.close的需要

我當他們是由垃圾收集器聲稱/ O流自動關閉。

darkredandyellow友好IRC就此問題:
[17:12]是的,而且,文件描述符的數量通常是由OS
[17:29]我認爲你可以限制容易用完之前的可用文件描述符垃圾收集器清理。在這種情況下,您可能想要自己關閉它們。 「垃圾收集者聲稱。」意味着GC在未來的某個時刻起作用。而且很昂貴。很多明確關閉文件的原因。

  1. 我們需要明確地關閉
  2. 如果是,那麼爲什麼用GC自動關閉?
  3. 如果不是那麼爲什麼選項?
+0

你的「常識」已經過時,因爲析構函數被髮明。 – meagar

+1

@meager:破壞者是什麼時候發明的? –

+0

只需注意:雖然文件描述符是有限的,但至少在Linux上,限制相當高。 – Linuxios

回答

109

我看到了無與倫比的File.open電話

紅寶石代碼很多時候你能舉個例子嗎?我只能看到,在新手編寫的代碼中,缺少「在大多數編程語言中用於處理文件的流程是開放使用關閉」的常識。

有經驗的Rubyist要麼明確地關閉他們的文件,要麼更習慣地使用File.open的塊形式,它會自動爲你關閉文件。它的實現基本如下所示:

def File.open(*args, &block) 
    return open_with_block(*args, &block) if block_given? 
    open_without_block(*args) 
end 

def File.open_without_block(*args) 
    # do whatever ... 
end 

def File.open_with_block(*args) 
    yield f = open_without_block(*args) 
ensure 
    f.close 
end 

腳本是一種特殊情況。腳本通常運行得如此之短,並且使用如此之少的文件描述符,以至於無法關閉它們,因爲操作系統在腳本退出時將會關閉它們。

我們是否需要明確關閉?

是的。

如果是,那麼爲什麼用GC自動關閉?

因爲收集完對象之後,就沒有辦法讓你關閉文件了,因此你會泄漏文件描述符。

請注意,這不是垃圾收集器關閉文件。垃圾收集器只是在收集對象之前執行任何對象的終結器。恰巧File類定義了一個關閉文件的終結器。

如果沒有,那麼爲什麼選擇?

因爲浪費的內存很便宜,但浪費的文件描述符不是。因此,將文件描述符的生存期與某些內存塊的生命週期相關聯是沒有意義的。

你根本無法預測垃圾收集器將運行。你甚至不能預測如果它會不惜一切運行:如果你從來沒有用完的內存,垃圾收集器將永遠不會運行,因此終結永遠不會運行,因此該文件將永遠不會被關閉。

+1

https://github.com/isaac/sunspot/blob/cell/sunspot/lib/sunspot/rich_document.rb +23(雖然它的內核#打開並主要用於它的HTTP端,但我用它來達到它本地文件路徑參數,儘管如此......;我仍然試圖找到補丁和請求拉的時間),https://github.com/jnicklas/carrierwave Ctrl + f「File.open」(它給出的例子,但以一種不好的方式......)以及其他幾個我不記得的地方。因爲我的項目中的穩定性要求,我有一個問題的牛肉。 – clyfe

+3

在這個例子中,應該提高在救援塊?如果調用raise並且沒有異常,這是不是會引發運行時錯誤? –

+0

@JeffStorey:很好! 17個月未被注意... –

0
  1. 如果你不這樣做,或者有一些其他故障
  2. 請參閱第2
61

你應該使用後一直關閉的文件描述符,這也將沖洗它。通常人們使用File.open或具有塊的等效方法來處理文件描述符的生存期。例如:

File.open('foo', 'w') do |f| 
    f.write "bar" 
end 

在該示例中,文件自動關閉。

+0

好點。我跟蹤了一個沒有調用File.close的腳本。因此,現在和以後某些文件中最後一行會丟失。 –

+0

傑出。我從來不知道這個伎倆。很像java-8在這方面。謝謝。 – sagneta

0

我們可以使用File.read()函數讀取紅寶石文件..... 如,

file_variable = File.read("index.html") 
在這個例子中 file_variable

可以有該文件的全部價值....

0

http://ruby-doc.org/core-2.1.4/File.html#method-c-open

沒有關聯塊,File.open是::新的代名詞。如果 可選代碼塊給定,它將被打開的文件作爲參數傳遞 並在文件對象將自動塊 終止時被關閉。該塊的值將從File.open返回。

因此,當塊終止將自動關閉:d