---
title: 'Dosya Sistemi'
source: 'https://academia.sh/tr/kurslar/ios-veri-ve-ag/dosya-sistemi'
course: 'Veri, Ağ ve Eşzamanlılık'
language: tr
updated: '2026-10-21T05:03:09+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Verinin türüne göre doğru dizini seçmeyi ayırır'
    - 'Dosyaya sona eklemenin hem yinelemeye hem sıraya duyarlı olduğunu ölçer'
    - 'Atomik yazmanın yinelemeyi çözüp sırayı çözmediğini doğrular'
    - 'Dizin oluşturmanın sağlam olduğunu ve dosya varlığına bağlı işlemlerin başlangıca duyarlı olduğunu gösterir'
---

# Dosya Sistemi

Büyük verilerin dosyalara yazıldığı yerde sona eklemenin, tam değiştirmenin ve dizin oluşturmanın yineleme ve sıra duyarlılığının ölçümü.

Tercih deposu küçük değerler, anahtarlık gizli değerler içindi. Bir belge, bir dışa aktarma dosyası, bir günlük ya da indirilmiş bir görsel gibi daha büyük veriler **dosya sistemi**ne yazılır. Dosya sisteminin sunduğu şey bir anahtar-değer eşlemesi değil, yol ve bayt dizisidir. Bu yüzden işlemleri iki gruba ayrılır: dosyanın içeriğini değiştirenler ve dizin yapısını değiştirenler. Kursun sorusu bu ikisinde de aynıdır: **bu işlem yinelenirse ya da sırası değişirse sonuç değişir mi?**

```swift
// Replay.swift — bir islemin yinelemeye ve siraya duyarliligini siniflandirir
struct Trial<State: Equatable & CustomStringConvertible> {
    let label: String
    let once: State
    let twice: State
    let forward: State
    let backward: State

    var sensitivity: String {
        switch (once != twice, forward != backward) {
        case (false, false): return "saglam"
        case (true, false): return "yinelemeye-duyarli"
        case (false, true): return "siraya-duyarli"
        case (true, true): return "cift-duyarli"
        }
    }

    func report() -> String {
        print("\(label) | bir=\(once) iki=\(twice) ab=\(forward) ba=\(backward) -> \(sensitivity)")
        return sensitivity
    }
}

func replay<State>(_ label: String, from start: State, _ a: (State) -> State, then b: (State) -> State) -> Trial<State> {
    Trial(label: label, once: a(start), twice: a(a(start)), forward: b(a(start)), backward: a(b(start)))
}

func countSensitivities(_ results: [String]) {
    for name in ["saglam", "yinelemeye-duyarli", "siraya-duyarli", "cift-duyarli"] {
        print("\(name): \(results.filter { $0 == name }.count)")
    }
}
```

`bir` işlemin başlangıç durumuna bir kez, `iki` iki kez uygulanmasıdır; `ab` önce `a` sonra `b`, `ba` ise tersi sıradır. Bu derste ölçülen işlemler bir dizin ve dosya ağacının saf Swift modeline uygulanır. Model diske hiçbir şey yazmaz ve platformun kendisi değildir.

## Hangi Veri Hangi Dizine

Uygulamanın dosya yazabildiği yerler amaçlarına göre ayrılır. Belgeler dizini kullanıcının ürettiği ve kaybolmaması gereken veri içindir; yedeklemeye girer. Destek dizini uygulamanın kullanıcıya göstermediği ama yeniden üretemeyeceği veriler içindir. Önbellek dizini yeniden üretilebilen veri içindir ve sistem yer gerektiğinde onu temizleyebilir. Geçici dizin bundan da kısa ömürlüdür.

```swift
import Foundation

let documents = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let caches = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]

var exports = documents.appendingPathComponent("exports", isDirectory: true)
try FileManager.default.createDirectory(at: exports, withIntermediateDirectories: true)

var values = URLResourceValues()
values.isExcludedFromBackup = true
try exports.setResourceValues(values)

let target = exports.appendingPathComponent("settings")
try Data("v1".utf8).write(to: target, options: .atomic)
```

Bu parça KAYNAK'tır; gerçek bir uygulama dizini gerektirdiği için burada koşmaz. Dört ayrıntı okunur. `createDirectory` çağrısı `withIntermediateDirectories: true` ile dizin zaten varsa hata vermez. `isExcludedFromBackupKey` anahtarına karşılık gelen özellik, bir dosyayı ya da dizini yedeklemenin dışında bırakır; yeniden indirilebilen veri için kullanılır. `.atomic` seçeneği veriyi önce geçici bir dosyaya yazar, sonra hedefin yerine koyar. Önbellek dizininin ne zaman temizleneceğini sistem seçer; bu ders onu ölçmez.

