---
title: 'Dosya Sistemi'
source: 'https://academia.sh/tr/kurslar/nodejs/dosya-sistemi'
course: 'Node.js Çalışma Zamanı'
language: tr
updated: '2026-08-17T18:09:51+00:00'
license: 'CC BY-SA 4.0'
---

# Dosya Sistemi

Aynı işi sunan üç arayüzün farkı, iş parçacığı havuzunun rolü, hata kodlarıyla dallanma, dizin işlemleri ve yarım yazılmış dosya bırakmayan güncelleme.

Çalışma zamanı modeli konusu, engelleyen işin olay döngüsünü nasıl durdurduğunu
ölçtü. Dosya sistemi arayüzü bu ölçünün doğrudan uygulama alanıdır: aynı okuma işi
için üç ayrı çağrı biçimi sunulur ve üçü olay döngüsüne farklı davranır.

Bu ders üç biçimi karşılaştırır, hangi durumda hangisinin doğru olduğunu belirler ve
ölçüm toplayıcının ilk gerçek adımını yazar: dosyayı okuyup özetini üretmek.

## Üç Arayüz

Yerleşik dosya sistemi modülü aynı işlemleri üç ayrı biçimde sunar. Eşzamanlı biçim
`node:fs` modülünde `Sync` sonekiyle, geri çağrılı biçim aynı modülde soneksiz,
söz tabanlı biçim ise `node:fs/promises` modülünde bulunur.

```js
// fs-uc-arayuz.mjs
import { readFileSync, readFile } from 'node:fs';
import { readFile as readFileSoz } from 'node:fs/promises';

const dosya = 'olcumler.ndjson';
const satirSay = (metin) => metin.trim().split('\n').length;

// 1. Eszamanli
console.log('eszamanli :', satirSay(readFileSync(dosya, 'utf8')));

// 2. Geri cagrili
readFile(dosya, 'utf8', (hata, metin) => {
  if (hata) throw hata;
  console.log('geri cagri:', satirSay(metin));
});

// 3. Soz tabanli
readFileSoz(dosya, 'utf8').then((metin) => {
  console.log('soz       :', satirSay(metin));
});

console.log('senkron akis burada devam etti');
```

```sh
node fs-uc-arayuz.mjs
```

```
eszamanli : 12
senkron akis burada devam etti
geri cagri: 12
soz       : 12
```

Çıktının sırası üç biçimin farkını gösterir. Eşzamanlı çağrı, sonucu döndürene kadar
sürecin ilerlemesini durdurdu; sonucu ikinci satırdan önce yazdı. Diğer ikisi işi
başlatıp geri döndü, bu yüzden `senkron akis burada devam etti` satırı onların
sonucundan önce göründü.

Geri çağrılı biçimin imzası bir sözleşme taşır: ilk parametre hatadır, sonuç ikinci
parametredir. Hata yoksa ilk parametre `null` gelir. Bu düzen, sözler dile girmeden
önce eşzamansız işin tek yoluydu ve yerleşik modüllerin çoğunda hâlâ bulunur.

Söz tabanlı biçim aynı işi `async`/`await` ile sıralı okunabilir hâle getirir. Kurs
boyunca varsayılan seçim budur.

Seçim kuralı şudur:

- **Eşzamanlı biçim**, olay döngüsü henüz iş görmüyorken kullanılır: başlangıçtaki
  yapılandırma okuması, tek seferlik bir betiğin gövdesi, kapanış anındaki son
  eşzamanlı yazma. Bir isteği işlerken kullanılmaz.
- **Söz tabanlı biçim**, hizmet kodunun varsayılanıdır.
- **Geri çağrılı biçim**, söz sarmalayıcısının maliyetinden kaçınmak gereken sıcak
  yollarda ve söz tabanlı karşılığı olmayan çağrılarda kullanılır.

## Eşzamansızlık Nereden Geliyor

Ağ soketleri için beklemeyi çekirdeğin bildirim düzeneği üstlenir; süreç yoklama
aşamasında uyur ve veri geldiğinde uyanır. Dosya sisteminde durum farklıdır: yaygın
işletim sistemlerinde sıradan dosyalar için karşılaştırılabilir bir bildirim düzeneği
yoktur.

Çalışma zamanı bu boşluğu bir **iş parçacığı havuzu (thread pool)** ile doldurur.
Dosya okuma, yazma ve dizin listeleme çağrıları havuzdaki bir iş parçacığına verilir;
o iş parçacığı engelleyen sistem çağrısını yapar, iş bitince sonuç ana iş parçacığının
kuyruğuna bırakılır. Ana iş parçacığı bu sırada başka istekleri işlemeye devam eder.

