C Dili – 10. Konu

BİR DOSYAYA YAZMAK

ONSATIR.C:
=============================================================
#include <stdio.h>
main()
{
FILE *fp;
char ivir[25];
int index;
fp = fopen("onsatir.txt","w"); /* yazmak icin açalım */
strcpy(ivir,"Bu bir ornek satirdir.");
for (index = 1;index <= 10;index++)
fprintf(fp,"%s Satir no: %d\n",ivir,index);
fclose(fp); /* dosyayı kapayalim */
}
=============================================================

Bir dosyaya yazan ilk programımız. Her zamanki gibi, “stdio.h” i programa
ekliyoruz, ve daha sonra cok tuhaf bir degisken tanımlıyoruz.

“FILE” tipi, bir dosya değiskenidir, ve “stdio.h” in icinde tanimlanmıştır.
Kullanacağımız dosyaya erişmek icin bir ‘dosya pointeri’ tanimlamaktadır.
Bu pointer sayesinde, dosyayı açtıktan sonra, ondan okumak yada yazmak gibi işlemler yapabiliriz.

DOSYA YOLU

Dosyaya ulaşmak için diskin başından beri geçilen yola dosya yolu diyoruz.
Örneğin, masa üstünüzde bulunan ve “beni.oku” ismindeki bir dosyaya giden yol, C dilinde
Windows altında şu şekilde yazılabilir: “C:\\Users\\ben\\Desktop\\beni.oku”
(Windows’da dosya yolu ters bölü işaretleriyle yazılmaktadır.  Hatırlarsanız C dilinde ters bölünün özel bir anlamı vardır; bu nedenle ikişer tane konması gereklidir.)
Linux altında ise aynı yol şu şekilde yazılabilir: “/home/ben/Desktop/beni.oku”
Yukarıdaki örnekte gibi bir yol belirtmezseniz, sadece dosyanın ismini yazarsanız, programınız hangi klasörde çalıştırılırsa, dosya da o klasörde yaratılır.

DOSYANIN  AÇILMASI

Bir dosyaya yazmadan once, onu açmamız gereklidir. Açmak demek, sisteme o
dosyanın ismini bildirmek, ve yazmak veya okumak istedigimizi belirtmektir. Bunu,
“fopen” fonksiyonu ile yapiyoruz. “fp” isimli dosya pointer’i, bu açılan
dosyaya ait bazi bilgileri tutar. “fopen” ise, iki parametre gerektirir.
Birincisi, dosyanın ismidir. Linux kullanıyorsanız, işletim sistemi büyük küçük harf ayrımı yapar. Yani dosyayı yaratırken küçük harfle yarattıysanız, tekrar erişirken de küçük harfle açmanız gerekecektir.

OKUMAK “r”

“fopen” in ikinci parametresi ise, acilacak dosya ile ne yapilacagini belirtir. Buraya, “r” “w” yada “a” yazabiliriz. “r” kullanildiginda, kutugun okuma icin acilacagini belirtir. “w”, kutuge yazilacagini, ve “a”  ise zaten var olan bir kutuge bilgi ekleyeceginizi belirtir. Bir dosyayı okumak icin açmak icin, o kutugun diskte var olmasini geretirir. Şayet dosya yok ise, “fopen”, geriye NULL degerini dondurur.

YAZMAK “w”

Bir dosya yazmak icin açılınca, şayet diskte yoksa yaratilir, sayet varsa, içindeki bilgiler silinir.

EKLEMEK “a”

Bir dosya eklemek (append) modunda açıldığında, şayet yoksa yaratılır, varsa, veri giriş pointer’i bu dosyanın sonuna ayarlanır. Bu sayede yeni bilgi yazılınca, dosyanın sonuna yazilmış olur.

Tam listesi şudur:

r  - Dosyayı okumak için açmak
w - Dosyaya yazmak için açmak (dosyanın var olması gerekmez)
a - Dosyanın sonuna eklemek için açmak (dosyanın var olması gerekmez)
r+ - Dosyayı hem yazmak hem okumak için açmak, başından başlayarak
w+ - Dosyayı hem okumak hem yazmak için açmak (dosyayı siler)
a+ - Dosyayı hem okumak hem yazmak için açmak (dosya varsa sonuna ekler)

DOSYAYA YAZMAK

