• Sonuç bulunamadı

KONU 7: DOSYA İŞLEME ( File Processing )

N/A
N/A
Protected

Academic year: 2022

Share "KONU 7: DOSYA İŞLEME ( File Processing )"

Copied!
9
0
0

Yükleniyor.... (view fulltext now)

Tam metin

(1)

DERS: PROGRAMLAMA DİLLERİ – 1 DÖNEM: 2002-2003 Güz yarı yılı

KONU 7: DOSYA İŞLEME (“File Processing”)

HEDEFLER:

1- Dosyaları yaratabilme, okuyabilme, yazabilme ve güncelleyebilme 2- Sıralı erişim dosyalarını tanıma

3- Rasgele (doğrudan) erişim dosyalarını tanıma 4- Bu dosyalar üzerinde G/Ç işlemleri yapma İÇERİK:

Veri hiyerarşisi

Sıralı erişim dosyası yaratma Sıralı erişim dosyasından okuma Sıralı erişim dosyalarını güncelleme Rasgele erişimli dosyalar

Sıralı erişim dosyalarını yaratma Sıralı erişim dosyalarına yazma Sıralı erişim dosyasından sıralı okuma

VERİ HİYERARŞİSİ

Bilgisayarlarda her sayı ya da alfabetik karakterin 0 ve 1’lerle temsil edildiğini biliyorsunuz.

Karakterlerin bitlerden oluşması gibi alanlar da karakter (veya baytlardan) oluşur. Alan bir anlamı olan bir grup karakterdir.

Bir kayıt ise (C++’da class , C’de struct ) birden fazla alandan meydana gelir. Örneğin bir muhasebe sisteminde bir çalışana ait bir kayıtta aşağıdaki alanlar bulunabilir.

1- Sicil no 2- Adı 3- Adresi 4- Ücreti 5- Vergi oranı

Dolayısıyla bir kayıt birbiriyle alakalı alanlardan meydana gelir.

100000 kaydın olduğu bir dosyadan bir kayda erişmek istediğimizi düşünelim. Genellikle bu erişimi kolaylaştırmak için kaydın bir alanı anahtar (“record key”) olarak belirlenir ve erişim esnasında kullanılır. Yukardaki örnekte sicil no kayıt anahtarı olarak kullanılabilir.

Şirketlerin birden fazla dosyaları vardır: muhasebe, alacak hesapları, stok, personel, vb gibi.

Birbiriyle ilgili dosyaların bir veri tabanı programı kullanılarak veri tabanında tutulması pek

çok kolaylık sağlar: veri bütünlüğü, veri tutarlılığı, bakım kolaylığı, mükerrer veri olmaması

gibi. Veri tabanlarını yaratmak ve erişimi sağlamak, bakımlarını yapmnak için Veri Tabanı

Yönetim Sistemi (DBMS) denen yazılımlar mevcuttur.

(2)

C++ bir dosyayı baytlar sırası (“sequence of bytes”) olarak görür. Her dosya, dosya sonunu belirten bir işaret ile biter.

C++’da dosya işlemleri yapabilmek için <iostream> ve <fstream> başlık dosyaları dahil edilmelidir.

<fstream> başlık dosyası ifstream (giriş işlemleri için) ve ofstream (çıkış işlemleri için) gerekli sınıf (“class”) tanımlarını içerir.

SIRALI DOSYA YARATMA

Örnek: Her müşteri için hesap no, müşter, adı, bakiyesi, vb. tutulacak. Program, kullanıcının kayıtları hesap no sırasında gireceğini varsaymaktadır

.

// fig. 14.4 s.761

// create a sequential file

#include <iostream>

using std::cout;

using std::cin;

using std::ios;

using std::cerr;

using std::endl;

#înclude <fstream>

using std::ofstream;

#include <cstdlib>

int main() {

ofstream MusteriDosyasi(“musteri.dat”, ios::out ); // musteri.dat çıkış // için açılır (open) if (!MusteriDosyasi) // dosya düzgün açılırsa 0 döndürür

{

cerr << “Dosya açılamadı” << endl;

exit(1); // sıfır harici bir değer programın bir hata sonucu bittiğini gösterir. Bu değer op.sys’e ...

}

cout << “Hesap no, Ad, Bakiye bilgilerini giriniz.\n”

<< “Girişi bitirmek için EOF giriniz.\n?”;

int hesap;

char ad[20];

double bakiye;

while (cin >> account >> ad >> bakiye ) //EOF olmadıkça bu koşul doğrudur {

MusteriDosyasi << hesap << „ „ << ad << „ „ << bakiye << „\n‟;

cout << “? “;

}

