Bütün bir dosyayı okumak ve yazmak
os.WriteFile ve os.ReadFile çoğu ihtiyacı karşılar. Tek bir çağrıda açar, yazar ya da okur ve kapatırlar.
Bu sayfadaki örnekler os.MkdirTemp'ten gelen geçici bir dizinde çalışır ve onu defer os.RemoveAll(dir) ile kaldırır, böylece geride hiçbir şey bırakmazlar. Kendi kodunuzda "config.json" gibi göreli bir yol, sürecin çalışma dizinine göre çözülür; bu da mutlaka kaynak dosyanın ya da binary'nin dizini değildir.
os.WriteFile gerekirse dosyayı oluşturur ve varsa onu sıfırlar (truncate). Üçüncü argüman yeni oluşturulan bir dosya için Unix iznidir: 0o644, sahibinin okuyup yazabileceği, diğer herkesin okuyabileceği anlamına gelir. Zaten var olan bir dosya için yok sayılır ve süreç umask'ı bazı bitleri kaldırabilir.
os.ReadFile her şeyi belleğe okur. Bu yapılandırma dosyaları ve küçük girdiler için doğrudur, çok gigabaytlık bir log için yanlıştır.
bufio.Scanner ile satır satır okumak
Büyük dosyalar için ya da zaten satırları istediğinizde bufio.Scanner kullanın. Parçalar halinde okur ve size her seferinde yeni satır karakteri olmadan bir satır verir.
Üç ayrıntı:
- Döngüden sonra
sc.Err()'ü kontrol edin.Scanhem dosya sonunda hem de bir hatadafalsedöndürür ve yalnızcaErronları ayırt eder. - 64 KB satır sınırı. Varsayılan olarak 64 KB'tan uzun tek bir satır scanner'ı
bufio.Scanner: token too longile durdurur. Uzun satırlı dosyalar (küçültülmüş JSON, bazı loglar) için döngüden önce sınırı yükseltin:sc.Buffer(make([]byte, 1024*1024), 10*1024*1024). - Diğer birimler.
sc.Split(bufio.ScanWords)kelimeler verir;bufio.ScanRuneskarakterler verir.
Bir akışı satırlar yerine sabit boyutlu parçalar halinde okumak için bir döngüde f.Read(buf) kullanın ya da başka bir writer'a io.Copy yapın.
Yazmak: os.Create, os.OpenFile ve sona ekleme
os.Create(name) bir dosyayı yazmak için açar; oluşturur ya da sıfırlar. os.OpenFile bayraklar üzerinden tam kontrol verir:
| Bayrak | Anlamı |
|---|---|
os.O_RDONLY, os.O_WRONLY, os.O_RDWR | okumak, yazmak ya da ikisi için aç (birini seçin) |
os.O_CREATE | dosya yoksa oluştur |
os.O_TRUNC | açarken dosyayı boşalt |
os.O_APPEND | her yazma sona gider |
os.O_EXCL | O_CREATE ile: dosya zaten varsa başarısız ol |
os.Open(name), OpenFile(name, O_RDONLY, 0)'dır. os.Create(name), OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0o666)'dır.
Yazarken Close'tan gelen hata önemlidir. Bazı dosya sistemleri yazma hatalarını yalnızca kapatma anında bildirir, bu yüzden tek başına defer f.Close() kaybolan veriyi gizleyebilir. Yazdığınız dosyalar için appendLine'ın yaptığı gibi Close'u açıkça kontrol edin. Yalnızca okuduğunuz dosyalar için defer f.Close() yeterlidir.
fmt.Fprintln ve fmt yazdırma fonksiyonlarının geri kalanı, bir dosya dahil her io.Writer'ı kabul eder. Bir bufio.Writer küçük yazmaları bellekte toplar. w.Flush()'ı unutmak klasik bir hatadır: program normal biçimde çıkar ve son birkaç kilobayt dosyaya hiç ulaşmaz.
Dosya var mı?
Go'da os.Exists yoktur. os.Stat'ı çağırın ve hatayı inceleyin:
errors.Is(err, fs.ErrNotExist) güncel kalıptır. Sarmalanmış hataların içini göremeyen eski os.IsNotExist(err)'ün yerini alır.
Açmadan önce kontrol etmek çoğu zaman gereksizdir ve race'e açıktır: dosya kontrol ile açma arasında ortaya çıkabilir ya da kaybolabilir. Genellikle onu doğrudan açıp açmadan gelen fs.ErrNotExist'i ele alırsınız. Bir dosyayı yalnızca henüz yoksa oluşturmak için, kontrolü ve oluşturmayı tek bir atomik adım yapan O_CREATE|O_EXCL'i kullanın.
Dizinler
| Görev | Fonksiyon |
|---|---|
| tek bir dizin oluşturmak | os.Mkdir(path, 0o755) |
| ebeveynleriyle bir yol oluşturmak | os.MkdirAll(path, 0o755) |
| bir dizini listelemek | os.ReadDir(path) |
| bir ağacı dolaşmak | filepath.WalkDir(root, fn) |
| bir dosyayı ya da boş dizini silmek | os.Remove(path) |
| bir ağacı silmek | os.RemoveAll(path) |
| yeniden adlandırmak ya da taşımak | os.Rename(old, new) |
| geçici dosya ya da dizin | os.CreateTemp("", "prefix-*"), os.MkdirTemp("", "prefix") |
| yol parçalarını birleştirmek | filepath.Join(a, b, c) |
Dosya sistemi yolları için path/filepath kullanın: işletim sistemi için doğru ayırıcıyı kullanır (Windows'ta \). path paketi ise URL'ler gibi eğik çizgiyle ayrılmış yollar içindir.
Go 1.24 ayrıca dosyaları yalnızca tek bir dizinin içinde açan ve .. ya da symlink'lerle dışarı kaçan yolları reddeden os.Root'u (os.OpenRoot(dir)) ekledi. Dosya adları kullanıcılardan geldiğinde onu kullanın.
Sık yapılan hatalar
- Hataları kontrol etmemek. Bu çağrıların her biri başarısız olabilir. Açılamayan bir dosya
nil'dir ve üzerindeki sonraki herRead,Writeya daCloseinvalid argumentdöndürür; bu da asıl nedeni (dosya yoktu ya da izin reddedildi) gizler. - Bir tarama döngüsünden sonra
sc.Err()'ü unutmak. Bir okuma hatası dosya sonu gibi görünür. - Bir
bufio.WriterüzerindeFlush'ı unutmak. Dosyanın sonu eksik kalır. - Yazdıktan sonra
Close'tan gelen hatayı yok saymak. Yazma hataları yalnızca orada ortaya çıkabilir. - Birçok dosya üzerinde dönen bir döngü içinde
defer f.Close(). Dosyalar fonksiyon dönene kadar açık kalır ve dosya tanımlayıcılarınız tükenebilir. Gövdeyi bir fonksiyona taşıyın ki her dosya yinelemede kapansın. - Onluk olarak yazılmış izinler.
644,0o644değildir. Go644'ü onluk sayı olarak okur; bu da0o1204'tür ve tuhaf bitler ayarlar.
Sıkça Sorulan Sorular
Go'da bir dosyanın tamamı bir string'e nasıl okunur?
data, err := os.ReadFile("notes.txt") içeriği []byte olarak döndürür; string(data) ile dönüştürün. Dosyayı sizin yerinize açar, okur ve kapatır. Belleğe rahatça sığan dosyalar için kullanın; büyük dosyalar için bufio.Scanner ile satır satır okuyun.
Go'da bir dosya satır satır nasıl okunur?
Dosyayı os.Open ile açın, defer f.Close() yazın, onu bufio.NewScanner(f) ile sarın, for sc.Scan() { line := sc.Text() } ile dönün ve döngüden sonra sc.Err()'ü kontrol edin. 64 KB'tan uzun satırlar, tamponu sc.Buffer ile büyütmedikçe scanner'ın token too long ile başarısız olmasına yol açar.
Go'da bir dosyanın sonuna nasıl ekleme yapılır?
Onu os.OpenFile(name, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644) ile açın, yazın ve Close'tan gelen hatayı kontrol edin. O_CREATE dosya yoksa oluşturur, O_APPEND her yazmanın sona gitmesini sağlar.
Go'da bir dosyanın var olup olmadığı nasıl kontrol edilir?
os.Stat(path)'i çağırın ve hatayı errors.Is(err, fs.ErrNotExist) ile test edin. Nil bir hata dosyanın var olduğu anlamına gelir. Başka herhangi bir hata (örneğin permission denied) bunu bilemeyeceğiniz anlamına gelir, bu yüzden onu "yok" olarak ele almak yerine ayrıca işleyin.