Как записать в файл в Ruby?


572

Мне нужно прочитать данные из базы данных, а затем сохранить их в текстовом файле.

Как я могу сделать это в Ruby? Есть ли в Ruby система управления файлами?

Ответы:


179

Рубиновый класс файла даст вам все входы и выходы ::newи , ::openно его родитель, класс IO , попадет в глубину #readи #write.


6
Спасибо @Geoff. Приятно видеть, как новые пользователи убирают устаревшие вопросы и ответы. Делает для лучшего сайта в целом.
2012 года

7
Я нахожу это ироничным. Ответ очень хорошо задокументирован ... но сейчас, год спустя, этот вопрос является первым хитом в Google. Когда был задан вопрос, могло показаться, что OP потратил немного усилий, но сейчас, что касается Google, это лучший источник.
Джефф

7
Вероятно, потому что все, что вам действительно нужно знать, здесь. Мой ответ «научить человека ловить рыбу» для тех, кто хочет прочитать более мелкие детали, и здесь есть множество ответов «дай человеку рыбу», а также для тех, кто просто хочет вырезать и вставить. Неудивительно, что эта комбинация оказалась в рейтинге Google.
2013 года

1
Так что, честно говоря, я работаю на множестве разных языков, что означает, что я редко могу вспомнить синтаксис для какого-то конкретного. Я гуглил это несколько раз, и я всегда прокручиваю сразу после этого ответа до ответа ниже, потому что, когда я гуглю StackOverflow, я обычно просто ищу чертову рыбу. Честно говоря, хорошо, когда есть и то, и другое. Возможно, когда-нибудь я буду делать достаточно Ruby сразу, чтобы позаботиться о деталях.
user435779

2
Это не отвечает на вопрос. Он просто указывает на два класса, которые содержат большинство методов для ввода / вывода, и не упоминает о связи с базой данных. Это было бы хорошо, как комментарий, но вряд ли можно квалифицировать как ответ. Я понимаю, что ОП и многие читатели, которые проголосовали за этот ответ, не согласны, и я, честно говоря, не понимаю, о чем они думали.
Кэри Свовеланд

929

Вы ищете следующее?

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

8
yourfileпеременная, которая содержит имя файла для записи.
B Семь

17
В качестве альтернативы: f = File.open ('name', 'w'); f.write ( 'текст'); f.close
виш

5
@vish: я бы не рекомендовал это решение, так как дескриптор файла был бы оставлен открытым, если возникнет f.writeисключение.
nbarraille

289
Коротко и сладко:File.write('filename', 'content')
Бенджамин Оукс

14
Еще короче и задокументировано:IO.write('filename', 'content')
Thai

636

Вы можете использовать короткую версию:

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

Возвращает написанную длину; смотрите :: написать для более подробной информации и опций.

Чтобы добавить файл, если он уже существует, используйте:

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

14
К вашему сведению, этот сокращенный метод работает только начиная с Ruby 1.9.3. В более ранних версиях 1.9 или 1.8 такого метода нет. В этом случае вы должны использовать метод более длинного блока, опубликованный @mvndaai
Эндрю Бернс

13
К вашему сведению, это правильно закрывает файл, когда закончите.
Freedom_Ben

2
Документы IO class говорят, что закрывают файл
nruth

7
Будет ли это добавить в файл или просто перезаписать его?
Джошуа Пинтер

8
@JoshPinter: это перезаписывает.
mklement0

248

Это предпочтительный подход в большинстве случаев:

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

Когда блок передается File.open, объект File будет автоматически закрыт после его завершения.

Если вы не передаете блок в File.open, вы должны убедиться, что файл правильно закрыт и содержимое было записано в файл.

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

Вы можете найти это в документации :

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;
}

Да, используя синтаксис блока с {| file | ....} закроет файл, когда блок закроется.
Весгаррисон

Хорошо, спасибо. Я не был уверен в этом. Вот еще немного информации о блоках и File.open blog.rubybestpractices.com/posts/rklemme/… это также упоминается в официальной документации
Tombart

1
Просто что-то ruby ​​way-ish: nil - это объект, поэтому, чтобы проверить, является ли файл нулевым, вы спрашиваете сам объект вместо сравнения (file.nil? Вместо file == nil)
JCabello

@JCabello, конечно, это более подход, похожий на Ruby, спасибо!
Томбарт

наконец, ответ, который показывает, что нужно также проверять состояние файла и как с ним обращаться, а не только один лайнер, который просто показывает открытый вызов.
Насер

115

Найденный здесь ответ Замбри самый лучший.

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

где ваши варианты для <OPTION>:

r- Только для чтения. Файл должен существовать.

w - Создать пустой файл для записи.

a - Добавить в файл. Файл создается, если он не существует.

r+- Откройте файл для обновления и чтения и записи. Файл должен существовать.

w+ - Создать пустой файл для чтения и записи.

a+- Откройте файл для чтения и добавления. Файл создается, если он не существует.

В вашем случае wэто предпочтительнее.


Я поражен, что ответ, который по общему признанию копирует другой ответ, может получить более 100 голосов. Я вижу публикацию первого предложения в качестве комментария к вопросу, но это все.
Кэри Свовеланд

@CarySwoveland Я действительно согласен с вами. Реальная проблема заключается в том, что один из двух вопросов давно должен был быть помечен как дубликат. Я скопировал ответ, потому что, как только я нашел вопрос, на который ответил Занбри, и в следующие несколько раз, когда мне понадобилась та же информация, я сначала наткнулся на этот вопрос и должен был выяснить, как добраться до другого вопроса. В конце концов, я подумал, что будет проще получить его ответ и здесь. Я надеялся, что я связался с его ответом, что люди кликнули бы и дали ему голос.
mvndaai

31

Для тех из нас, кто учится на примере ...

Запишите текст в файл следующим образом:

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

БОНУСНАЯ ИНФОРМАЦИЯ ...

Прочитайте это обратно, как это

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

Часто я хочу прочитать файл в буфер обмена ***

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

И в других случаях я хочу написать, что в моем буфере обмена в файл ***

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

*** Предполагается, что у вас установлен гем буфера обмена

Смотрите: https://rubygems.org/gems/clipboard


1
Остерегайтесь IO.writeопции перезаписывать содержимое файла вместо добавления. Добавить с IO.write немного утомительно.
fguillen

Не уверен, о чем ты говоришь? Команде IO.write не нужна эта опция для записи в файл. Я хотел бы сохранить файл в каталоге / tmp или в текущем каталоге; В противном случае вы можете увидеть Errno::ENOENT: No such file or directory @ rb_sysopenсообщение и файл, созданный с размером 0 байт.
13

25

Чтобы уничтожить предыдущее содержимое файла, запишите в него новую строку:

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

Чтобы добавить файл без перезаписи его старого содержимого:

open('myfile.txt', "a") { |f| f << 'I am appended string' } 
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.