return 0; // EOF olunca main biter. Musteri.dat dosyası kapatılır.

}

Hesap no, Ad, Bakiye bilgilerini giriniz.

Girişi bitirmek için EOF giriniz.

? 100 Jones 24.98 ? 200 Doe 345.67 ? 300 White 0.00 ? 400 Stone –42.16 ? 500 Rich 224.62 ? ^Z

(3)

Dosya açma durumları (“file open modes”)

ios::app dosyanın sonuna ekle ios::in dosyayı giriş için aç ios::out dosyayı çıkış için aç ios::trunc dosyanın içeriğini at

ios::binary dosyayı ikili (metin olmayan) giriş çıkış için aç

SIRALI DOSYADAN OKUMA YAPMA (“reading from sequential access file”)

// fig. 14.7 s. 766-767 .

.

#include <fstream>

. .

void satiryazdir(int, const char * const, double);

int main() {

ifstream MusteriDosyasi(“musteri.dat”, ios::in ); // ios::in konulmasa da olur

if ( !MusteriDosyasi) {

cerr << “Dosya açılamadı\n”;

exit(1);

}

int hesap;

char ad[20];

double bakiye;

cout << setiosflags( ios::left ) setw( 10) << “HESAP NO”

<< setw(13) << “ADI”

<< BAKİYE\n” << setiosflags( ios::fixed | ios::showpoint );

while ( MusteriDosyasi >> hesap >> ad >> bakiye ) satiryazdir(hesap, ad, bakiye);

return 0;

}

void satiryazdir(int hes, const char * char ad, double bak) {

cout << setiosflags( ios::left ) setw( 10) << hes << setw(13) << ad << setw(7) << setprecision(2) << resetiosflags( ios::fixed ) << bal << „\n‟;

}

HESAP NO ADI BAKIYE 100 Jones 24.98 200 Doe 345.67 300 White 0.00 400 Stone -42.16

500 Rich 224.62

---

ss. 768-769-770-771 atlandı

ad is a char

pointer to a

const char

(4)

SIRALI ERİŞİM DOSYALARININ GÜNCELLENMESİ

Yukarıda yaratılmış olan

musteri

dosyasındaki bir veri değiştirilmek (güncellenmek) istendiğinde diğer verilerin bozulma riski vardır. Örneğin White ismini Worthington yapmak istersek, bu isim orijinal isim olan Whhite’dan 6 karakter daha uzun olduğundan kendisinden sonra gelen kaydı bozar. Bunu önlemek için 300 White 0.00’a kadar olan kayıtlar yeni bir dosyaya kopyalanıp 300 Worthington 0.00 yazılıp geri kan kayıtlar da yeni dosyaya aktarılabilir. Bir seferde çok sayıda kayıt güncellenecekse bu yöntem kabul edilebilir.

RASGELE ERİŞİMLİ DOSYALAR

Belirli bir kaydın hemen bulunmasu gerektiği durumlarda kullanılır. Bankada belirli bir müşteri hesabına (dosyada daha önce gelen müşteri kayıtları okunmadan ) erişilmesi, kayıt sırasında belirli bir öğrenci numarasına daha önceki tüm numaralar okunmadan erişilmesi gibi.

C++ dosyalar üzerinde bir yapı oluşturmadığı için bunu programcı yapmalıdır. Rasgele erişimli dosya yaratmak için pek çok teknik vardır. Bunların en kolayında, tüm kayıtların sabit uzunluklu olması tercih edilir / gerekir. Kayıtların sabit uzunluklu olması aranan bir kaydın dosyanın başına göre kaçıncı bayttan (“byte offset”) başladığını hesaplamamızı mümkün kılar.

RASGELE ERİŞİMLİ DOSYALARI YARATMAK

Bu tür dosyalara genellikle class veya struct ile tanımlanmış bir grup alanı bir anda yazdırırız, tek bir sayıyı değil.

Örnek: 100 müşteri için 100 sabit uzunluklu kayıt tutulacak. Her kayıtta hesap no (kayıt anahtarı), ad, soyad, bakiye alanları bulunacak. Program, bir hesabı güncelleyebilmeli, yeni hesap ekleyebilmeli, hesap silebilmeli ve tüm hesapları listeleyebilmeli.

Aşağıda rasgele erişimli bir dosyanın nasıl açıldığını, struct ile kayıt yapısının nasıl tanımlandığı (

musveri.h

adlı başlık dosyasında) gösterilmektedir. Program öncelikle 100 kayda boş struct’lar yazarak kayıtların ik değer atamalarını yapmaktadır. Boş struct’da hesap no için 0, ad ve soyad için “null” dizgi, ve bakiye için 0.0 vardır.