## Dosya Ağacının Modeli

Model, dizinlerin bir kümesini ve her dosya için satırların listesini tutar. Çıktıda dizinler ve dosyalar sıralı basılır; boş küme `-` olarak görünür.

```swift
// FolderModel.swift — dizin ve dosya agacinin saf Swift modeli
struct FolderBox: Equatable, CustomStringConvertible {
    private(set) var directories: Set<String>
    private(set) var files: [String: [String]]

    init(directories: Set<String> = [], files: [String: [String]] = [:]) {
        self.directories = directories
        self.files = files
    }

    var description: String {
        let dirText = directories.isEmpty ? "-" : directories.sorted().joined(separator: ",")
        let fileText = files.isEmpty ? "-" : files.keys.sorted().map { "\($0)=\(files[$0]?.joined(separator: "+") ?? "")" }.joined(separator: ",")
        return "dizin:\(dirText) dosya:\(fileText)"
    }

    mutating func ensureDirectory(_ path: String) { directories.insert(path) }
    mutating func append(_ line: String, to path: String) { files[path, default: []].append(line) }
    mutating func appendIfPresent(_ line: String, to path: String) {
        if files[path] != nil { files[path]?.append(line) }
    }
    mutating func writeAtomically(_ text: String, to path: String) { files[path] = [text] }
}

func ensuring(_ path: String) -> (FolderBox) -> FolderBox {
    { box in
        var next = box
        next.ensureDirectory(path)
        return next
    }
}

func appending(_ line: String, to path: String) -> (FolderBox) -> FolderBox {
    { box in
        var next = box
        next.append(line, to: path)
        return next
    }
}

func appendingIfPresent(_ line: String, to path: String) -> (FolderBox) -> FolderBox {
    { box in
        var next = box
        next.appendIfPresent(line, to: path)
        return next
    }
}

func writing(_ text: String, to path: String) -> (FolderBox) -> FolderBox {
    { box in
        var next = box
        next.writeAtomically(text, to: path)
        return next
    }
}
```

Model iki yazma biçimini ayırır. `append` dosyanın sonuna bir satır ekler; mevcut içerik korunur. `writeAtomically` dosyanın içeriğini tamamen yenisiyle değiştirir; yarım yazılmış bir ara durum görünmez. Gerçek platformda atomik yazma bir geçici dosya ve bir yer değiştirme ile yapılır. Modelde yalnız bu işlemin sonucu kurulur.

**KL7.** Model, bir yazmanın ya tamamen görüldüğünü ya da hiç görülmediğini varsayar. Yazma sırasında uygulamanın kesilmesi ve yarım dosya kalması kurulmadı.

**KL8.** Model, dosya adlarını düz yol dizgisi olarak tutar. Dizinin dosyadan önce var olması gerekmez; gerçek yazmada üst dizin yoksa çağrı hata verir.

## Dört İşlemin Ölçümü

Dört işlem kurulur. Birincisi aynı satırı iki kez eklemektir. İkincisi iki farklı satırı eklemektir. Üçüncüsü iki farklı içeriği atomik yazmaktır. Dördüncüsü iki farklı dizini oluşturmaktır.

```swift
// main.swift — sona ekleme, atomik yazma, dizin olusturma
let sameLine = replay("ekle-ayni-satir", from: FolderBox(), appending("a1", to: "log"), then: appending("a1", to: "log")).report()
let twoLines = replay("ekle-iki-satir", from: FolderBox(), appending("a1", to: "log"), then: appending("b2", to: "log")).report()
let atomic = replay("atomik-yaz", from: FolderBox(), writing("v1", to: "settings"), then: writing("v2", to: "settings")).report()
let folders = replay("dizin-olustur", from: FolderBox(), ensuring("cache"), then: ensuring("docs")).report()

countSensitivities([sameLine, twoLines, atomic, folders])
```

