gets pobiera pojedyncza linie danych ze standardowego wejscia,readlines czyta wszystkie linie, dopoki nie napotka terminatora (EOF - End Of File, na przyklad Ctrl+D). Napotkawszy EOF, zwraca linie w tablicy.File.open("text.txt").each { |line| puts line } File.new("text.txt", "r").each { |line| puts line }
Obydwa polecenia otwieraja plik do odczytu (File.open - domyslnie, File.new poprzez “r”). Ponadto File.open moze przyjac blok kodu, a gdy dzialanie tego sie zakonczy, zamknie plik, co nie dzieje sie w przypadku drugiej metody (trzeba skorzystac z metody close).
File.open("text.txt") do |f| puts f.gets end f = File.new("text.txt", "r") puts f.gets f.close
Korzystajac z pierwszej opcji, mamy szybki i prosty sposob na przeprowadzenie operacji w pojedynczej lokalizacji. W drugim przypadku, udostepniamy referencje szerszej “publice”.
each_byte wczytuje strumien bajt po bajcie. Otrzymujemy wtedy pojedyncze wartosci bajtow a nie znaki. Aby przekonwertowac je na znaki, mozna skorzystac z metody chr.each_char wczytuje strumien znak po znaku. Jest to przydatne, gdy korzystamy z zestawu znakow, w ktorych niektore znaki przedstawiane sa za pomoca wiecej niz jednego bajta.read(6) wczytuje 6 bajtow z pliku.File posiada wiele przydatnych metod do szybkiej obslugi plikow:data = File.read(filename) otwiera plik, uzywa metody read i zamyka go.array_of_lines = File.readlines(filename).pos pokazuje, w ktorym miejscu w pliku sie znajdujemy.pos= umieszcza wskaznik w danym miejscu (f.pos = 8)# writing.rb File.open("test.txt", "w") do |f| f.puts "This is a test" end
Output:
sqbell@sqbell-gentoo ~/ruby/beginning_ruby/ch09_files_db $ cat test.txt This is a test
| Tryby | Wlasnosci |
|---|---|
r | Tylko do odczytu, wskaznik na poczatku pliku |
r+ | Odczyt i zapis, wskaznik na poczatku pliku |
w | Tylko zapis, nowy plik jest tworzony (istniejace sa zastepowane) |
w+ | Zapis i odczyt, File.new tworzy nowy plik (istniejacy jest zastepowany) |
a | Zapis w trybie dolaczania do pliku, wskaznik jest umieszczony na koncu pliku |
a+ | Zapis i odczyt w trybie dolaczania, wskaznik umieszczony jest na koncu pliku |
b | Tryb binarny, do odczytu plikow nietekstowych |
# logging.rb f = File.new("logfile", "a") f.puts Time.now f.close
Output:
sqbell@sqbell-gentoo ~/ruby/beginning_ruby/ch09_files_db $ cat logfile 2011-05-06 13:10:29 +0200 2011-05-06 13:10:30 +0200 2011-05-06 13:10:31 +0200 2011-05-06 13:10:32 +0200
File.rename(“file1”, “file2”) zmienia nazwe pliku.File.delete(“file”) lub File.unlink(“file”) usuwa plik.File.join('full', 'path', 'to', 'a', 'file.txt') generuje sciezke dostepu.File.expand_path(“file”) wyswietli absolutna sciezke do pliku.puts “It exists!” if File.exist?(“file”) sprawdzi czy plik istnieje.puts File.size(“file”) wyswietli rozmiar pliku.W systemach UNIXowych mamy dwa rodzaje blokad: współdzielona (shared) i na wyłączność ((exclusive). Druga może być w posiadaniu tylko przez jeden proces. Procesy współdzielące plik muszą najpierw zwlonić blokadę, by proces, który chce posiadać plik na wyłączność będzie mógł taką założyć. Przykład w Rubym:
#!/usr/bin/env ruby -wKU File.open("/tmp/foo", "w") do |f| f.flock(File::LOCK_EX) f.puts "Something clever..." f.flock(File::LOCK_UN) end
Dir.chdir(“/usr/bin”) zmienia katalog,Dir.pwd wyswietla obecny katalog,Dir.entries(“/usr/bin”) zwroci tablice zawartosci katalogu,Dir.foreach(“/usr/bin”) dziala podobnie, ale jest iteratorem,Dir[“/usr/bin/*”] wyswietli liste podkatalogow,Dir["**/**"] wyświetli wszystkie pliki i katalogi w obecnym katalogu, rekursywnie,Dir.mkdir(“newdir”) tworzy katalog,Dir.delete(“newdir”) usuwa katalog, podobnie jak Dir.unlink i Dir.rmdir.Wiekszosc systemow operacyjnych posiada katalogi, w ktorych programy moga przechowywac tymczasowe dane.
# tmp_dir.rb require 'tmpdir' puts Dir.tmpdir tempfilename = File.join(Dir.tmpdir, "myapp.dat") tempfile = File.new(tempfilename, "w") tempfile.puts "This is only temporary." tempfile.close File.delete(tempfilename) # poprzez biblioteke tempfile require 'tempfile' f = Tempfile.new('myapp') f.puts "Hello" puts f.path f.close
Output:
/tmp /tmp/myapp20110506-5927-3wba79
Aby okreslic kodowanie wczytywanego pliku, dodajemy je do trybu pliku po dwukropku.
File.new("text.txt", "r:utf-8").each { |line| puts line }
Aby sprawdzic “zewnetrzne” kodowanie jakiegokolwiek obiektu I/O, skorzystac mozemy z metody external_encoding.
# ext_encoding.rb puts File.open("logfile", "r:utf-8").external_encoding puts File.open("logfile", "r").external_encoding
Output:
UTF-8 UTF-8
Mozna transkodowac wejscie z jednego kodowania w drugie:
# transcoding.rb File.open("text.txt", "r:utf-8:iso-8859-2") do |f| puts f.external_encoding first_line = f.gets puts first_line.encoding end
Output:
UTF-8 ISO-8859-2
Wlasnosc ta jest przydatna gdy chcemy w calym programie korzystac z jednego kodowania (na przyklad utf-8) ale pliki wejsciowe mamy w innym.
# csv.rb require 'csv' CSV.open('text.txt', 'r').each do |person| puts person.inspect end
Output:
["Fred Bloggs", "Manager", "Male", "45"] ["Laura Smith", "Cook", "Female", "23"] ["Debbie Watts", "Professor", "Female", "38"]
PStore umozliwia zapisywanie obiektow i struktur danych do pliku i ladowania ich z powrotem. Takie operacje zwane sa object persistence i opieraja sie na technice zwanej marshalling, gdzie struktury sa splaszczane.
# pstore.rb class Person attr_accessor :name, :job, :gender, :age end fred = Person.new fred.name = "Fred Bloggs" fred.age = 45 laura = Person.new laura.name = "Laura Palmer" laura.age = 23 require 'pstore' store = PStore.new("storagefile") store.transaction do store[:people] ||= Array.new store[:people] << fred store[:people] << laura end
||= upewniamy sie, ze element :people znajduje sie w danej 'przechowalni'. Nastepnie dodajemy do niego freda i laure («) i konczymy transakcje.# pstore_read.rb class Person attr_accessor :name, :job, :gender, :age end require 'pstore' store = PStore.new("storagefile") people = [] store.transaction do people = store[:people] end people.each do |person| puts person.name end
Output:
Fred Bloggs Laura Palmer
# yaml.rb require 'yaml' class Person attr_accessor :name, :age end fred = Person.new fred.name = "Fred Bloggs" fred.age = 45 laura = Person.new laura.name = "Laura Smith" laura.age = 23 test_data = [ fred, laura ] puts YAML::dump(test_data)
Output:
--- - !ruby/object:Person age: 45 name: Fred Bloggs - !ruby/object:Person age: 23 name: Laura Smith
Wczytywanie:
# yaml_read.rb require 'yaml' class Person attr_accessor :name, :age end yaml_string = <<END_OF_DATA --- - !ruby/object:Person age: 45 name: Fred Bloggs - !ruby/object:Person age: 23 name: Laura Smith END_OF_DATA test_data = YAML::load(yaml_string) puts test_data[0].name puts test_data[1].name
Output:
Fred Bloggs Laura Smith
# sqlite.rb require 'rubygems' require 'sqlite3' $db = SQLite3::Database.new("dbfile") # $ - zmienna globalna $db.results_as_hash = true # wymusza zwracanie wynikow jako hasha def disconnect_and_quit $db.close puts "Bye!" exit end def create_table puts "Creating 'people' table" $db.execute %q{CREATE TABLE people ( id integer primary key, name varchar(50), job varchar(50), gender varchar(6), age integer) } end def add_person puts "Enter name: " name = gets.chomp puts "Enter job: " job = gets.chomp puts "Enter gender: " gender = gets.chomp puts "Enter age: " age = gets.chomp $db.execute("INSERT INTO people (name, job, gender, age) VALUES (?, ?, ?, ?)", name, job, gender, age) end def find_person puts "Enter name or ID of person to find: " id = gets.chomp person = $db.execute("SELECT * FROM people WHERE name = ? OR id = ?", id, id.to_i).first unless person puts "No result found." return end puts %Q{Name: #{person['name']} Job: #{person['job']} Gender: #{person['gender']} Age: #{person['age']} } end
# mysql.rb require 'rubygems' require 'mysql' db = Mysql.connect('localhost', 'root', 'test') db.query("INSERT INTO people (name, age) VALUES('Chris', 25)") begin query = db.query('SELECT * FROM people') puts "There were #{query.num_rows} rows returned." query.each_hash do |h| puts h.inspect end rescue puts db.errno puts db.error end db.close
DBI (The DataBase Interface) to proba utworzenia jednego interfejsu do porozumiewania sie z roznymi bazami danych.
# dbi.rb require 'dbi' db = DBI.connect('DBI:Mysql:db_name', 'username', 'password') db.do("INSERT INTO people (name, age) VALUES (?, ?)", name, age) query = db.prepare('SELECT * FROM people') query.execute while row = query.fetch do puts row.inspect end query.finish db.select_all('SELECT * FROM people') do |row| puts row.inspect end