// musveri.h

// struct musteri’nin tanımı

#ifndef MUSVERI_H

#define MUSVERI_H

Header file musveri.h

struct musteri

{ aşağıdaki tüm programlarda

int hesapno; bu başlık dosyası kullanılacak char soyad[15];

char ad[10];

double bakiye;

};

#endif

(5)

// fig.14.11 s.774

// creating random-access file sequentially

#include <iostream>

using std::cerr;

using std::endl;

using std::ios;

#include <fstream>

using std::ofstream;

#include <cstdlib>

#include “musveri.h”

int main() {

ofstream kredi(“kredi.dat”, ios::binary); // kredi.dat file is associated with // ofstream object kredi

if ( !kredi ) {

cerr << “kredi dosyası açılamadı” << endl;

exit(1);

}

musteri bosmusteri = { 0, “”, “”, 0.0 };

for ( int i = 0; i <100, i++ ) kredi.write(

reinterpret_cast<const char *>( &bosmusteri ), sizeof(musteri));

return 0;

}

kredi.write(

reinterpret_cast<const char *>( &bosmusteri ), sizeof(musteri));

cümlesinin anlamı:

kredi.dat ile ilişkilendirilmiş kredi nesnesine (“object”) musteri yapısı büyüklüğündeki bosmusteri yapısını yazar.

NOTE THAT the first argument of write function must be of type const char *.

However, the data type of &bosmusteri is musteri *.

To convert &bosmusteri to the appropriate pointer type, the expression

reinterpret_cast<const char *>( &bosmusteri )

uses the cast operator reinterpret_cast to convert the address of

bosmusteri

to a

const char *,

so the call to write compiles without issuing a syntax error.

(6)

RASGELE-ERİŞİMLİ DOSYAYA VERİLERİ RASGELE YAZMA

Aşağıdaki program kredi.dat dosyasına veri yazar. Dosyaya verileri tam yerlerine yazmak için ofstream fonksiyonları write ve seekp kullanır. Fonksiyon seekp, dosyaya yazıacak kaydın tam yerini ayarlar ve write verileri yazar.

// fig.14.12 s.775

// writing to a random access file

#include <iostream>

using std::cerr;

using std::endl;

using std::ios;

using std::cin;

using std::cout;

#include <fstream>

using std::ostream;

#include <cstdlib>

#include “musveri.h”

int main() {

ofstream kredi(“kredi.dat”, ios::binary); // kredi.dat file is associated with // ofstream object kredi

if ( !kredi ) {

cerr << “kredi dosyası açılamadı” << endl;

exit(1);

}

cout << “Hesap numarasını ( 1 ile 100 arasında )giriniz. “ << “Bitirmek için 0 giriniz.\n? “;

musteri mus;

cin >> mus.hesapno;

while ( mus.hesapno > 0 && mus.hesapno <= 100 ) {

cout << “Ad, soyad ve bakiye giriniz.\n? “;

cin >> mus.ad >> mus.soyad >> mus.bakiye;

// kredi dosyasında gerekli adrese konumlan

kredi.seekp( ( mus.hesapno – 1 ) * sizeof (musteri) );

kredi.write(

reinterpret_cast<const char *>(&mus), sizeof(musteri) );

cout << “Hesap numarasını giriniz:\n? “;

cin >> mus.hesapno;

}

return 0;

}

(7)

Hesap numarasını ( 1 ile 100 arasında )giriniz.Bitirmek için 0 giriniz.

? 37

Ad, soyad ve bakiyeyi giriniz:

? Bakır Deniz 0.00

Hesap numarasını giriniz:

? 29

Ad, soyad ve bakiyeyi giriniz:

? Baki Naci –24.54

Hesap numarasını giriniz:

? 96

Ad, soyad ve bakiyeyi giriniz:

? Sarı Sami 34.98

Hesap numarasını giriniz:

? 88

Ad, soyad ve bakiyeyi giriniz:

? Simit Davut 258.34 Hesap numarasını giriniz:

? 0

kredi.seekp( ( mus.hesapno – 1 ) * sizeof (musteri) );

Parantez içindeki aritmetik ifade, yazılacak yadın, dosya içine baştan kaçıncı bayttan başlacağını hesaplar. Musteri 50 bayt ise, hesapno 4 ise, hesapno 4 olan kayıt 200.bayttan itibaren yazılacak demektir. Dosya konumlandırma işaretçisi (“file position pointer”) bu adrese konumlanır.