İki sonucu vardır. Birincisi, dosya işlemleri gerçekten paralel yürür; ikincisi,
havuzun sabit bir genişliği vardır. Aynı anda havuz genişliğinden çok dosya işlemi
başlatılırsa fazlası sıraya girer. Havuz genişliği bir ortam değişkeniyle
ayarlanabilir; ölçmeden değiştirmek yarar sağlamaz.

## Hata Kodlarıyla Dallanma

Dosya sistemi hataları, iletileriyle değil `code` alanlarıyla ayırt edilir. İleti
metni okunabilirlik içindir ve değişebilir; kod, işletim sisteminin sistem
çağrısından döndürdüğü ada karşılık gelir.

```js
// fs-hata.mjs
import { readFile } from 'node:fs/promises';

async function guvenliOku(yol) {
  try {
    return await readFile(yol, 'utf8');
  } catch (hata) {
    if (hata.code === 'ENOENT') return '';       // dosya yok: bos veri
    if (hata.code === 'EACCES') {                 // izin yok: cagirana birak
      throw new Error(`okuma izni yok: ${yol}`, { cause: hata });
    }
    throw hata;
  }
}

console.log('var olan  :', (await guvenliOku('olcumler.ndjson')).length, 'karakter');
console.log('olmayan   :', (await guvenliOku('yok.ndjson')).length, 'karakter');

try {
  await readFile('yok.ndjson', 'utf8');
} catch (hata) {
  console.log('kod:', hata.code, '| cagri:', hata.syscall, '| yol:', hata.path);
}
```

```sh
node fs-hata.mjs
```

```
var olan  : 1000 karakter
olmayan   : 0 karakter
kod: ENOENT | cagri: open | yol: yok.ndjson
```

`ENOENT` (dosya yok), `EACCES` (izin yok), `EISDIR` (dizin verildi), `ENOSPC`
(disk dolu) ve `EMFILE` (açık dosya sınırı aşıldı) en sık karşılaşılanlardır. Linux'a
Giriş kursundaki izin modeli, `EACCES` hatasının ne zaman geleceğini belirler:
sürecin kullanıcı kimliği ve grup üyeliği dosyanın izin bitleriyle karşılaştırılır.

Yakalanan her hatanın yutulmaması önemlidir. Yukarıdaki fonksiyon yalnızca bildiği iki
durumu ele alıyor, geri kalanı olduğu gibi yukarı fırlatıyor. Bilinmeyen bir kodu
sessizce boş veriye çevirmek, arızayı gizler.

## Dizin İşlemleri

Dizin oluşturma, listeleme ve silme aynı modülde bulunur. Aşağıdaki blok örnek ağacı
kendi kurar, sonra listeler:

```js
// fs-dizin.mjs
import { mkdir, writeFile, readdir, stat, rm, readFile } from 'node:fs/promises';

// Örnek ağacı bu blok kendisi kurar
await rm('veri', { recursive: true, force: true });
await mkdir('veri/2024-02-07/ham', { recursive: true });   // ara dizinleri de acar
await writeFile('veri/2024-02-07/olcumler.ndjson', await readFile('olcumler.ndjson'));
await writeFile('veri/2024-02-07/not.txt', 'kenar-03 dugumu sabahtan beri sicak\n');

const girdiler = await readdir('veri/2024-02-07', { withFileTypes: true });
for (const girdi of girdiler.sort((a, b) => a.name.localeCompare(b.name))) {
  if (girdi.isDirectory()) {
    console.log(`dizin     - ${girdi.name}`);
  } else {
    const { size } = await stat(`veri/2024-02-07/${girdi.name}`);
    console.log(`dosya ${String(size).padStart(5)} ${girdi.name}`);
  }
}
```

```sh
node fs-dizin.mjs
```

```
dizin     - ham
dosya    36 not.txt
dosya  1000 olcumler.ndjson
```

`recursive` seçeneği iki yerde geçiyor ve iki farklı işi yapıyor. `mkdir` çağrısında
ara dizinleri açar ve dizin zaten varsa hata vermez; bu, işlemi yinelemeye dayanıklı
kılar. `rm` çağrısında ise alt ağacın tamamını siler — `force` ile birlikte, hedef
yoksa da hata vermez.

`rm` çağrısı geri alınamaz. Linux'a Giriş kursunda kabuk için söylenen kural burada
da geçerlidir: silinecek yolu bir değişkenden alıyorsanız, silmeden önce yolun
beklediğiniz kök altında kaldığını doğrulayın. Bu doğrulamanın nasıl yazıldığı
sonraki dersin konusudur.