Bir dosyaya yazmak, ekrana yazmak ile neredeyse aynidir. En onemli farklar,
yeni fonksiyon isimleri, ve dosya pointer’inin bu fonksiyonlara parametre
olarak eklenmesidir. Ornek programda, “fprintf” komutu “printf” komutunun
yerini alir.

DOSYAYI KAPATMAK

Bir dosyayı kapatmak icin, sadece “fclose” komutunu kullanmak yeterlidir. Parametre olarak da dosyanın pointer’ini gecirmek yeterlidir. İşletim sistemi, program sona erince kullandigi dosyaları kapattigindan, “fclose” u kullanmak şart degildir, fakat bir aliskanlik yapmasi icin, kullandiginiz dosyaları kapatmanizi tavsiye ederim.

Bu programi calistirdiginizda, ekranda hicbir sey cikarmaz. Program bittikten sonra, “onsatir.txt” isimli dosyayı inceleyin. Icinde programin yazdigi on satirlik ciktiyi goreceksiniz.

KARAKTERLERI TEKER TEKER YAZMAK

KAROUT.C:
=============================================================
#include <stdio.h>
main()
{
FILE *dosyapoint; char digerleri[35]; int index,say;
strcpy(digerleri,"Ek satirlar.");
dosyapoint = fopen("onsatir.txt","a"); /* eklemek icin açmak */
   for (say = 1;say <= 10;say++) {
for (index = 0;digerleri[index];index++)
putc(digerleri[index],dosyapoint);/* bir karakter yaz*/
putc('\n',dosyapoint); /* bir de <RETURN> */
}
fclose(point);
}
=============================================================

Normal “include” satırımızdan sonra, “dosyapoint” isimli bir dosya pointeri
tanimliyoruz. Yazacagimiz bilgileri tutmasi icin, “digerleri” isminde bir
karakter dizisi tanimliyoruz. Daha sonra bu actigimiz sahaya,
“strcpy” fonksiyonu ile “Ek satirlar.” sozcugunu yaziyoruz. Bundan sonra,
yine ayni dosyayı “append” yani sonuna eklemek icin açıyoruz.

Bu program iki tane iç içe döngüden olusuyor. Dıştaki dongu, sadece birden
ona kadar sayiyor.. Içindeki dongu ise, yazilan karakter sıfır olmadigi
surece, “putc” fonksiyonunu cagirir.

“putc” FONKSIYONU

Bu programin ilgimizi ceken yonu, “putc” fonksiyonudur. Belirtilen dosyaya bir karakter yazan bu fonksiyon, ilk parametre olarak yazilacak karakteri, ikinci olarak da dosya pointer’ini veriyoruz. “Digerleri” isimli dizi bitince satirin sonuna bir <RETURN> karakteri koymak icin “putc” yi tekrar cagiriyoruz.

Dış dongu on kere tekrarlandiktan sonra, program dosyayı kapatip sona eriyor. Bu program calistiktan sonra dosyayı incelerseniz, gercektende sonuna 10 satir eklendigini gorursunuz.

BIR DOSYAYI OKUMAK

KAROKU.C:
================================================================

#include <stdio.h>
main()
{
FILE *dosya;
int c;
dosya = fopen("onsatir.txt","r");
if (dosya == NULL) printf("Boyle bir dosya yok\n");
else {
do {
c = getc(dosya); /* Bir karakter oku */
putchar(c); /* ekranda goster */
} while (c != EOF); /* Dosya sonuna (END OF FILE) a kadar devam */
}
fclose(dosya);
}
================================================================

Bir dosya okuyan ilk programimiz! “stdio.h” ve iki degisken tanimindan
sonra, “fopen” fonksiyonunda okumak icin “r” parametresini veriyoruz. Daha
sonra, dosya açmanin basarili olip olmadigini kontrol ediyoruz. Sayet
basarili degilse, geriye NULL degeri donecektir.

Program, bir “do while” dongusunun icinde tek bir karakter okuyup, ekrana
yaziyor. Bu dongu, ta ki, “getc” fonksiyonu dosyanın sonunu belirten EOF (end of file)
döndürene kadar sürer. EOF dönünce de, dosya kapatilir, ve program sona
erer.

KELIME KELIME OKUMAK