```
ekle-ayni-satir | bir=dizin:- dosya:log=a1 iki=dizin:- dosya:log=a1+a1 ab=dizin:- dosya:log=a1+a1 ba=dizin:- dosya:log=a1+a1 -> yinelemeye-duyarli
ekle-iki-satir | bir=dizin:- dosya:log=a1 iki=dizin:- dosya:log=a1+a1 ab=dizin:- dosya:log=a1+b2 ba=dizin:- dosya:log=b2+a1 -> cift-duyarli
atomik-yaz | bir=dizin:- dosya:settings=v1 iki=dizin:- dosya:settings=v1 ab=dizin:- dosya:settings=v2 ba=dizin:- dosya:settings=v1 -> siraya-duyarli
dizin-olustur | bir=dizin:cache dosya:- iki=dizin:cache dosya:- ab=dizin:cache,docs dosya:- ba=dizin:cache,docs dosya:- -> saglam
saglam: 1
yinelemeye-duyarli: 1
siraya-duyarli: 1
cift-duyarli: 1
```

Aynı satırı iki kez eklemek dosyayı büyütür: `a1` ve `a1+a1`. İki işlem aynı olduğu için sıra anlamsızdır. Sınıf **yinelemeye duyarlı**dır. Bir yeniden deneme mantığı bir ekleme çağrısını iki kez koşturursa günlüğe satır çiftlenir.

İki farklı satırı eklemek hem yinelemeyi hem sırayı ayrıştırır. Dosya ya `a1+b2` ya `b2+a1` olur ve her iki durumda da iki kez eklemek dosyayı büyütür. Sınıf **çift duyarlı**dır. Sona eklemenin bu kadar duyarlı olması şaşırtıcı değildir: dosyanın içeriği, o ana kadar eklenen her şeyin sıralı toplamıdır.

Atomik yazma yinelemeyi çözer: aynı içeriği ikinci kez yazmak dosyayı değiştirmez. Ama iki farklı içerikte sırayı çözmez: `ab` `v2`, `ba` `v1`. Son yazan kazanır. Atomiklik yarım dosyayı engeller; hangi yazmanın son olduğunu belirlemez. Sınıf **sıraya duyarlı**dır.

Dizin oluşturma dört satırın tek sağlam olanıdır. `withIntermediateDirectories: true` ile dizin zaten varsa işlem bir şey yapmaz; iki farklı dizin hangi sırayla oluşturulursa oluşturulsun aynı küme çıkar. Sınıf **sağlam**dır.

Sayım her sınıftan birer tanedir.

## Seçim Rehberi

Ölçüm dosya yazma kararını küçük bir kurala indirir. Veri bir kez yazılıp bir daha dokunulmuyorsa atomik yazma seçilir; yarım dosya ve çiftlenme riski ortadan kalkar, ama iki yazıcı varsa kazananı sıra belirler. Veri zamanla büyüyen bir günlükse sona ekleme seçilir, ama çiftlenmeyi önleyen bir anahtar ya da sayaç gerekir. Dizin oluşturma her zaman sağlam sayılabilir; uygulama başlarken ihtiyaç duyduğu dizinleri sormadan oluşturabilir.

## Sık Yapılan Hatalar

- Yeniden üretilebilen veriyi belgeler dizinine koymak. Yedeklemeyi şişirir.
- Kullanıcı verisini önbellek dizinine koymak. Sistem onu yer açmak için silebilir.
- Atomik yazmayı kullanmadan büyük bir dosyayı yerinde değiştirmek. Kesilme yarım dosya bırakır.
- Sona eklemeyi yeniden deneme içinde çağırmak. Satır çiftlenir.
- İki farklı yerden aynı dosyaya yazmak ve kazananın belli olduğunu sanmak.
- Dizin oluşturmadan önce var olup olmadığını denetlemek. Denetlemek gereksizdir; oluşturma zaten sağlamdır.

## Sınırlayıcı Ölçüm

Bazı işlemler dosyanın önceden var olmasına bağlıdır. Burada işlem, yalnız dosya varsa satır ekleyen bir ekleme olsun: dosyayı açamayan çağrı sessizce bir şey yapmaz. Aynı işlem çifti iki başlangıçta ölçülür: dosyanın olmadığı ve olduğu.

```swift
// main.swift — ayni islem cifti iki farkli baslangicta
let missing = replay("ekle-varsa-bos", from: FolderBox(), appendingIfPresent("x", to: "log"), then: appendingIfPresent("x", to: "log")).report()
let present = replay("ekle-varsa-dolu", from: FolderBox(files: ["log": ["a1"]]), appendingIfPresent("x", to: "log"), then: appendingIfPresent("x", to: "log")).report()

countSensitivities([missing, present])
```

