Làm thế nào để viết vào tập tin trong Ruby?


572

Tôi cần đọc dữ liệu ra khỏi cơ sở dữ liệu và sau đó lưu nó vào một tệp văn bản.

Làm thế nào tôi có thể làm điều đó trong Ruby? Có bất kỳ hệ thống quản lý tập tin trong Ruby?

Câu trả lời:


179

Lớp Ruby File sẽ cung cấp cho bạn thông tin chi tiết ::new::opennhưng lớp cha của nó, lớp IO , sẽ đi sâu vào #read#write.


6
Cảm ơn @Geoff. Thật tốt khi thấy người dùng mới dọn dẹp các câu hỏi và câu trả lời lỗi thời. Làm cho một trang web tổng thể tốt hơn.
jdl

7
Tôi thấy điều này thật mỉa mai. Câu trả lời là tài liệu rất tốt ... nhưng bây giờ một năm sau, câu hỏi này là câu hỏi đầu tiên trên Google. Khi câu hỏi được đặt ra, có vẻ như OP đã dành rất ít nỗ lực nhưng bây giờ theo như Google có liên quan, đây là nguồn tốt nhất.
Jeff

7
Có lẽ bởi vì tất cả mọi thứ bạn thực sự cần biết là ở đây. Của tôi là câu trả lời "dạy một người đàn ông câu cá" cho những người muốn đọc các chi tiết tốt hơn, và có rất nhiều câu trả lời "cho một người một con cá" ở đây cũng cho những người chỉ muốn cắt và dán. Không có gì đáng ngạc nhiên khi sự kết hợp này kết thúc được xếp hạng tốt trên Google.
jdl

1
Vì vậy, công bằng mà nói, tôi làm việc với rất nhiều ngôn ngữ khác nhau, điều đó có nghĩa là tôi hiếm khi loanh quanh để nhớ cú pháp cho bất kỳ ngôn ngữ cụ thể nào. Tôi đã googled điều này một vài lần và tôi luôn cuộn qua câu trả lời này, đến câu hỏi bên dưới, bởi vì khi tôi google StackOverflow tôi thường chỉ tìm kiếm một con cá dang. : p Thành thật tho nó tốt cả hai. Có lẽ một ngày nào đó tôi sẽ làm đủ Ruby ngay lập tức mà tôi sẽ quan tâm đến các chi tiết.
user435779

2
Điều này không trả lời câu hỏi. Nó chỉ trỏ đến hai lớp có chứa hầu hết các phương thức để thực hiện I / O và không đề cập đến kết nối với cơ sở dữ liệu. Điều đó sẽ tốt như một bình luận, nhưng hầu như không đủ điều kiện như một câu trả lời. Tôi nhận ra rằng OP và nhiều độc giả đã phản đối câu trả lời này không đồng ý và tôi thực sự không hiểu họ đang nghĩ gì.
Cary Swoveland

929

Bạn đang tìm kiếm sau đây?

File.open(yourfile, 'w') { |file| file.write("your text") }

8
yourfilelà một biến chứa tên của tệp sẽ được viết.
B Bảy

17
Ngoài ra: f = File.open ('name', 'w'); f.write ('văn bản'); f.close
Vish

5
@vish: Tôi sẽ không đề xuất giải pháp này vì bộ mô tả tệp sẽ bị bỏ ngỏ nếu f.writetăng Ngoại lệ.
nbarraille

288
Ngắn gọn và ngọt ngào:File.write('filename', 'content')
Benjamin Oakes

14
Thậm chí ngắn hơn và được ghi lại:IO.write('filename', 'content')
Thái

636

Bạn có thể sử dụng phiên bản ngắn:

File.write('/path/to/file', 'Some glorious content')

Nó trả về độ dài được viết; xem :: viết để biết thêm chi tiết và các tùy chọn.

Để thêm vào tệp, nếu nó đã tồn tại, sử dụng:

File.write('/path/to/file', 'Some glorious content', mode: 'a')

14
FYI phương pháp tốc ký này chỉ hoạt động bắt đầu với Ruby 1.9.3. Không có phương pháp nào như vậy trong bất kỳ phiên bản 1.9 hoặc 1.8 nào trước đó. Trong trường hợp đó, bạn phải sử dụng phương thức chặn dài hơn được đăng bởi @mvndaai
Andrew Burns

13
FYI này đóng đúng tập tin khi hoàn thành.
Freedom_Ben

2
Các tài liệu lớp IO nói rằng nó đóng tệp
nruth

7
Điều này sẽ nối vào một tập tin hoặc chỉ ghi đè lên nó?
Joshua Pinter

8
@JoshPinter: nó ghi đè.
mkuity0

248

Đây là cách tiếp cận ưa thích trong hầu hết các trường hợp:

 File.open(yourfile, 'w') { |file| file.write("your text") }

Khi một khối được truyền đến File.open, đối tượng Tệp sẽ tự động đóng khi khối kết thúc.

Nếu bạn không chuyển một khối tới File.open, bạn phải đảm bảo rằng tệp được đóng chính xác và nội dung được ghi vào tệp.

