aofsorular.com
BİL107U

Ünite 5: C# ile Dosya İşlemleri

PROGRAMLAMA I
Dosya İşlemleri C# programlama dilinde System.IO kütüphanesi, dosya işlemleri ile ilgili çeşitli sınıfları içermektedir. I/O (Input/Output) yani giriş/çıkış işlemlerinin yanında bilgisayarın çeşitli kaynaklarına erişim için kullanılan yolları simgeler. Net ortamında soket ve bellek işlemleri de benzer bir biçimde çalışabilmesi için dosya gibi davranmaktadır. Ekrana bilgi yazdırma, yazıcıdan çıktı alma, klavyeden bilgi girişi, dosya kaydetme, farenin yaptığı işlemlerin hepsi birer I/O işlemidir. I/O sistemleri, Stream sınıfı üzerine kuruludur. Bu sistemler, bir girdi ya da çıktı sistemi üzerinden byte düzeyinde veriyi okuyan sanal birimlerdir. FileStream, MemoryStream, NetworkStream gibi sınıflar, Stream abstract sınıfından türetilerek fonksiyonları tanımlanmıştır. FileStream sınıfı, dosyadan veri okurken, veri yazarken ve yeni bir dosya oluştururken kullanılan bir sınıftır. Bu sınıf ile işlem yapabilmek için ilk önce bu sınıftan bir nesne türetmemiz gerekmektedir. Yeni nesne oluşturulurken zorunlu olarak verilmesi gereken parametreler vardır. Bu parametrelerden ilki dosya yoludur. Dosya yolu (File Path) parametresi string veri içerir, bilgisayarımızın istediğimiz bir klasöründe işlem yapabilmemize imkân sağlar. Bu parametreye doğrudan “yeni_dosya.txt” gibi bir dosya adı da verebiliriz. Bu durumda projemizin bulunduğu klasörün altında, verdiğimiz isimdeki dosya ile işlem yapacağız demektir. Dosyanın açılma şeklinde (FileMode) ise 6 farklı dosya açılma şekli görmekteyiz.
• Append: Dosya yoksa oluşturur, varsa dosyanın sonuna ekleme yapmak için kullanılır.
• Create: Dosya yoksa yeni dosya oluşturur, aynı isimde başka bir dosya varsa üzerine yazar.
• CreateNew: Aynı isimde bir dosya varsa hata verir, yoksa yeni bir dosya oluşturur.
• Open: Belirtilen dosya yolundaki dosyayı açmak için kullanılır. Dosya yoksa hata verir.
• OpenOrCreate: Belirtilen dosya yolundaki dosyayı açmak için kullanılır, dosya yoksa yeni dosya oluşturur.
• Truncate: Belirtilen dosya yolundaki dosyanın içeriğini silerek açmak için kullanılır. Dosyanın kullanım şeklinde (enum türünde oluşturulmuş FileAccess) ise dosyaya hangi türde erişebileceğimiz belirtilir. Read, Write ve ReadWrite olmak üzere üç farklı şekilde dosyaya erişebiliriz. Dosya Oluşturma FileStream sınıfını kullanarak, “c:\tmp” klasörü altına “yeni_dosya.txt” dosyasını yoksa oluşturmak (FileMode.OpenOrCreate) varsa (FileAccess.Write) yazmak için açalım. Dosyaya Veri Yazma System.IO kütüphanesinin bir sınıfı olan StreamWriter sınıfı parametre olarak FileStream nesnesi almaktadır.
StreamWrite, açılan dosyaya veri koymak için kullanılır. Şu şekilde tanımlanır: StreamWriter sw = new StreamWriter(fs); Unutmamalıdır ki StreamWriter kullandıktan sonra, her zaman için Close() metodu ile kapatmak gerekmektedir. Aksi hâlde dosyaya yazma işlemi gerçekleşmez. Bu metot aynı zamanda FileStream (fs) nesnesini de kapatır. StreamWriter sw = new StreamWriter(fs); sw.Write("Bu benim "); sw.WriteLine("ilk dosya işlemim. "); sw.WriteLine("Merhaba dünya!!!"); sw.Close(); Yeni bir dosya oluşturmak için kullandığımız “fs” nesnesi ile dosyaya veri ekleyebilmek için StreamWriter nesnesi tanımlanabilir. Ardından dosyamıza 2 satırlık veri eklenir. WriteLine metodu, veriyi bir satıra ekler ve bir alt satıra iner, yeni verilerin kayıtları bu satırdan devam eder. Dosyadan Veri Okuma Mevcut dosyadan okuma yapmak için de StreamReader sınıfını kullanılır. İlk önce StreamReader (sr) nesnemizi okumak istediğimiz dosyanın yolunu parametre olarak vererek oluşturuyoruz. Açtığımız dosyadan okuma yapabilmek için, satır satır okuyan ReadLine() metodunu kullanabiliriz. Tüm dosyayı bu metot ile okuyabilmek için bir while döngüsü içinde, ReadLine() metodu dosya sonuna gelip “null” değerini verene kadar okumaya devam edecek kodumuzu hazırlayabiliriz. Diğer okuma yöntemi olan ReadToEnd() metodu ile de dosya içindeki tüm veriyi bir kerede alabiliriz. Satır sonlarını gösteren “\r\n” karakterleri de bu veri içinde görülebilir. BinaryWriter ve BinaryReader BinaryWriter ve BinaryReader sınıflarının yaptığı iş ile StreamWriter ve StreamReader sınıflarının yaptıkları işler aynıdır. Aralarındaki en önemli fark, BinaryWriter ve BinaryReader sınıfları ile string olma zorunluluğu olmadan her türlü veriyi yazdırıp okunabilmesidir. Bu sınıflarda Write(int), Write(char[]), Write(byte) ile ReadByte(), ReadChar() ve ReadString() gibi metotlar bulunmaktadır. BinaryWriter sınıfıyla oluşturulan dosyalar açıldığında okunamayan karakterler ile karşılaşılır. Bunun sebebi de BinaryWriter metodunun dosyaya text yöntemi yerine binary yöntemle kayıt yapmasıdır. Directory ve File Sınıfları Directory ve File sınıfları System.IO altında bulunur. Bu iki sınıfta da statik metotlar vardır ve birçok metotları benzerdir. Aralarındaki en büyük fark, Directory sınıfı klasörler üzerinde işlem yaparken File sınıfı da dosya işlemleri yapmaktadır. DirectoryInfo ve FileInfo Sınıfları DirectoryInfo ve FileInfo sınıflarının metotları static değildir, bu sınıflardan oluşturulan nesneler üzerinden erişilebilirler. Directory ve File sınıfları sadece klasör ve dosyalar üzerinde yaptıkları işlemler için dosya yolunu
kullanırken, DirectoryInfo ve FileInfo sınıfları ise dosya yolunun yanında dosya adı, boyutu, uzantısı, oluşturulma tarihi gibi bilgileri de vermektedir. Günlük Dosya Yedekleme Yedeğini almak istediğimiz bir klasörümüz varsa, hazırlayacağımız çok kısa bir kod ile istediğimiz zaman dosyaların son hâllerini yedekleyebiliriz. Kodumuzda, yedekleme klasörümüz içerisinde günün tarihi ile yeni bir klasör açılarak kaynak klasördeki tüm dosyalar bu klasöre yedeklenmektedir. Hedef klasör yok ise oluşturulmakta, daha önceden kopyalanan dosyalar da tekrar kopyalanmaması için kontrol edilmektedir. Giriş/Çıkış (Input/Output) Fonksiyonları C# programlama dilinde I/O fonksiyonları System.Console sınıfına tanımlanmıştır. Console sınıfı, System.IO altında tanımlanmayan ama ekrana yazı yazdıran ve kullanıcı girdilerini alan I/O işlemleri yapan bir sınıftır. Console için tanımlanmış üç adet akım (stream) mevcuttur. Bunlar; TextWriter türünde tanımlanmış Console.Out, Console.Error ve TextReader türünde tanımlanmış Console.In’dir. Konsol ekranına yazı yazdırabilmek için Console sınıfının Write() ve WriteLine() metotları kullanılmaktadır. Bu metotlar arasındaki tek fark, WriteLine’da yazının sonuna “\n” koyarak, sonraki yazının yeni bir satırda başlamasını sağlarken, Write metodu ise yeni satıra geçmeden aynı yerden yazdırmaya devam eder. Ayrıca bu metotlarla verileri biçimlendirerek de yazdırabiliriz. Konsoldan bilgi almak için Read() ve ReadLine() metotları kullanılmaktadır.
• Read metodu kullanıcıdan veri girişi bekler, verileri birer karakter hâlinde alarak sonucu da int olarak alır.
• ReadLine metodunda ise enter tuşuna basana kadar girilen tüm veriyi depolar, sonra string formatında aktarır.
• int Peek(): Input stream’den yani girdiden, tampondan silmeden, bir karakter okunması işlemini gerçekleştirir. Örnek ile inceleyelim. Console.Write((char)Console.In.Peek() + " " + (char)Console.In.Peek()); Örnek kod için kullanıcının ekrana “Merhaba” yazdığını düşünelim. Kodumuz ekrana M M yazacaktır. Çünkü tampondan silinmeden hep aynı karakteri okumaktadır.
• int ReadBlock(char[] dizi, int indeks, int adet): Bu metot yardımıyla, Input stream yani girdi, dizi değişkeninin indeks elemanından başlayarak adet sayısı kadar dizi değişkenine aktarılır.
• string ReadToEnd(): Input stream yani girdideki tüm verileri okuyarak tamponu temizler. Okunan verileri de string türünde döndürür.
Input Stream C#’da, bütün I/O işlemleri (stream) akımlar üzerine kurulmuştur. Akımlar arasında yönlendirme yapmak mümkündür. Komut satırından şu şekilde programları çalıştırdığımızda;
1. program > cikti.txt Çalıştırılan programın ekran çıktıları, cikti.txt adlı dosyaya yazdırılacağı anlamına gelmektedir. Dolayısıyla, standart konsol çıktısı dosya akımına yönlendirilmiş olur. Yönlendirmeye başka bir örnek verelim;
2. program < veriler.txt Çalıştırılan programdaki Console.Read() veya Console.ReadLine() yerine veriler.txt dosyasındaki veriler kullanılacaktır. C# programları içinde de akımlar şu şekilde yönlendirilebilir; o static void SetIn( StreamReader sr ) veya static void SetIn( TextReader sr ) o static void SetOut( StreamWriter sw ) veya static void SetOut( TextWriter tw ) o static void SetError( StreamWriter sw ) veya static void SetError( TextWriter tw ) Biçimlendirme Kuralları Console sınıfı metotlarından Write()/WriteLine() ile formatlı şekilde metin, sayı ve tarih gibi içerikler yazdırılabilir. Sayı Biçimlendirme { argumentSırası[, hizalama][:biçim] } { argument[, hizalama][:biçim] } Şablonun kullanıldığı örneğimiz: int sayi = 56; string metin = "C#" ; Console.Write("sayı={0, 8:F2}", sayi ); Console.Write("sayı={0,-8:F0}", sayi ); Console.Write("metin={0,10}", metin ); İlk örneğimizdeki {0, 8:F2} biçimini inceleyelim. 0, parametre sırasını göstermektedir. Buradaki karşılığı, int türünde tanımlanmış “sayi” değişkenidir. 8 rakamı da hizalamak için kullanılacak basamak sayısını göstermektedir. Yani ekrana basılacak ifadenin uzunluğu 8 karakter olacaktır. Pozitif değerler için rakamlar sağa yaslı olacaktır ve basamak sayısını tamamlamak için eksik kalan yerlere boşluk bırakılacaktır. Negatif değerlerde ise rakamlar sola yaslanacak ve boşluklar bu sefer sağda bırakılacaktır. “:F2” ise noktalı bir gösterim yapılacağı ve noktadan sonra 2 basamak gösterileceğini ifade etmektedir. Sayı biçimlendirme örnekleri için Tablo 5.1. incelenebilir. Tarih Biçimlendirme C#’da tarih bilgisini Tablo 5.2’de detayları verildiği gibi formatlayabiliriz. Kod içerisinde kullanımı da Tablo 5.2’de sunulmuştur.
Özel Tarih Biçimlendirme Tarih biçimlendirmede Tablo 5.2’ye ilaveten özel formatlar mevcuttur. Bunlar da Tablo 5.3’de sunulmuştur. Konsol (Console) İşlemleri C# kod geliştirme ortamı olan Visual Studio ile yeni bir proje oluştururken “Windows Forms Application” ve “Console Application” gibi seçenekler karşımıza çıkmaktadır. Windows Forms Application, programcıya kullanım kolaylığı sağlayarak hazır bileşenler sunan (form, textBox, radioButton, comboBox vs.) grafik arayüzüne sahip bir C# proje türüdür. Console ise grafik arayüzü bulunmayan, girdi ve çıktıların siyah bir ekranda işlendiği kullanıcı arayüzüdür. Hazır bileşenler bu yapı içinde yoktur. a) Console.SetWindowSize(x, y): Konsolun büyüklüğünü yani ekran genişliğini ayarlamaya yarayan metottur. İlk parametresi karakter olarak genişliği, ikinci parametre de satır olarak yüksekliği belirtmektedir. b) Console.BackgroundColor, Console.ForegroundColor: Console ekranında, yazı rengi ve yazının vurgu rengi sistemde tanımlı olan 16 renkten biri seçilerek tanımlanabilmektedir. o ForegroundColor ile yazı rengi o BackgroundColor ile de yazının vurgu rengi ayarlanır. o Console.ResetColor() metodu ile renkler eski hâline döndürülür. Konsol renk isimleri için Tablo 5.4 incelenebilir. c) Console.CursorLeft, Console.CursorTop: Konsol üzerindeki imlecin konumunu verilen koordinatlara getirmek için kullanılır. Aynı işlemi tek başına yapan başka bir metot da Console.SetCursorPosition(x, y)’dir. d) Console.Clear(): Bu metot ile console ekranı temizlenir.