Bildirim
size_t fread(void *ptr, size_t size, size_t count, FILE *stream);
Açıklama
Her biri size parametre değeri kadar bayt boyutunda olan count parametre değeri kadar elemanı stream parametresi ile gösterilen akıştan okur ve bunları ptr parametresi ile gösterilen belleğe yükler.
Akışın konum göstergesi, okunan toplam bayt miktarı kadar (size * count) ile ileri alınır.
Bu fonksiyon akıştan bir karakter dizisi okuduğunda, karakter dizisinin sonuna otomatik olarak boş sonlandırıcı karakteri ('\0') eklemediğinden, bu karakterin program ile ayrıca eklenmesi gerekir.
Parametreler
ptr: Minimum boyutu size * count kadar olan bir bellek bloğunu gösteren işaretçidir.
size: Okunacak olan her bir elemanın boyutunu gösterir.
count: Okunacak eleman sayısını gösterir.
stream: Karakterlerin okunacağı akışı tanımlayan FILE nesnesi işaretçisidir.
Dönüş değeri
Başarıyla okunan toplam öğe sayısı geri döndürülür.
Eğer bu sayı count parametresinden farklıysa, okuma esnasında okuma hatası oluşur veya dosyanın sonuna ulaşılır. Her iki durumda da, sırasıyla ferror() ve feof() fonksiyonları ile kontrol edilebilen uygun gösterge ayarlanır.
Eğer size veya count parametrelerinden birisi sıfır ise, fonksiyon sıfır değeri döndürür ve hem akış durumu hem de ptr ile gösterilen bellek içeriği değişmeden kalır.
Örnek
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
FILE *fp;
char cdizi[]="Bilgisayar";
char gdizi[40];
if ((fp=fopen("dosya.txt", "w+")) == NULL) {
printf("Dosya açılamadı!\n");
exit(1);
}
if (fwrite(cdizi, strlen(cdizi), 1, fp) != 1) {
printf("Dosyaya yazma hatası!\n");
exit(1);
}
rewind(fp);
if (fread(gdizi, strlen(cdizi), 1, fp) != 1) {
printf("Dosyadan okuma hatası!\n");
exit(1);
}
/* Okunan karakter dizisi sonuna boş karakter ekleme */
gdizi[strlen(cdizi)] = '\0';
printf("%s", gdizi);
fclose(fp);
return 0;
}
Yukarıdaki örnekte, program aşağıdaki satırı ekrana yazar:
Bilgisayar
Yukarıdaki program, yazma ve okuma modunda (w+) açtığı dosyaya fwrite() fonksiyonu ile yazdığı karakter dizisini, dosyanın konumunu başa aldıktan sonra, fread() fonksiyonu ile dosyadan okuyarak, sonuna boş karakter ekledikten sonra, ekrana yazar.
Örnek
Aşağıdaki program, örnek bir dosya oluşturur (ornek_metin_dosyasi.txt) ve içine metin yazar. dosya_oku() fonksiyonu ile dosya içeriğini okur ve ekrana yazar. İşlem bittiğinde free() fonksiyonu ile ayrılan belleği serbest bırakır.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
// Fonksiyon prototipi
char *dosya_oku(const char *dosya_adi, unsigned long *boyut);
int main(void)
{
const char *dosya_adi = "ornek_metin_dosyasi.txt";
unsigned long dosya_boyutu = 0;
char *dosya_icerigi = NULL;
setlocale(LC_ALL, "Turkish");
// 1. Deneme dosyası oluşturma (Eğer yoksa)
// Bu kısım sadece kodun test edilebilmesi için eklenmiştir.
FILE *f_test = fopen(dosya_adi, "w");
if (f_test) {
fprintf(f_test, "Bu bir deneme metnidir.\n");
fprintf(f_test, "Dosyanın içeriği tek seferde okunacak.\n");
fclose(f_test);
}
else {
fprintf(stderr, "Hata: Deneme dosyası oluşturulamadı (%s).\n", dosya_adi);
return 1;
}
// 2. Dosyayı okuma fonksiyonunu çağırma
dosya_icerigi = dosya_oku(dosya_adi, &dosya_boyutu);
if (dosya_icerigi) {
printf("Dosya başarıyla okundu:\n");
printf("Boyut: %lu byte\n", (unsigned long) dosya_boyutu);
// Okunan veriyi ekrana basıyoruz.
// String olarak sonlandırmak için eklenen NULL karakteri dahil etmiyoruz.
printf("İçerik:\n%s\n", dosya_icerigi);
// 3. Ayrılan belleği serbest bırakma
free(dosya_icerigi);
}
else {
fprintf(stderr, "Dosya okuma işlemi başarısız oldu veya dosya boş.\n");
}
// 4. Deneme dosyasını silme (İsteğe bağlı)
// remove(dosya_adi);
return 0;
}
/*
* Belirtilen dosyayı okur, içeriğini belleğe yükler ve bellek adresini döndürür.
* Hata durumunda NULL döndürür.
* @param dosya_adi Okunacak dosyanın adı.
* @param boyut Okunan dosyanın boyutunun yazılacağı size_t işaretçisi.
* @return Dosya içeriğini içeren bellek bloğunun işaretçisi (veya hata durumunda NULL).
*/
char *dosya_oku(const char *dosya_adi, unsigned long *boyut) {
FILE *dosya;
char *buffer = NULL;
long dosya_uzunlugu = 0;
unsigned long okunan_byte = 0;
// 1. Dosyayı ikili (binary) okuma modunda aç
dosya = fopen(dosya_adi, "rb");
if (dosya == NULL) {
fprintf(stderr, "Hata: Dosya açılamadı (%s).\n", dosya_adi);
return NULL;
}
// 2. Dosya boyutunu al
// a. Dosyanın sonuna git
if (fseek(dosya, 0, SEEK_END) != 0) {
fprintf(stderr, "Hata: fseek() başarısız oldu.\n");
fclose(dosya);
return NULL;
}
// b. Konumu al (bu dosya boyutudur)
dosya_uzunlugu = ftell(dosya);
if (dosya_uzunlugu == -1) {
perror("Hata: ftell() başarısız oldu"); // ftell hatasını daha detaylı yazdırır.
fclose(dosya);
return NULL;
}
// c. Dosyanın başına geri dön
if (fseek(dosya, 0, SEEK_SET) != 0) {
fprintf(stderr, "Hata: fseek() başarısız oldu (başa dönüş).\n");
fclose(dosya);
return NULL;
}
// Güvenlik: Uzunluk 0 veya negatif mi?
if (dosya_uzunlugu <= 0) {
fprintf(stderr, "Uyarı: Dosya boş veya geçersiz uzunlukta (%ld byte).\n", dosya_uzunlugu);
*boyut = 0;
fclose(dosya);
// Boş dosya için NULL döndür (veya isteğe bağlı olarak boş bir string/buffer döndürülebilir)
// Burada NULL döndürmeyi tercih ettik.
return NULL;
}
// 3. Dosya boyutu kadar bellek ayır (+1, string sonlandırma karakteri '\0' için)
// Dosya içeriğini bir C string'i olarak kullanmak için '\0' eklenir.
buffer = (char *)malloc(dosya_uzunlugu + 1);
if (buffer == NULL) {
fprintf(stderr, "Hata: Bellek ayırma (malloc) başarısız oldu.\n");
fclose(dosya);
return NULL;
}
// 4. Dosya içeriğini tek seferde oku
// fread(bellek_adresi, bir_elemanin_boyutu, okunacak_eleman_sayisi, dosya_isaretcisi)
okunan_byte = fread(buffer, 1, dosya_uzunlugu, dosya);
// 5. Okuma hata kontrolü
if (okunan_byte != (unsigned long)dosya_uzunlugu) {
if (feof(dosya)) {
// feof() fonksiyonu dosyanın sonuna ulaşıldığını kontrol eder.
// Bu durumda, okunan_byte dosya_uzunlugu'ndan küçükse, dosya beklenenden kısadır
// veya okuma başarısız olmuştur (ancak bu senaryoda okunan_byte > 0 olmalıdır).
// Eğer okunan_byte < dosya_uzunlugu ise ve feof() doğru ise,
// dosya okuma işlemi sırasında dosya beklenenden kısa bitmiştir (örneğin dosya boyutu değişmiş olabilir).
fprintf(stderr, "Uyarı: Dosya sonuna ulaşıldı,\
ancak beklenen boyutta (%ld byte) okuma yapılamadı (Okunan: %lu byte).\n",
dosya_uzunlugu, okunan_byte);
}
else if (ferror(dosya)) {
// ferror() fonksiyonu okuma sırasında bir hata (örneğin disk hatası) oluşup oluşmadığını kontrol eder.
perror("Hata: fread() sırasında I/O hatası oluştu");
free(buffer);
fclose(dosya);
return NULL;
}
// Eğer okunan_byte < dosya_uzunlugu ise ve feof()/ferror() yanlışsa,
// bu da bir hata durumu olabilir, ancak çoğu zaman dosya beklenenden kısa çıktıysa feof() doğru olur.
}
// 6. Bellek bloğuna string sonlandırma karakteri ekle (metin dosyası için önemli)
buffer[okunan_byte] = '\0';
// 7. Dosyayı kapat
fclose(dosya);
// 8. Okunan boyutu *boyut değişkenine yaz
*boyut = okunan_byte;
// 9. Buffer'ın işaretçisini döndür
return buffer;
}
Yukarıdaki örnekte, program aşağıdaki satırı ekrana yazar:
Dosya başarıyla okundu: Boyut: 65 byte İçerik: Bu bir deneme metnidir. Dosyanın içeriği tek seferde okunacak.