begin
  file = File.open("/tmp/some_file", "w")
  file.write("your text") 
rescue IOError => e
  #some error occur, dir not writable etc.
ensure
  file.close unless file.nil?
end

Bạn có thể tìm thấy nó trong tài liệu :

static VALUE rb_io_s_open(int argc, VALUE *argv, VALUE klass)
{
    VALUE io = rb_class_new_instance(argc, argv, klass);
    if (rb_block_given_p()) {
        return rb_ensure(rb_yield, io, io_close, io);
    }
    return io;
}

Có, sử dụng cú pháp khối với {| file | ....} sẽ đóng tệp khi khối đóng.
wesgarrison

Tuyệt thật, cảm ơn nhé. Tôi không chắc về điều đó. Dưới đây là một số thông tin khác về các khối và File.open blog.rubybestpractices.com/posts/rklemme/, nó cũng được đề cập trong tài liệu chính thức
Tombart

1
Chỉ cần một cái gì đó ruby ​​way-ish: nil là một đối tượng, vì vậy để kiểm tra xem một tập tin có phải là null không, bạn hãy tự hỏi đối tượng đó thay vì so sánh (file.nil? Thay vì tập tin == nil)
JCabello

@JCabello chắc chắn, đó chắc chắn là cách tiếp cận giống Ruby hơn, cảm ơn!
Tombart

cuối cùng một câu trả lời cho thấy rằng người ta cũng nên kiểm tra trạng thái tệp và cách xử lý nó, và không chỉ một lớp lót chỉ hiển thị cuộc gọi mở.
Nasser

115

Câu trả lời của Zambri được tìm thấy ở đây là tốt nhất.

File.open("out.txt", '<OPTION>') {|f| f.write("write your stuff here") }

lựa chọn của bạn <OPTION>là:

r- Chỉ đọc. Các tập tin phải tồn tại.

w - Tạo một tập tin trống để viết.

a - Nối vào một tệp. Tệp được tạo nếu nó không tồn tại.

r+- Mở một tệp để cập nhật cả đọc và viết. Các tập tin phải tồn tại.

w+ - Tạo một tập tin trống cho cả đọc và viết.

a+- Mở một tập tin để đọc và nối thêm. Các tập tin được tạo ra nếu nó không tồn tại.

Trong trường hợp của bạn, wlà thích hợp hơn.


Tôi loạng choạng rằng một câu trả lời thừa nhận sao chép câu trả lời khác có thể nhận được hơn 100 lượt upvote. Tôi có thể thấy việc đăng câu đầu tiên như một bình luận cho câu hỏi, nhưng đó là nó.
Cary Swoveland

@CarySwoveland Tôi thực sự đồng ý với bạn. Vấn đề thực sự là một trong hai câu hỏi nên được đánh dấu là trùng lặp từ lâu. Tôi đã sao chép câu trả lời vì một khi tôi tìm thấy câu hỏi mà zanbri đã trả lời và vài lần tiếp theo khi tôi cần thông tin tương tự, tôi đã bắt gặp câu hỏi này trước tiên và phải tìm ra cách để đến câu hỏi khác. Cuối cùng, tôi nghĩ sẽ dễ dàng hơn khi có câu trả lời của anh ấy ở đây. Tôi liên kết với câu trả lời của anh ấy để hy vọng, mọi người sẽ nhấp vào và đưa cho anh ấy một upvote.
mvndaai

31

Đối với những người trong chúng ta học bằng ví dụ ...

Viết văn bản vào một tệp như thế này:

IO.write('/tmp/msg.txt', 'hi')

TIỀN THƯỞNG THÔNG TIN ...

Đọc lại như thế này

IO.read('/tmp/msg.txt')

Thường xuyên, tôi muốn đọc một tập tin vào clipboard của mình ***

Clipboard.copy IO.read('/tmp/msg.txt')

Và những lần khác, tôi muốn viết những gì trong clipboard của mình vào một tệp ***

IO.write('/tmp/msg.txt', Clipboard.paste)

*** Giả sử bạn đã cài đặt gem gem

Xem: https://rubygems.org/gems/clipboard


1
Coi chừng IO.writetùy chọn ghi đè lên nội dung tệp thay vì nối thêm. Nối với IO.write là một chút tẻ nhạt.
fguillen 2/11/2016

Không chắc chắn những gì bạn đang nói về? Lệnh IO.write không cần tùy chọn đó để ghi vào tệp. Tôi sẽ cẩn thận để lưu tệp vào thư mục / tmp hoặc thư mục hiện tại; Mặt khác, bạn có thể thấy một Errno::ENOENT: No such file or directory @ rb_sysopenthông báo và tệp được tạo với kích thước 0 byte.
l3x

25

Để hủy nội dung trước đó của tệp, sau đó viết một chuỗi mới vào tệp:

open('myfile.txt', 'w') { |f| f << "some text or data structures..." } 

Để thêm vào một tập tin mà không ghi đè lên nội dung cũ của nó:

open('myfile.txt', "a") { |f| f << 'I am appended string' } 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.