`readdir` çağrısındaki `withFileTypes` seçeneği, adların yanında tür bilgisini de
getirir; onsuz her ad için ayrı bir `stat` çağrısı gerekirdi. Dönen girdilerin sırası
dosya sistemine bağlıdır ve alfabetik olduğu varsayılamaz — örnekteki sıralama
bunun içindir.

## Yarım Dosya Bırakmadan Yazmak

Ölçüm toplayıcının ilk çıktısı, düğüm ve metrik başına özet üreten bir dosyadır.
Doğrudan hedef dosyanın üzerine yazmak bir risk taşır: yazma sırasında süreç
sonlanırsa dosya yarım kalır ve onu okuyan program bozuk veri görür.

Çözüm, geçici bir ada yazıp tamamlandığında yerine koymaktır. Aynı dosya sistemi
içinde ad değiştirme işlemi bölünmez: okuyucular ya eski dosyanın tamamını ya yeni
dosyanın tamamını görür.

```js
// ozetle.mjs
import { readFile, writeFile, rename, stat } from 'node:fs/promises';

async function ozetle(kaynak, hedef) {
  const metin = await readFile(kaynak, 'utf8');
  const kova = new Map();

  for (const satir of metin.split('\n')) {
    if (satir.trim() === '') continue;
    const { dugum, metrik, deger } = JSON.parse(satir);
    const anahtar = `${dugum}/${metrik}`;
    const kayit = kova.get(anahtar) ?? { sayi: 0, toplam: 0 };
    kayit.sayi += 1;
    kayit.toplam += deger;
    kova.set(anahtar, kayit);
  }

  const ozet = [...kova].map(([anahtar, { sayi, toplam }]) => ({
    anahtar,
    sayi,
    ortalama: Number((toplam / sayi).toFixed(2)),
  }));

  // Yarim yazilmis dosya birakmamak icin once gecici ada yaz, sonra yerine koy
  const gecici = `${hedef}.gecici`;
  await writeFile(gecici, JSON.stringify(ozet, null, 2) + '\n');
  await rename(gecici, hedef);

  const bilgi = await stat(hedef);
  return { kayitSayisi: ozet.length, bayt: bilgi.size };
}

const sonuc = await ozetle('olcumler.ndjson', 'ozet.json');
console.log(`${sonuc.kayitSayisi} ozet kaydi, ${sonuc.bayt} bayt yazildi`);
```

```sh
node ozetle.mjs
```

```
6 ozet kaydi, 477 bayt yazildi
```

Geçici dosya hedefle **aynı dizinde** oluşturulmalıdır. Farklı dosya sistemlerine
yayılan bir ad değiştirme işlemi bölünmez değildir; çekirdek onu kopyala–sil olarak
yürütür ve güvence ortadan kalkar.

Bu yaklaşımın sınırı da vardır: veri ancak süreç bittikten sonra değil, ad değiştirme
işleminden sonra görünür hâle gelir, ama diske gerçekten yazıldığı an işletim sistemi
önbelleğine bağlıdır. Elektrik kesintisine karşı dayanıklılık gerekiyorsa dosya
tanıtıcısı üzerinden eşitleme çağrısı yapılır; sıradan hizmetlerde bu ek maliyet
genellikle üstlenilmez.

Üretilen `ozet.json` dosyası kurs boyunca hizmetin sunacağı içeriktir; sonraki
derslerde aynı özet, önce akışlarla, sonra HTTP üzerinden üretilecek.

## Özet

- Dosya sistemi işlemleri üç arayüzle sunulur: eşzamanlı, geri çağrılı ve söz
  tabanlı. Eşzamanlı biçim yalnızca olay döngüsü iş görmüyorken kullanılır.
- Dosya işlemlerinin eşzamansızlığı iş parçacığı havuzundan gelir; havuz sabit
  genişliktedir ve aşırı eşzamanlı istek sıraya girer.
- Hatalar `code` alanıyla ayırt edilir; ileti metnine dayanan dallanma kırılgandır.
- `mkdir` çağrısındaki özyineli seçenek işlemi yinelemeye dayanıklı kılar; `readdir`
  çağrısının döndürdüğü sıra dosya sistemine bağlıdır.
- Bir çıktı dosyası, geçici ada yazılıp aynı dizin içinde ad değiştirilerek
  güncellendiğinde okuyucular hiçbir zaman yarım içerik görmez.

## Sonraki Adım

Bu dersteki bütün yollar çalışma dizinine göre yazıldı; program başka bir dizinden
çağrıldığında dosyayı bulamaz. Ayrıca ayırıcı karakteri elle yazmak, aracı tek bir
platforma bağlar. Sonraki ders yol kurmayı ele alır: parçaları birleştirmenin,
göreli yolu mutlak yapmanın ve bir kullanıcı girdisinin kök dizin dışına çıkmadığını
doğrulamanın kuralları.