```
ekle-varsa-bos | bir=dizin:- dosya:- iki=dizin:- dosya:- ab=dizin:- dosya:- ba=dizin:- dosya:- -> saglam
ekle-varsa-dolu | bir=dizin:- dosya:log=a1+x iki=dizin:- dosya:log=a1+x+x ab=dizin:- dosya:log=a1+x+x ba=dizin:- dosya:log=a1+x+x -> yinelemeye-duyarli
saglam: 1
yinelemeye-duyarli: 1
siraya-duyarli: 0
cift-duyarli: 0
```

Aynı iki işlem boş başlangıçta sağlam, dolu başlangıçta yinelemeye duyarlı çıktı. Dosya yokken işlem hiçbir şey yapmaz ve bu yüzden hiçbir şeyi bozamaz; dosya varken her çağrı bir satır ekler. Sağlam ölçülen ilk satır işlemin sağlam olduğunu söylemez, yalnız o başlangıçta etkisiz kaldığını söyler. Kural eşitsizliği görür; başlangıç durumunu genellemez.

Ölçümün dışında kalanlar açıkça sayılır. Dizin türleri, yedekleme dışı bırakma özelliği ve önbellek dizininin temizlenme zamanı KAYNAK ve düzyazı olarak kaldı. Bunlar sistemin zamanlamasına ve politikasına bağlıdır; bu modelde bir işlemin sonucu olarak kurulamaz.

## Gerçek Uygulamada Nerede Görülür

Dosyaya ekleme, bir günlük dosyasının tipik kullanımıdır ve ölçümün `ekle-ayni-satir` satırı bunun yinelemeye karşı korumasız olduğunu gösterdi. Uygulama bir olayı günlüğe yazar; olayı üreten kod bir yeniden denemede ya da bir yaşam döngüsü geçişinde ikinci kez çalışırsa aynı satır dosyada iki kez bulunur. Günlüğü sonradan okuyan bir çözümleme, bir olayı iki kez sayar. Dosya her zaman sona ekleme biçimindeyse çoğaltmanın izi silinemez, çünkü iki satır birbirinden ayırt edilemez.

İki farklı satırın iki sırayla eklenmesi ise çift duyarlılığı gösterir: `ekle-iki-satir` satırında hem yineleme hem sıra sonucu değiştirdi. Günlükte bu, olayların sırasının kayması anlamına gelir. Sıra önemsiz görünebilir, ama bir günlüğün çoğu zaman anlatı olarak okunduğunu düşünün: "bağlandı" satırı "koptu" satırından sonra gelirse okuyan yanlış sonuca varır.

Atomik yazma, bu dersin sağlam görünmesi beklenen ama yine de sıraya duyarlı çıkan işlemidir. Dosyanın tamamını geçici bir adla yazıp sonra asıl adın üzerine taşımak, yarım dosya kalmasını engeller; ancak iki yazma yarışırsa sonuncusu kazanır. Bu, yarım dosya sorununu çözmesine karşın sıra sorununu çözmediğinin ölçüdeki kanıtıdır. Dizin oluşturma ise iki sıra ve yineleme için sağlamdır, çünkü varlığı kontrol eden bir işlem, olan bir şeyi ikinci kez oluşturmaz.

## Yanlış Kurulum ve Düzeltmesi

Yaygın yanlış kurulum, yapılandırmayı doğrudan asıl dosyaya yazmaktır. Yazma sırasında uygulama kesilirse dosya yarım kalır ve bir sonraki açılışta okunamaz. Kullanıcı, uygulamanın artık açılmadığını görür. Düzeltme geçici dosya kalıbıdır: önce yeni içerik ayrı bir adla yazılır, tamamlandığı doğrulanır ve sonra asıl dosyanın yerine tek adımda konur. Bu, dosyanın ya eski ya da yeni içerikte bulunmasını sağlar. KL7 modelin bu garantiyi varsaydığını kaydeder.

İkinci yanlış, günlük gibi biriken veriyi ve ayar gibi üzerine yazılan veriyi aynı biçimde saklamaktır. Birikenin her satırı bağımsız bir olaydır ve yineleme çoğaltma yaratır. Üzerine yazılanın ise her yazması bir önceki değeri ezer ve yineleme zararsızdır. Doğru kurulum, ikisini ayrı dosyalarda ve ayrı kurallarla tutmaktır. Birikeni çoğaltmaya karşı korumak istiyorsanız her olaya bir kimlik verip aynı kimliği ikinci kez yazmamak gerekir; bu, sıra duyarlılığını yine de ortadan kaldırmaz, yalnız yinelemeyi çözer.