TEXTOKU.C:
============================================================
#include "stdio.h"
main()
{
FILE *fp1;
char birkelime[100];
int c;
fp1 = fopen("onsatir.txt","r");
do {
c = fscanf(fp1,"%s",birkelime); /* dosyadan bir kelime okuyalim */
printf("%s\n",birkelime); /* ekrana yazalim */
} while (c != EOF); /* ta ki EOF olana kadar */
fclose(fp1);
}
============================================================

Bu program, nerdeyse bir oncekinin aynisidir. Burada, kelime kelime okumak
icin “fscanf” fonksiyonunu kullaniyoruz, cunku “fscanf” fonksiyonu, bir
boşluğa gelince, okumayi birakir.

FAKAT BIR PROBLEM VAR

Programi inceleyince, verinin dosyadan okundugunu, ekrana yazildigini ve
daha sonra EOF olup olmadiginin kontrol edildigini goruyoruz. Bu nedenle,
istemedigimiz birsey ekrana yazilmis oluyor. Buyuk ihtimalle, programin
sonunda, en son kelimeyi bir daha yaziyoruz – cunku zaten “birkelime” nin
icinde idi o deger.

Buna mani olmak icin, bir baska program gorelim. Ismi IYIOKU.C olsun:

IYIOKU.C:
================================================================

#include "stdio.h"
main()
{
FILE *fp1;
char birkelime[100];
int c;
fp1 = fopen("onsatir.txt","r");
do {
c = fscanf(fp1,"%s",birkelime); /* dosyadan bir kelime oku... */
if (c != EOF)
printf("%s\n",birkelime); /* ekrana yaz... */
} while (c != EOF); /* ta ki EOF olana dek.. */
fclose(fp1); /* dosyayı kapa */
}
================================================================

Gordugunuz gibi, bir “if” komutu ile, sayet dosyanın sonuna gelip
gelmedigimize bakiyoruz. Aslinda bu problem KAROKU.C da da vardi, fakat
orada pek gorunmuyordu.

SONUNDA, BUTUN BIR SATIR OKUYORUZ

SATIROKU.C:
================================================================
#include "stdio.h"
main()
{
FILE *fp1;
char birsatir[500]; /* olabilecek en uzun satıra göre */
char *c;
fp1 = fopen("onsatir.txt","r");
do {
c = fgets(birsatir,500,fp1); /* bir satir okuyalim */
if (c != NULL)
printf("%s",birsatir); /* ekrana yazalim */
} while (c != NULL); /* ta ki NULL olana kadar.*/
fclose(fp1);
}

================================================================

Bu program, simdiye de gorduklerimize benziyor, fakat NULL isimli yeni bir
nesne de katildi.

“fgets” fonksiyonu ile, bir butun satiri, ve sonundaki yeni satir
karakterini (\n), bir diziye okur. Ilk parametre olarak, donen karakterleri
koyacagimiz yerin adresi tanimlanir, ikinci parametrede en fazla kac
karakter okunmasina izin verecegimizi belirtiyoruz, ve son olarak da dosya
degiskeninin ismini veriyoruz.

Yani bu fonksiyon, ya bir yeni satir karakterine rastlayana kadar, yada
izin verilen karakter sayısı eksi bir kadar okur. Eksi birin sebebi ise,
stringin sonunu belirten (\0) sifir değerine yer bırakmasıdır.
Tabi sonunda, dosyayı kapatiyoruz..

DEGISKEN DOSYA ISMI

HERDOSYA.C:
============================================================
#include "stdio.h"
main()
{
FILE *fp1;
char birsatir[100],dosyaismi[25];
char *c;
printf("Dosya ismini girin -> ");
scanf("%s",dosyaismi); /* dosya ismini alalim */
fp1 = fopen(dosyaismi,"r");
do {
c = fgets(birsatir,100,fp1); /* dosyadan bir satir okuyalim */
if (c != NULL)
printf("%s",birsatir); /* ekrana yazalim */
} while (c != NULL); /* ta ki NULL olana kadar */
fclose(fp1);
}
=============================================================

Burada, ilk once kullanicidan “scanf” ile dosya ismini kullanicidan
aliyoruz, daha sonra dosyayı acip, satir satir ekrana yaziyoruz.

YAZICIYA NASIL BIRSEY YOLLAYABILIRIZ

