Câu hỏi File.open của Ruby và sự cần thiết của f.close


Đó là kiến ​​thức phổ biến trong hầu hết các ngôn ngữ lập trình mà dòng chảy để làm việc với các tập tin được mở-sử dụng-đóng. Tuy nhiên, tôi đã thấy nhiều lần trong mã ruby ​​chưa từng có File.open cuộc gọi, và hơn nữa tôi tìm thấy đá quý kiến ​​thức này trong tài liệu ruby:

Các luồng I / O được tự động đóng lại khi chúng được yêu cầu bởi bộ thu gom rác.

darkredandyellow irc thân thiện đưa ra vấn đề:
[17:12] vâng, và ngoài ra, số lượng các bộ mô tả tập tin thường bị giới hạn bởi hệ điều hành
[17:29] Tôi cho rằng bạn có thể dễ dàng chạy hết các bộ mô tả tập tin có sẵn trước bộ thu dọn rác dọn dẹp. trong trường hợp này, bạn có thể muốn tự mình sử dụng chúng. "tuyên bố bởi người thu gom rác." có nghĩa là GC hoạt động tại một số điểm trong tương lai. và nó đắt tiền. rất nhiều lý do để đóng tệp một cách rõ ràng.

  1. Chúng ta có cần đóng một cách rõ ràng không
  2. Nếu có thì tại sao GC tự động đóng?
  3. Nếu không thì tại sao lựa chọn?

76
2018-01-25 15:38


gốc


'Kiến thức chung' của bạn đã lỗi thời kể từ khi các destructors được phát minh. - meagar♦
@meager: Khi nào những người phá hủy được phát minh? - Andrew Grimm
Chỉ cần một lưu ý: Trong khi các bộ mô tả tập tin bị giới hạn, trên Linux ít nhất, giới hạn là khá cao. - Linuxios
@Linuxios: trên ubuntu12.04 của tôi $ ulimit -n => 1024 nó chỉ cao khi bạn làm một số công việc đơn giản. Thói quen xấu sẽ gây ra vấn đề lớn một ngày! - HVNSweeting


Các câu trả lời:


Tôi đã thấy nhiều lần trong các mã ruby ​​chưa từng có File.open cuộc gọi

Bạn có thể đưa ra một ví dụ không? Tôi chỉ thấy rằng trong mã được viết bởi những người mới thiếu sót "kiến thức phổ biến trong hầu hết các ngôn ngữ lập trình mà dòng chảy để làm việc với các tệp là mở-sử dụng-đóng".

Rubyists kinh nghiệm hoặc đóng một cách rõ ràng các tập tin của họ, hoặc, thành ngữ hơn, sử dụng dạng khối File.opensẽ tự động đóng tệp cho bạn. Việc thực hiện của nó về cơ bản trông giống như thế này:

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

Kịch bản là một trường hợp đặc biệt. Các tập lệnh thường chạy quá ngắn và sử dụng quá ít phần mô tả tệp mà đơn giản là không có ý nghĩa khi đóng chúng, vì hệ điều hành sẽ đóng chúng khi tập lệnh thoát.

Chúng ta có cần đóng một cách rõ ràng không?

Vâng.

Nếu có thì tại sao GC tự động đóng?

Bởi vì sau khi đã thu thập được đối tượng, không có cách nào để bạn đóng tệp nữa, và do đó bạn sẽ làm rò rỉ các bộ mô tả tệp.

Lưu ý rằng nó không phải là bộ thu gom rác đóng các tệp. Bộ thu gom rác đơn giản thực thi bất kỳ trình hoàn thành nào cho một đối tượng trước khi nó thu thập nó. Nó chỉ xảy ra là File class định nghĩa một finalizer để đóng file.

Nếu không thì tại sao lựa chọn?