RASGELE-ERİŞİMLİ BİR DOSYAYI SIRALI OKUMA s.777

Daha önce yarattığımız rasgele-erişimli dosyayı sıralı okuyacağız yani ilk kayıttan başlayarak sırayla her kaydı. Öncelikle birkaç önmeli konuya bakalım:

ifstream fonksiyonu read belirlenen bayt uzunluğundaki veriyi dosyadan okur. Örneğin

kredi.read(reinterpret_cast<char *>( ?mus ), sizeof(musteri) );

=

kredi

dosyasından

musteri

uzunluğunda baytı okuyup

mus

yapısına koyar.

NOT:

read

fonksiyonunun ilk argümanı

char *

olmak durumundadır.

Aşağıdaki program

kredi.dat

dosyasındaki bütün kayıtları sırayla okur ve okunan her bir kaydın veri içerip içermediğine bakar. Döngü koşulunu inceleyecek olursak:

while ( kredi && !kredi.eof() )

dosya sonuna gelip gelinmediğini anlamak için

eof

fonksiyonunu kullanır. Dosya sonuna gelindiyse döngüden çıkılır. İkinci bir koşul da

&&

işaretinin sol tarafında yer alan

kredi

sözcüğüyle belirtilmiştir.

kredi

dosyası okunurken bir hata oluşursa bu noktaya

false

döner ve yine döngüden çıkılır.

OutputLine

fonksiyonunun 2 argümanına dikkat edelim:

1- ostream objesi 2-musteri yapısı (structure).

Görüldüğü gibi,

cout

gibi bir

ostream

objesini argüman olarak vermek mümkündür.

(8)

Program: Rasgele erişimli dosyasını sıralı okunması

// fig. 14.14 reading a random access file sequentially

#include <iostream>

using std::cerr;

using std::endl;

using std::ios;

using std::cout;

#include <iomanip>

using std::setprecision;

using std::setiosflags;

using std::resetiosflags;

using std::setw;

#include <fstream>

using std::ifstream;

using std::ostream;

#include <cstdlib>

#include “musveri.h”;

void outputLine( ostream&, const clientData & );

int main() {

ifstream kredi(“kredi.dat”, ios::in); // kredi.dat file is associated with // ifstream object kredi if ( !kredi )

{

cerr << “kredi dosyası açılamadı” << endl;

exit(1);

}

cout << setioflags( ios:: left ) << setw (10) << “HESAP NO”

<< setw(16) << “SOYADI” << setw(11) << “ADI” << resetiosflags(ios::left) << setw(10) << “BAKİYE” << endl;

musteri mus;

kredi.read(reinterpret_cast<char *>( &mus ), sizeof( musteri ));

while ( kredi && !kredi.eof() ) {

if (mus.hesapno != 0 ) outputLine ( cout, mus);

kredi.read(reinterpret_cast<char *>( &mus ),

sizeof( musteri ));

}

return 0;

}

void outputLine( ostream &output, const musteri &c) {

output << setiosflags( ios::left ) << setw (10) << c.hesapno << setw(16) << c.soyad

(9)

<< setw(11) << c.ad << setw(10)

<< setprecision(2) << resetiosfalgs( ios::left) << setiosflags( ios::fixed | ios::showpoint) << c.bakiye << „\n‟;

}

HESAP NO SOYADI ADI BAKİYE 29 Baki Naci -24.54 33 Dakik Selin 314.33 37 Bakır Deniz 0.00 88 Simit Davut 258.34 96 Sarı Sami 34.98

Referanslar

Benzer Belgeler

Sıralı listeler (ordered list) Sıralı listeler rakam veya harf kullanarak liste, Sırasız listeler (unordered list) madde imleri koyarak liste.. Tanımlama listeleri (definition

• Açık Erişim Æ Görünürlük Æ Araştırma Etkisi Æ Daha çok araştırma desteği. • Araştırma raporlarını hızla web sayfalarına ya da kurumsal

[r]

Bilgi ve Belge Yönetimi Bölümü Açık Erişim Arşivi Uygulaması.. İşletim Sistemi: Linux

Bilgi ve Belge Yönetimi Bölümü Açık Erişim ve Kurumsal

Aşağıdaki soruları zihinden çözün ve cevaplarını

first time sperm collection from Russian sturgeon, potassium chloride (KCI) and saccharose in semen cryopreservation and post-thaw evaluation solutions buffered with

Nitekim bizim çalışmamızda da TDBT ile yapılan pulmo- ner BT anjiyografi incelemesiyle saptanan sub- segmenter emboli tüm embolilerin %9’unu oluş- tururken, ÇDBT ile