PRINTDAT.C:
=============================================================
#include "stdio.h"
main()
{
FILE *guzel,*printer;
int c;
guzel = fopen("onsatir.txt","r"); /* dosyayı acalim */
printer = fopen("PRN","w"); /* printeri acalim */
do {
c = getc(guzel); /* dosyadan bir karakter okuyoruz */
if (c != EOF) {
putchar(c); /* ekranda goruntuleyelim */
putc(c,printer); /* ve yaziciya yollayalim */
}
} while (c != EOF); /* ta ki (End Of File) dosya bitene kadar */
fclose(guzel);
fclose(printer);
}
=============================================================

Okumak icin, “onsatir.txt” yi actiktan sonra, yazmak icin “PRN” isimli
dosyayı aciyoruz. Printere bir bilgi yollamak, ayni bir dosyaya yazmak
gibidir, fakat standart bir dosya ismi kullanmak zorundayiz. Bu konuda
kesin standartlar yoktur, fakat genellikle bu isimler “PRN” , “LPT”,
“LPT1” yada “LPT2” dir.

Bazi yeni derleyicilerin, “stdprn” diye, onceden tanimli bir dosya tanimliyicilari vardir. Bu sayede, siz printer’i bir dosya gibi açmadan, ona veri yollayabilirsiniz.

Program, birer birer butun dosyayı okuyup, ekranda gosterir, ve printer’e yollar. EOF , dosya sonu bulundugunda, dosyalar kapanir, ve program biter.

Yazıcıdan çıktıya bakın, çok acaip çıktıysa özel printer kodlarını kullanmadan yazıcıya olduğu gibi gönderdiğimiz içindir. Yazıcıların özel dilleri vardır, Postscript gibi örneğin. Bu dillerle gönderirseniz farklı yazı türleri, grafikler vs gibi herşeyi yazdırmak mümkündür.

BİNARY (BİNER) OKUMA VE YAZMA

Bazen dosyaya bilgileri olduğu gibi yazmak, ve hatta ASCII kodları 0-31 yada 127-255 arası bilgiler girmek isteyebilirsiniz. Bunlara binary bilgiler denir. Örneğin bir programın derlenmiş hali, bir MP3 parça yada bir JPG resim binary verilere örnektir. Yani 8-bit verilerle çalışmak istiyorsanız Binary gerekebilir.

Bir dosyayı “binary” olarak açmak isterseniz, bunu fopen() a bildirmeniz gereklidir. Bunu da fopen’ın ikinci parametresine “b” harfini ekleyerek yapabilirsiniz. “rb” yada “wb” gibi örneğin.

Bunları okumak için C de  genelde “fread” kullanılır, yazmak için ise  “fwrite” kullanılır. İki fonksiyon da veri blokları ile çalışır yani bellekten arka arkaya kısımları okur yada yazar. Genelde array (dizin) ler kullanılır. Bunlara parametre olarak adres girildiğinden, dilerseniz pointer geçirebilirsiniz yada  daha sonra göreceğimiz structure ları bile diske bunlarla yazabilir yada okuyabilirsiniz.

Tanımı:

size_t fread(void *ptr, size_t size_of_elements, size_t number_of_elements, FILE *a_file);       
size_t fwrite(const void *ptr, size_t size_of_elements, size_t number_of_elements, FILE *a_file);

Buradaki void *ptr lafı, herhangi bir cins pointer konabileceği belirtilmek için konmuştur, karakter pointer yada integer pointer gibi. fread’in 4 parametresi vardır. Birincisi, sizin dizinin (array) adresidir. İkincisi, dizinin her elemanının boyudur. Üçüncü ise, dizide kaç tane eleman olduğudur. Sonuncu parameter ise malum dosya pointer’ımızdır.

Örnek:

===========================================================
#include <stdio.h>
main() {
	FILE *fp;
	char x[10]="ABCDEFGHIJ";
	fp=fopen("c:\\test.bin", "wb");
	fwrite(x, sizeof(x[0]), 10, fp);
	fclose(fp);
}

===============================================================

ODEVLER:

1. Okunacak, yazilacak dosyaların isimlerini kullaniciya soran, daha sonra
bu ikisini ve printer dosyası açan bir program yazin. Program bunlari
actiktan sonra, dosya sonu gelinceye kadar okunacak dosyayı harf harf
okuyup, yazilacak dosyaya ve yaziciya bu karakteri yollamalidir.

2. Programiniz, kullaniciya bir dosya ismi sorsun, cevabi alinca da, bu
dosyayı ekranda, satir numaralari ile birlikte gostersin..

Bir Sonraki Konu