Ders 7 - Dosyalama İşlemleri - Altan MESUT

Download Report

Transcript Ders 7 - Dosyalama İşlemleri - Altan MESUT

PROGRAMLAMA DİLLERİNE
GİRİŞ
Ders 7: Dosyalama İşlemleri
Yrd. Doç. Dr. Altan MESUT
Trakya Üniversitesi
Bilgisayar Mühendisliği
Dosya
• Programda kullanılacak verileri veya programda
üretilen verileri saklamak için dosyalar kullanılır.
• Programlama dilleri dosya yaratma, dosya silme,
dosyadan bilgi okuma ve dosyaya bilgi ekleme gibi
temel işlevler için gerekli komutları içerirler.
• Dosyalar saklama türüne göre ve kayıt erişim
biçimlerine göre aşağıdaki gibi sınıflandırılırlar:
– Saklama türleri: ikili (binary) ve metin (text)
– Kayıt erişim biçimleri: sıralı (sequential) ve rastgele
(random)
Saklama Türüne Göre Dosyalar
• Metin (text) türündeki dosyalara bilgi ASCII
biçiminde kaydedilir. Bu tip dosyalar Not Defteri
(Notepad) gibi bir metin editörleri tarafından
okunabilir.
• İkili (binary) türündeki dosyalara sayısal veriler
ASCII formatına dönüştürülmeden doğrudan
kaydedilir.
• Örn: 123 sayısı metin türü dosyaya 00110001,
00110010, 00110011 (49, 50, 51) şeklinde 3 byte
olarak kaydedilirken, ikili dosyaya 01111011
şeklinde 1 byte olarak kaydedilir.
Erişim Biçimlerine Göre Dosyalar
• Sıralı Erişimli (Sequential Access) dosyalarda, kayıtların
boyutu sabit değildir. Bu nedenle aradığımız kayda
erişmek için tüm kayıtlara tek tek bakmamız gerekir.
• Rastgele Erişimli (Random Access) dosyalarda, her kayıt
sabit bir uzunlukta olmalıdır (Örneğin soyad alanı kayıt
deseninde 20 karakter olarak belirlendiyse, o uzunlukta
soyad girilmediğinde kalan kısımlar boşluk karakteri ile
doldurulur). Bu sayede n. kayda erişmek gerektiğinde,
önceki kayıtları atlamak için; (n  1) × Kayıt Boyu kadar
dosyada ilerleme seçeneği kullanılabilir.
Sıralı – Rastgele Karşılaştırması
• Rastgele Erişimli dosyalarda herhangi bir kayda dosyadaki
sıra numarası biliniyorsa doğrudan erişilebilir (bu nedenle
Doğrudan Erişimli Dosyalar da denir). Fakat dosyalarda
gereksiz boşluklar bulunduğu için dosya boyu büyük olur.
• Sıralı Erişimli dosyalarda gereksiz boşluklar oluşmadığı
için dosya boyu rastgele erişimli dosyaya göre daha azdır.
Fakat herhangi bir kayda erişmek için dosyanın başından
itibaren o kayda kadar olan tüm kayıtların okunması
gereklidir.
Sıralı Erişim
Rastgele Erişim
Dosyaya Yazma
• Dosyalama işlemleri için System.IO isim
uzayı altındaki bazı sınıflara ihtiyacımız olacak:
using System.IO;
• Bu isim uzayındaki File sınıfının WriteAllText
yöntemi ile istediğimiz bir yazıyı string türünde
dosyaya yazdırabiliriz:
Dosya adı
File.WriteAllText("deneme.txt",
"Trakya Üniversitesi");
Dosyaya yazılacak olan string
Dosyadan Okuma
• File sınıfının ReadAllText yöntemi ise dosyanın
içeriğini string türünde döndürür:
File.ReadAllText("deneme.txt");
• Dönen değeri bir string değişkene atayabilir
yada ekrana gösterebiliriz:
string str = File.ReadAllText("deneme.txt");
Console.Write(File.ReadAllText("deneme.txt"));
Bayt türünde yazma ve okuma
• File sınıfının WriteAllBytes yöntemi ilk parametre
olarak dosya adını, ikinci parametre olarak
dosyaya yazılacak olan byte dizisini alır.
• ReadAllBytes yöntemi ise bir dosya adını
parametre olarak alır ve dosyanın içeriğini byte
dizisi olarak döndürür.
• WriteAllText ve ReadAllText yötemlerinden farkı
bu yöntemlerin byte veri türü ile çalışmalarıdır.
byte[] data = { 65, 66, 67 };
File.WriteAllBytes("deneme.txt", data);
Dosyaya ABC yazar
FileStream Sınıfı
• System.IO isim uzayı altındaki FileStream sınıfı
da dosyalama ile ilgili işlemlerde sıkça kullanılır.
• FileStream sınıfı ve içindeki yöntemler statik
olarak tanımlanmadığı için bu sınıfa ait bir nesne
oluşturmadan yöntemlerine erişemeyiz.
FileStream fs = new FileStream("dosya.txt",
FileMode.Append);
Bu sınıfın 15 farklı yapıcı yönteminden en çok kullandığımız ilk parametresi
dosya adı (string), ikinci parametresi ise dosya kipi (FileMode) olandır.
Dosya kiplerinden en çok kullandıklarımız:
Open: varolan dosyayı açar ve başına konumlanır.
Append: dosya varsa açar ve sonuna konumlanır, yoksa yaratır.
Write ve WriteByte
• FileStream sınıfından bir nesne oluşturduktan sonra bu
nesnenin adının (fs adını verdik) sonuna nokta
koyduğunuzda kullanabileceğiniz yöntemleri ve
erişebileceğiniz özellikleri görebilirsiniz.
• Write yönteminde ilk parametre dosyaya yazılacak byte
dizisi, ikinci parametre dizinin hangi elemanından
başlanacağı ve üçüncü parametre kaç byte
kopyalanacağıdır. WriteByte yöntemi ise sadece bir
byte parametre olarak alır ve bunu dosyaya yazar.
byte[] data = { 65, 66, 67 };
fs.Write(data, 0, 3); Dosyaya ABC yazar
Dosyaya A yazar
fs.WriteByte(65);
Read ve ReadByte
• ReadByte yöntemi hiç parametre almaz.
Dosyadan bir bayt okuma yapar (okuduğu değeri
int olarak döndürür) ve okuma pozisyonunu bir
bayt ileri taşır.
• Read yöntemi Write yöntemi ile aynı
parametrelere sahiptir, yaptığı iş ise Write
yönteminin tersidir: Dosyanın okuma
konumundan ikinci parametrede (offset) verilen
kadar ileriden, ve üçüncü parametrede (count)
verilen kadar miktarda okuma yapar ve birinci
parametrede verilen byte dizisine yazar.
StreamWriter & StreamReader Sınıfları
• Console sınıfındaki Write ve WriteLine ile aynı
kullanımlara sahip fakat dosya üzerinde çalışan
yöntemler StreamWriter sınıfında, Read ve ReadLine ile
aynı olanlar ise StreamReader sınıfında mevcuttur.
• Bu sınıflara ait bir nesne yaratılırken daha önce
yaratılmış bir FileStream nesnesi parametre olarak
yapıcı fonksiyona verilmelidir:
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine("Hello World");
StreamReader sr = new StreamReader(fs);
string str = sr.ReadLine();
BinaryWriter & BinaryReader Sınıfları
• Text ve Binary olmak üzere iki farklı saklama türü
olduğundan bahsetmiştik. Eğer dosyalar ile ikili (binary)
türde çalışmak istersek BinaryWriter ve BinaryReader
sınıflarını kullanmalıyız.
byte bSayi = 255;
int iSayi = 255;
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(bSayi); 1 byte yazar
Tüm veri tipleri ile kullanılan
tek bir Write yöntemi var
bw.Write(iSayi); 4 byte yazar
BinaryReader br = new BinaryReader(fs);
bSayi = br.ReadByte();
Her veri tipi için farklı
bir Read... yöntemi var
iSayi = br.ReadInt32();
NOT: BinaryReader sınıfında FileStream sınıfındakine benzer bir Read yöntemi de var
Open & Close Yöntemleri
• FileStream, StreamWriter ve BinaryWriter
sınıflarında dosyayı kapatmak için Close()
yöntemi kullanılır.
• Önceki 2 slaytta yazdığımız kodların
çalışabilmesi için yazma işleminden sonra
dosya kapatılıp, File.Open yöntemi ile Open
kipinde (FileMode.Open) tekrar açılmalıdır:
fs.Close(); // yada bw.Close(); sw.Close();
fs = File.Open("dosya.txt", FileMode.Open);
Yapı (Struct)
• Yapı ile Sınıf kavramları birbirine benzemektedir.
En temel fark bir yapıdan türetilen bir nesne, aynı
yapıdan başka bir nesneye eşitlendiğinde
özelliklerine ait değerler kopyalanmaktadır.
• Oysa aynı sınıfa ait iki nesne için böyle bir
eşitleme yaptığımızda iki nesnenin adresleri eş
oluyordu (yani birinde değiştirdiğiniz bir özelliğin
değeri diğerinde de değişmekteydi, bak: Ders 5,
Slayt 10).
struct Personel
{
public long perno;
public string ad;
public string soyad;
public string telefon;
public string adres;
public float maas;
}
Eğer struct yerine class yazılsaydı,
programın çıktısı 100 olurdu.
Fakat struct adres eşitlemesi
değil de kopyalama yaptığı için
bu program çıktı olarak 0 yazar.
Çünkü Ali’nin özellikleri Veli’ye
kopyalanırken henüz Ali’nin
personel numarası 100 değildi.
class Program
{
static void Main()
{
Personel Ali = new Personel();
Personel Veli = Ali;
Ali.perno = 100;
Console.WriteLine(Veli.perno);
}
}
Veri Tipi = Yapı
• C# dilinde tüm veri tipleri de aslında struct
olarak tanımlanmıştır:
C ve C++ Dillerinde Yapı
• C++ dilinde hem sınıf hem de yapı, C’de ise sadece
yapı vardır. C’de yapılar dosyalama işlemlerinde bir
kayıt deseni oluşturmak amacıyla kullanılabilir.
struct Personel{
long int perno;
char ad[15];
char soyad[20];
char tel[13];
char adres[100];
float maas;
} kayit;
Yandaki tanım C diline aittir. Personel
yapısından üretilen kayıt değişkeninin
(eskiden nesne değil değişken denirdi)
boyutu içerdiği 6 farklı özelliğin boyutu
kadardır (160 bayt). kayit.perno = 595;
gibi bütün özelliklere değer girildikten
sonra kaydın tamamı fwrite komutu ile bir
defada dosyaya yazılabilir. C# dilinde
sabit uzunluklu bir karakter dizisi için
fixed char ad[15]; gibi bir tanım
kullanılabilir ancak bu kullanım unsafe
(güvensiz) olarak bildirilmelidir.
Veri Tabanı
• Günümüzde personel verisini saklamak gibi işler için
genellikle bir veri tabanı tablosunu tercih ederiz (tablo
içinden aradığımız veriyi hızlı bir şekilde elde edebilme gibi
avantajlara sahip oluruz).
• Rastgele Erişimli dosyalama için C’deki fread ve fwrite,
VB’deki FilePut ve FileGet gibi komutlara benzer yöntemler
C# dilinde yoktur. Sabit uzunluklu karakter dizilerini de
güvensiz olarak niteleyip string kullanımını tavsiye etmesi
nedeniyle sabit uzunlukta bir struct yapısı oluşturmada
fazladan iş çıkarmaktadır (rastgele erişimi sağlamak için
sabit uzunluk şarttır). Bu dili geliştirenler muhtemelen "veri
tabanı varken bu tip dosyalama işlemlerine gerek yok"
şeklide düşünmüş ve bu nedenle C# diline bu özellikleri
eklememiş olabilirler.
Ödev
• Kullanıcının ekleyeceği notları notlar.txt dosyasında sıra ile saklayan
bir program yazın. Program çalıştırıldığında dosyanın içinde saklı
olan tüm notlar sıra numarası ile birlikte görüntülenecek ve altında
"not eklemek için 1’e, not silmek için 2’ye çıkış için ESC’ye basın"
mesajı görüntülenecektir.
• Not Ekleme seçildiğinde "Notunuzu Giriniz" mesajı görüntülenecek
ve kullanıcının ekrana yazacağı not ENTER basıldığı anda dosyanın
sonuna eklenecektir.
• Not Silme seçildiğinde "Silmek İstediğiniz Notun Numarasını Giriniz"
mesajı görüntülenecek ve kullanıcının seçtiği not dosyadan
silinecektir.
• Ekleme ve silme işlemlerinden sonra ekran temizlenip programın
başına dönülmelidir (Dosyanın son hali ekranda gösterilip yine
altında "not eklemek için 1’e, not silmek için 2’ye çıkış için ESC’ye
basın" mesajı görüntülenmelidir).