Üçüncü yanlış, dizinin varlığını varsaymaktır. Dosya yazan kod, üst dizin yoksa hata alır. Dizin oluşturma işleminin ölçümde sağlam çıkması, "önce dizini oluştur, sonra dosyayı yaz" sırasının güvenle kurulabileceğini söyler.

## KAYNAK Parçayı Okumak

Dersin başındaki adsız parça, uygulamanın kendi alanındaki dizinleri sorgular. Belgeler dizini kullanıcının verisi içindir, önbellek dizini yeniden üretilebilen veri içindir ve geçici dizin kısa ömürlü veri içindir. Sistem bu dizinlere farklı davranır: önbellek dizinindeki dosyalar yer azaldığında silinebilir, belgeler dizinindeki dosyalar yedeğe girer. Parçanın gösterdiği asıl ders budur: dosyanın nereye yazıldığı, dosyanın ne kadar yaşayacağını belirler.

Model dizin adlarını düz yol dizgisi olarak tuttuğu için bu ayrımı kurmaz; KL8 bunu kaydeder. Ölçümler dolayısıyla yalnız işlemlerin sonuçlarını, yani eklemenin, üzerine yazmanın ve oluşturmanın sınıflarını söyler. Hangi dizinin silinebilir olduğu ise model dışıdır ve uygulama tasarımında ayrıca düşünülmelidir.

## Ölçümden Tasarıma

Dört ölçümün ortak dersi, dosya işlemlerinin kendi başlarına değil, ne için kullanıldıklarıyla değerlendirileceğidir. Sona ekleme günlük için doğru bir işlemdir, ama çoğaltmaya karşı korunmasızdır. Dosyanın üzerine yazma ayar için doğru bir işlemdir, ama son yazanı kazandırır. Bu yüzden tasarım sorusu "hangi işlemi kullanayım" değil, "bu veri için hangi kusuru kabul edebilirim" olur. Günlükte arada bir çoğalan satır çoğu zaman kabul edilebilir; bir ayar dosyasında kaybolan değişiklik çoğu zaman edilemez.

Kusuru kabul edilemez olan veri için iki yol vardır. Birincisi, her yazmayı tek bir yerden geçirmektir; böylece sıra tek bir yerde belirlenir. İkincisi, yazmayı yinelemeye karşı koruyacak bir kimlik eklemektir: her satır bir olay kimliği taşır ve aynı kimlik ikinci kez yazılmaz. Kimlik, çift duyarlı bir işlemi yalnız sıraya duyarlı bir işleme çevirir; sıra sorununu ise ancak tek bir yazıcı çözer.

Dosya sistemi bir de başka bir kusur getirir: ölçmediğimiz her şey. Yer dolduğunda yazma başarısız olur, kullanıcı uygulamayı yazma sırasında kapatır, sistem önbellek dizinini temizler. Bu durumların hiçbiri modelde yoktur. Ölçüm, işlemin mantığındaki kusuru gösterir; ortamın kusurlarını değil. İkisini de düşünmek, dosyaya yazan her kodun sorumluluğundadır.

## Özet

- Veri türüne göre dizin seçilir: kullanıcı verisi belgelere, yeniden üretilebilen veri önbelleğe; yedeklemeyi yeniden indirilebilen veri için kapatmak mümkündür.
- Aynı satırı iki kez eklemek dosyayı `a1`'den `a1+a1`'e büyütür; sınıf yinelemeye duyarlıdır.
- İki farklı satırı eklemek yinelemeyi ve sırayı birlikte ayrıştırır (`a1+b2` ve `b2+a1`); sınıf çift duyarlıdır.
- Atomik yazma yinelemeyi çözer ama sırayı çözmez: `ab` `v2`, `ba` `v1`.
- Dizin oluşturma sağlamdır; dosya varlığına bağlı ekleme ise boş başlangıçta sağlam, dolu başlangıçta yinelemeye duyarlıdır.
- Bu dersin duyarlılığı: **çift duyarlı**.

## Sonraki Adım

Dosyalar veriyi düz bir bayt dizisi olarak tutar. Sıradaki derste, Yerel Veritabanı, verinin satır ve birincil anahtarla saklandığı yere geçilecek ve varsa güncelle yoksa ekle işleminin bu kez sağlam çıkıp çıkmadığı ölçülecek.
