- Bir dosyayı açtıysak, kapatmamız lazım.
- Elle kapatmak yerine dosya işlemlerini bir blok içinde yapın.
- Dosya açma modunu gerektiği kadar verin.
Dosya açma modu, yazdığınız programın bir dosyayı açarken hangi amaçlarla kullanacağını belirttiği bir stringtir.
Bu modlar şunlardır:
Dosya Açma Modu | Kısa Açıklama | Uzun Açıklama |
---|---|---|
"r" |
Sadece Oku | Dosyayı sadece okunabilir olarak aç. Dosyanın başından itibaren sadece okuyabilecek (yazma işlemi yapamayacak) şekilde açmanızı sağlar.Herhangi bir mod belirtmezseniz dosya bu modda açılacaktır (varsayılan) |
"r+" |
Oku ve Yaz | Dosyayı hem okunabilir ve yazılabilir olacakşekilde açar. |
"w" |
Sadece Yaz | Dosyaya sadece yazma işlemi yapılabilir, içinden bilgi okunamaz. İçindeki mevcut bilgiler SİLİNİR! |
"w+" |
Yaz ve Oku | Dosyaya okuma ve yazma işlemi yapılır. Belirtilen dosya yoksa oluşturulur, varsa içindekiler SİLİNİR ve öyle düzenlenir. |
"a" |
Sonuna Yaz | Dosyanın sonuna ekleme yapılır. Belirtilen dosyayoksa oluşturulur, varsa,içindeki bilgiler korunarak en sona eklemeler yapılır. Okuma yapılamaz. |
"a+" |
Sondan Oku ve Yaz | Dosyanın sonundan itibaren okuma ve yazma işlemleri yapılır. Dosya yoksa oluşturulur, varsa sondan işlemler yapılmaya devam edilir. |
"b" |
Derlenmiş Dosya Modu | Derlenmiş yani işlemcinin anlayabileceğiikilik tabandaki komutlar haline çevrilmiş dosyalar için kullanılır. |
"t" |
Metin Dosyası Modu | Sadece metin içeren dosyalar için kullanılır. |
Ruby'de bulunduğunuz dizinde veya belirttiğiniz yoldaki bir dizinde yeni bir
dosya oluşturmak için File.new
fonksiyonu kullanılır.
Bu fonksiyonu çağırırken 2 tane parametre verilir.
Bunlar dosya adı ve dosyayı açma modudur.
Örnek kullanım:
File.new("dosya_adi", "w+")
# w+ modunda dosya yoksa oluşturulur ve dosyada okuma ve yazma işlemleri yapılabilir.
Yukarıdaki kodda sadece dosya oluşturuldu, ancak oluşturduğumuz dosyayı kullanamıyoruz.
Ayrıca dosyayı oluşturduk ancak kapatmadık, bu yüzden programımız çalıştığı sürece dosya da program tarafından kullanılıyor, yani bir diğer tabirle işgal ediliyor olacaktır.
Bunun önüne geçmek için 3 temel farklı yol izleyebiliriz.
Aşağıda 3 faklı senaryo için 3 farklı kullanım mevcuttur.
Ancak önce açtığımız bir dosyayı nasıl kapatacağımızı öğrenelim.
Ruby veya herhangi başka bir programlama dilinde bir program yazarken dosya işlemleri sırasında bir dosyayı kullanmak üzere açtıysanız işiniz bittiğinde o dosyayı kapatmanız gerekmektedir.
Eğer ki dosyayı açıp da kapatmadan bırakırsanız, programınız çalıştığı süre boyunca hard diskinizden (veya ilgili depolama aracından) dosya kullanılmaya devam edecektir. Bu da dosyayı başka programların açamamasına , açsa da üzerinde değişiklğik yapamamasına, harici bir çıkarılabilir diskte olması durumunda ise belleği güzenli çıkar işlemiyle çıkarmak istediğinizde kullanıcının "Bu disk kullanılıyor" tarzında hata almasına, eski işletim sistemine sahip cihazlarda bu işlem yapılırken çıkartılan çıkarılabilir diskin zarar görmesine kadar bir çok istenmeyen duruma neden olabilir.
Bu yüzden bir dosyayı açıyorsak mutlaka işimiz bittiğinde kapatmalıyız.
Kapatma işlemi .close
fonksiyonu ile yapılmaktadır.
Örnek kullanım
# Dosya açılmış ve "dosya" isimli değişkende tutulmakta olduğu varsayımıyla
dosya.close
Bu senaryoda sadece bilgisayarımızda bir dosya oluşturup, içine herhangi bir şey okuyup yazmayacağımızı varsayalım.
O halde dosyayı oluşturup, ruby programımızda kapatılmasını sağlayalım.
Burada herhangi bir ekstra değişken kullanmamak için Ruby'nin zincileme fonksiyon çağırma özelliğinden faydalanacağız.
Yapacağımız işlemler:
- Dosyayı oluştur
- Hiç bir şey yapmadan hemen kapat
Bu işleri yapan kodumuz şöyle olacaktır:
File.new("yeni_dosya.txt", "w").close
Yukarıdaki kodda yeni_dosya.txt
adında bir dosya w
moduyla açılmak üzere
oluşturulur. Hemen ardından ise oluşturulan dosyamız hiç bir işlem yapılmadan
kapatılır. Böylelikle ekstradan bir değişken de kullanmaya gerek kalmaz.
Bu senaryoda ise bilgisayarımızda bir dosya oluşturup, bu oluşturduğumuz dosyayı Ruby programımızda bir değişkende tutup, yine herhangi bir işlem yapmadan kapatma senaryosunu inceleyeceğiz.
Dosyamızı oluşturduktan sonra arada başka işlemler yapacaksak bu senaryoda anlatılan yöntemi kullanabiliriz ancak genelde 3. senaryoyu kullanmak daha uygun olacaktır.
Yapacağımız işlemler:
- Dosyayı oluştur
- Oluşturduğun dosyayı bir değişkende tut
- Arada başka işlemler yapacaksan yap
- Dosyayı kapat
dosya = File.new("yeni_dosya.txt", "w")
puts 'Dosya oluşturuldu ve hala açık'
dosya.close
puts 'Dosya kapatıldı'
Bu senaryoda ise dosyamızı oluştururken blok kullanımı yöntemine başvuracağız.
Bu yöntemde açtığınız dosyayı sonradan tekrardan elle kapatmanız gerekmiyor.
Eğer geçerli bir nedeniniz yoksa dosya işlemlerinde blok yöntemini kullanın!
Ancak File.new
fonksiyonu blok kullanımını desteklememektedir.
Bu yüzden dosya oluşturmaya yarayan File.new
yerine , asıl amacı dosya
okumak olan ancak dosya oluşturmada da çokça kullanılan File.open
fonksiyonunu kullanacağız.
File.open("yeni_dosya.txt", "w") do |dosya|
puts 'Dosyanız oluşturuldu ve hala açık'
end
puts 'Dosyanız otomatik olarak kapatıldı'
Bu yöntemde diğerlerinden farklı olarak File.new
yerine File.open
kullandık. Genel olarak pratik kullanımda File.new
den ziyade File.open
çok daha sıkça kullanılır.
Dosya işlemlerinde sıklıkla kullanılan işlemlerden birisi de dosya okumadır.
Varolan bir dosyanın içindekileri okumak için temel olarak seçebileceğimiz 2 farklı yol vardır.
Bu yollara değinmeden önce, küçük bir bilgilendirme yapalım.
Dosya okuma işlemlerini File.read
veya File.open
ile yapabiliriz.
Ancak burada amacımızı doğrudan açğıa vuran fonksiyon File.read
olduğu
için sadece dosya okuma işlemi yapacaksak File.open
yerine
File.read
fonksiyonunu tercih edelim. Hem bu şekilde dosya açma
modunu belirtmemize gerek de kalmayacaktır.
File.read("dosya_adi.txt")
Evet, az önce dosya okumanın 2 yolu olduğundan bahsetmiştik.Bunlar:
1 - Dosyanın tamamını okuyup bir stringe atama
2 - Dosyayı satır satır okuyup, her satırı diziye bir eleman olarak ekleme
Bu yöntemlerden hangisini kullanacağınız kullanım senaryonuza bağlıdır.
Örneğin bir dosyanın tümünde bir arama gerçekleştirecekseniz toplu halde okumak işinizi kolaylaştıracaktır.
Ancak bir kelimenin kaç satırda geçtiğini sayacaksanız da satır satır okumak işinizi çok daha kolaylaştıracaktır.
Gelin bu 2 yolu inceleyelim
Bu yöntemde dosyanın içindeki tüm bilgiler bir string olarak alınacaktır.
Alt satıra geçme elemanı olan \n
karakteri de stringin içinde yer alacaktır.
Örneğin isimler.txt
dosyamızın içeriği aşağıdaki gibi olsun.
durmuş hoca
serhat
taha
ömer
tunahan
Bu dosyayı okumak için File.read
fonksiyonunu aşağıdaki gibi kullanırız.
File.read("isimler.txt")
Bu komutun bize vereceği string ise şu şekildedir:
"durmuş hoca\nserhat\ntaha\nömer\ntunahan\n"
Okuduğumuz dosyanın içeriğini bir değişkene atayabiliriz.
dosya_icerigi = File.read("isimler.txt")
Artık bu değişkeni bir string olarak kullanabiliriz. Örneğin dosyanın içindeki tüm karakterlerin büyüğe çevrilmiş halini elde edebiliriz.
dosya_icerigi = File.read("isimler.txt")
dosya_icerigi.upcase
Türkçe karakterler dönüşüme uğramayacaktır.
"DURMUş HOCA\nSERHAT\nTAHA\nöMER\nTUNAHAN\n"
Gördüğünüz gibi satırlar \n
karakteriyle ayrılıyor.
Satır satır kullanmak için bu okuma yöntemi elverişli değil.
Çoğu zaman bir dosyanın tüm içeriğiyle değil, aynı anda sadece bir satırıyla ilgilenmek, bir satırı üerinde işlem yapmak isteriz.
Bu durumlar için ise File.readlines
fonksiyonunu kullanırız.
Örneğin yukarıdaki örnekteki isimler.txt
dosyasını bu sefer de
File.readlines
ile okursak
File.readlines("isimler.txt")
Bu işlem bize şu diziyi dönecektir:
["durmuş hoca\n", "serhat\n", "taha\n", "ömer\n", "tunahan\n"]
Gördüğünüz üzere bu fonksiyonun bize döndürdüğü değer bir String değil, Stringlerden oluşan bir dizi, yani string dizisidir.
Biz bu diziyi bir değişkene atayarak yada doğrudan döndüğü değer üzerinden bir döngü oluşturarak satırlar üzerinde gezinebiliriz.
satirlar = File.readlines("isimler.txt")
satirlar.each do |satir|
puts satir
end
Ekran çıktısı aşağıdaki gibi olacaktır:
durmuş hoca
serhat
taha
ömer
tunahan
Veya satır satır okuduğumuzu daha iyi anlamamıza yaracak bir örnek olarak her satırın uzunluğunu yazdıracak olursak:
satirlar = File.readlines("isimler.txt")
satirlar.each_with_index do |satir, i|
puts "#{i+1}. satırın uzunluğu: #{satir.length}"
end
Çıktısı aşağıdaki gibi olacaktır:
1. satırın uzunluğu: 12
2. satırın uzunluğu: 7
3. satırın uzunluğu: 5
4. satırın uzunluğu: 5
5. satırın uzunluğu: 8
Gördüğünüz gibi satır satır işlem yapmada işimizi oldukça kolaylaştırıyor.
Yukarıdakiyle aynı işlemleri yapan kodları arada herhangi bir ek değişken kullanmadan aşağıdaki gibi de yapabiliriz:
File.readlines("isimler.txt").each do |satir|
puts satir
end
durmuş hoca
serhat
taha
ömer
tunahan
Diğer örnek ise şu şekilde:
File.readlines("isimler.txt").each_with_index do |satir, i|
puts "#{i+1}. satırın uzunluğu: #{satir.length}"
end
Dosya okuma işlemlerini yaparken File.read
ve File.readlines
yerine
önce dosya açılıp daha sonra okuma işlemi de yapılabilir.
Örneğin dosyayı tümüyle okuyacaksak File.read
yerine
File.open("dosya_adi").read
kullanabiliriz.
Yine ayın şekilde, satır satır okuma yapacaksak File.readlines
yerine File.open("dosya_adi").readlines
fonksiyon zincirini kullanabiliriz.
Dosyaya yazmanında mantığı yine dosyayı açmaktan geçer.
Bu yüzden öncelikle dosyamızı yazılabilir modda açıp, ardından üzerinde istediğimiz işlemleri gerçekleştireceğiz.
Yazma işlemleri için genellikle dosya açma işlemini blok kullanarak yaparız.
Ancak burada dikkat etmemiz gereken nokta, dosya açma modunun yazmaya izin vermesi gereklidir.
Herhangi bir okuma modu belirtmezsek sadece okunabilir modda açacağı için
File.open
metoduna 2. parametre olarak "w"
, "w+"
"a"
yada "a+"
açma modlarından birini vermeliyiz.
Dosyanın içine yazmak için .write
, .puts
, .print
fonksiyonlarını kullanabiliriz.
Burada dikkat etmemiz gereken ise, write
ve print
fonksiyonları stringin
sonuna satır sonu karakteri ( \n
) eklemediği için dosyada da
yeni satıra geçilmeyecektir.
Eğer eklediğimiz metinden sonra yeni satıra geçmek istiyorsak ya
write
veya print
e verdiğimiz stringin sonuna \n
karakterini
eklemeliyiz yada kısa yoldan puts
kullanarak satır sonu karakterinin
otomatik olarak eklenmesini sağlayabiliriz.
File.open("isimler.txt", "a+") do |dosya|
dosya.write "celil"
end
Dosyanın içeriğini okuyacak olursak
File.read("isimler.txt")
"durmuş hoca\nserhat\ntaha\nömer\ntunahan\ncelil"
Gördüğünüz gibi okunan stringin sonunda \n
karakteri bulunmamaktadır.
Bu dosyanın üzerine yazmaya devam edersek
File.open("isimler.txt", "a+") do |dosya|
dosya.puts "ileri"
end
dosyanın içeriğini okumak için
File.read("isimler.txt")
yaptığımızda aşağıdaki stringi verecektir
"durmuş hoca\nserhat\ntaha\nömer\ntunahan\ncelilileri\n"
Gördüğünüz gibi celil
in sonunda \n
karakteri yok ancak son eklenen
ileri
nin sonunda \n
karakteri var.
Bu stringi puts ile ekrana bastıracak olursak çıktısı aşağıdaki gibi olacaktır:
durmuş hoca
serhat
taha
ömer
tunahan
celilileri
File.absolute_path
fonksiyonuyla bir dosyanın gerçek dosya yolunu
öğrenebilirsiniz.
Örnek kullanım:
File.absolute_path("isimler.txt")
# "/home/sci/isimler.txt"
File.atime
fonksiyonuyla bir dosyaya en son erişilen zamanı öğrenebilirsiniz.
Örnek kullanım:
File.atime("isimler.txt")
# 2017-12-04 20:31:38 +0300
File.basename
fonksiyonuyla bir dosyanın baz adını öğrenebilirsiniz.
File.basename("/home/sci/isimler.txt")
# "isimler.txt"
Eğer ki bir dosyanın uzantısını biliyor ve uzantısız baz adını öğrenmek
istiyorsanız File.basename(dosya_yolu, uzantı)
olarak kullanabilirsiniz.
File.basename("/home/sci/isimler.txt", ".txt")
# "isimler"
Okuduğunuz dosyanın uzantısını bilmiyor veya uzantısının ne olduğu sizin için fark etmiyor, sadece uzantısız baz adını öğrenmek istiyorsanız
File.basename("/home/sci/isimler.txt", ".*")
# "isimler"
Burada ".*"
ın anlamı: .
ve sonrasında ne gelirse olarak özetlenebilir.
File.delete
fonksiyonuyla istediğimiz (silme yetkimiz olan) bir dosyayı silebiliriz.
File.delete("isimler1.txt")
Verdiğiniz dosya yolundaki dosyanın biz dizin olup olmadığını öğrenmek
için File.directory?
fonksiyonunu kullanabilirsiniz.
Örneğin bulunduğumuz dizinde Downloads
adında bir dizin ve
isimler.txt
adında bir dosya bulunmaktadır.
File.directory?("Downloads")
# true
File.directory?("isimler.txt")
# false
File.dirname
fonksiyonuyla yolunu verdiğimiz dosyanın bulunduğu dizinin
yolunu verir. (tam yolu değil, verdiğimiz yoluna göre bulunduğu dizin)
File.dirname("/home/sci/isimler.txt")
# "/home/sci"
Bir dosya yolu vererek, orada gerçekten bir dosya olup olmadığını anlamak
için File.exist?
fonksiyonunu kullanırız.
Örneğin bir dosya varsa farklı, yoksa farklı davranacak bir program yazmak istiyorsanız bu fonksiyon işinize yarayacaktır.
File.exist?("tunahan.cs")
# false
File.exist?("isimler.txt")
# true
File.extname
fonksiyonunu kullanarak yolunu verdiğimiz bir dosyanın
uzantısını elde edebiliriz.
File.extname("isimler.txt")
# ".txt"
Bu bilgi biraz erken bir bilgi olacak ancak, bir dosya dosya
, dizin
, link
gibi farklı tiplerde olabilir.
Bir dosyanın hangi tipten olduğunu öğrenmek için File.ftype
fonksiyonunu
kullanabiliriz.
Sonucunda "file”, “directory”, “characterSpecial”, “blockSpecial”, “fifo”, “link”, “socket”, “unknown”
değerlerinden birini dönecektir.
File.ftype("isimler.txt")
# "file"
Farklı işletim sistemlerinde dosya yolları farklı karakterlerle birleştirildiği
için eğer ki yazdığımız programın her işletim sisteminde sorunsuz çalışmasını
istiyorsak bir dosya yolu oluştururken elle oluşturmak yerine
File.join
fonksiyonunu kullanmalıyız.
Bu fonksiyon kendine verdiğimiz parametreleri kullandığımız işletim sistemine uygun olarak birleştirerek bize bir dosya yolu verektir.
Örneğin Unix mimarisini kullanan bir işletim sisteminde aşağıdaki kod ve çıktısı şöyledir:
File.join("home", "sci", "isimler.txt")
# "home/sci/isimler.txt"
Aynı kodu bir Windows işletim sisteminde çalıştırsak sonuç şu şekilde olacaktı:
File.join("home", "sci", "isimler.txt")
# "home\sci\isimler.txt"
File.mtime
fonksiyonuyla bir dosyanın en son ne zaman değiştirildiğini öğrenebilirsiniz.
Örnek kullanım:
File.mtime("isimler.txt")
# 2017-12-04 20:31:35 +0300
File.rename
fonksiyonunu kullanarak bir dosyayı yeniden adlandırabiliriz.
Bu fonksiyona ilk parametre olarak şu anki dosya adını, ikinci parametre olarak da yeni dosya adını verdiğimizde dosyayı yeniden isimlendirecektir.
File.rename("isimler.txt", "derse_girenler.txt")
File.size?
fonksiyonuyla bir dosyanın boyutunu öğrenebiliriz.
Olmayan bir dosya için nil
değerini döndürecektir.
File.size?("isimler.txt")
# 50
File.size?("olmayan_dosya")
# nil
Not: .size
diye bir fonksiyon da vardır ve aynı işlevi görmektedir
ancak eğer dosya yoksa hata vermektedir. Hata almak yerine nil
sonucunun dönmesini istiyorsak .size?
fonksiyonunu kullanacağız.
Bir dosyanın var olduğu halde içinin boş olup olmadığını öğrenmek için
File.zero?
fonksiyonunu kullanırız.
Dosya yoksa veya var olup da içi doluya false
dönecektir.
File.zero?("ici_bos_dosya")
# true
File.zero?("isimler.txt")
# false
File.zero?("olmayan_dosya")
# false
Bu dokümanda anlatılanlar temel ve en çok kullanılan dosya işlemleri idi.
Eğer tüm dosya fonksiyonlarına ulaşmak istiyorsanız https://ruby-doc.org/core-2.2.0/File.html adresinde bulabilirsiniz.
Bu doküman Serhat Celil İLERİ ( GitHub: @ileri ) tarafından oluşturulmuştur.