Bởi vì bộ nhớ lãng phí là rẻ, nhưng các bộ mô tả tập tin lãng phí thì không. Vì vậy, nó không có ý nghĩa để gắn kết trọn đời của một bộ mô tả tập tin vào tuổi thọ của một số đoạn bộ nhớ.

Bạn chỉ đơn giản là không thể dự đoán khi nào bộ thu gom rác sẽ chạy. Bạn thậm chí không thể dự đoán nếu nó sẽ chạy ở tất cả: nếu bạn không bao giờ hết bộ nhớ, trình thu gom rác sẽ không bao giờ chạy, do đó trình hoàn thiện sẽ không bao giờ chạy, do đó tệp sẽ không bao giờ bị đóng.


113
2018-01-25 16:04



github.com/isaac/sunspot/blob/cell/sunspot/lib/sunspot/… +23 (mặc dù hạt nhân của nó mở và được sử dụng chủ yếu cho phía HTTP của nó, nhưng tôi đã đạt nó với một tham số đường dẫn tệp cục bộ, tuy nhiên ...; Tôi vẫn đang cố gắng tìm thời gian để vá và yêu cầu kéo), github.com/jnicklas/carrierwave Ctrl + f "File.open" (nó được đưa ra như là một ví dụ, nhưng trong một cách xấu ...), và một số nơi khác tôi không nhớ. Tôi có thịt bò với vấn đề này vì yêu cầu về độ ổn định trong các dự án của tôi .. - clyfe
Trong ví dụ này, nên tăng lên bên trong khối cứu hộ? Điều này sẽ không chỉ là một lỗi thời gian chạy nếu nâng cao được gọi là và không có ngoại lệ? - Jeff Storey
@ JeffStorey: đẹp bắt! 17 tháng không được chú ý… - Jörg W Mittag
@ JörgWMittag và bây giờ 17 tháng nữa không cố định: P Tôi đoán điểm chính ở đây là ensure, rescue và raise không cần thiết chút nào. - KL-7
Tôi nghĩ bạn không thể có ensure không có rescue. Và bạn không thể im lặng nuốt được ngoại lệ, bạn cần truyền bá nó cho người gọi, sau khi đóng tập tin. Dù sao, nhắc tôi lần nữa vào tháng Năm '15 :-D - Jörg W Mittag


Bạn nên luôn đóng các bộ mô tả tập tin sau khi sử dụng, nó cũng sẽ xóa nó. Thường thì mọi người sử dụng Mở tập tin hoặc phương pháp tương đương với các khối để xử lý thời gian mô tả tập tin. Ví dụ:

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

Trong ví dụ đó, tệp được đóng tự động.


62
2018-01-25 15:47



Điểm tốt. Tôi theo dõi một lỗi để một kịch bản mà không gọi File.close. Kết quả là dòng cuối cùng sẽ bị thiếu trong một số tệp ngay bây giờ. - Erwan Legrand
Nổi bật. Tôi chưa bao giờ biết mẹo này. Giống như java-8 trong lĩnh vực đó. Cảm ơn bạn. - sagneta


  1. Vâng
  2. Trong trường hợp bạn không, hoặc nếu có một số thất bại khác
  3. Xem 2.

1
2018-01-25 15:40





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

Không có khối liên kết, File.open là một từ đồng nghĩa cho :: new. Nếu   khối mã tùy chọn được đưa ra, nó sẽ được chuyển qua tệp đã mở dưới dạng đối số   và đối tượng Tệp sẽ tự động bị đóng khi chặn   chấm dứt. Giá trị của khối sẽ được trả về từ File.open.

Vì thế, sẽ tự động bị đóng khi chặn kết thúc : D


1
2018-05-26 17:31





Chúng ta có thể sử dụng File.read() chức năng để đọc các tập tin trong ruby ​​..... nhu la,

file_variable = File.read("index.html")

trong ví dụ này file_variable có thể có giá trị đầy đủ của tệp đó ....


-1
2018-01-10 12:09