Java'da bir dosyanın sonuna metin eklemek için Files.write yöntemine StandardOpenOption.APPEND seçeneği verilir. Dosya henüz yoksa StandardOpenOption.CREATE da birlikte verilmelidir. Bu seçenekler olmadan yöntem eski içeriği silip baştan yazar. Bu yazıda ekleme kodunun parçalarını ve seçeneklerin birbirini nasıl etkilediğini adım adım göreceksin.
Path, UTF-8 ve satır sonu: ekleme kodunun üç parçası
Ekleme kodu üç parçadan oluşur: yazılacak dosyanın yolu, yazılacak metnin byte karşılığı ve metnin sonundaki satır sonu.
Dosya yolu bir Path nesnesiyle tanımlanır. Path.of("gunluk.txt") ya da Paths.get("gunluk.txt") aynı işi görür. Yalnız dosya adı verirsen yol, programın çalıştığı klasöre göre çözülür. Başka bir klasörü hedeflemek istiyorsan yolu o klasörle birlikte yazarsın.
Files.write(Path, byte[], OpenOption...) metni değil byte dizisini ister. Bu yüzden metni metin.getBytes(StandardCharsets.UTF_8) ile dönüştürürsün. Karakter kodlamasını açıkça yazmak önemlidir. Türkçe karakterler (ç, ğ, ı, ö, ş, ü) kodlamaya göre farklı byte'lara dönüşür. Yazarken ve sonradan okurken aynı kodlama kullanılmazsa harfler bozuk görünür. StandardCharsets.UTF_8 vermek, kodun çalıştığı ortama bağlı kalmadan aynı sonucu almanı sağlar.
Java'nın Files sınıfında bir de metin satırlarını alan Files.write(Path, Iterable<? extends CharSequence>, Charset, OpenOption...) imzası vardır. Burada kodlamayı Charset parametresiyle verirsin. Resmî belgeye göre her satır, platformun satır ayırıcısıyla bitirilerek yazılır. Yani bu imzada satır sonunu sen eklemezsin. Byte dizisi alan imzada ise hiçbir şey kendiliğinden eklenmez.
Byte dizisiyle çalışırken satır sonunu kendin eklemelisin: metin + System.lineSeparator(). Bu yöntem, çalıştığı işletim sisteminin satır sonu dizisini döndürür. Böylece kodu elle "n" ya da "rn" yazmak zorunda kalmadan her ortamda doğru satır sonuyla çalıştırabilirsin.
Satır sonunu unutursan ne olur? Dosyaya sırayla "Birinci kayıt" ve "İkinci kayıt" eklediğini düşün. Hiçbirinin sonunda satır sonu yoksa dosyanın içeriği şöyle olur:
Birinci kayıtİkinci kayıt
Satır sonu eklendiğinde ise her kayıt kendi satırında durur:
Birinci kayıtİkinci kayıt
Log tutan küçük projelerde bu ayrıntı, dosyanın okunabilir kalıp kalmamasını belirler.
Seçenek vermezsen ne olur? Varsayılanlar ve APPEND ile değişen davranış

Files.write çağrısına hiç seçenek vermezsen yöntem, CREATE, TRUNCATE_EXISTING ve WRITE seçenekleri verilmiş gibi çalışır. Dosya yoksa oluşturulur. Varsa uzunluğu sıfıra indirilir ve yazma baştan başlar. Bu varsayılan, "eski içeriği sil, yenisini yaz" demektir. Log dosyasına kayıt eklemek isteyen biri seçenek vermeyi unutursa önceki kayıtları kaybeder.
Seçenek verdiğin anda bu varsayılanlar geçerli olmaz. Yalnızca verdiklerin uygulanır. Bu yüzden StandardOpenOption.APPEND tek başına verildiğinde CREATE kendiliğinden gelmez. APPEND, dosya yazma için açıldığında baytların dosyanın başına değil sonuna yazılacağını söyler. Dosyayı kendisi oluşturmaz.
Sonuç olarak hedef dosya henüz yoksa ve yalnız APPEND verdiysen çağrı NoSuchFileException fırlatır. Bu istisna, IOException sınıfının bir alt sınıfıdır. İlk çalıştırmada dosya olmadığı için programın hata vermesi bu yüzden yaygın bir tuzaktır. Çözüm iki seçeneği birlikte vermektir: StandardOpenOption.CREATE dosya yoksa oluşturur, StandardOpenOption.APPEND ise yazılanı sona ekler. Dosya varsa içeriği korunur.
TRUNCATE_EXISTING, dosya zaten varsa uzunluğunu sıfırlayan seçenektir. Amacı mevcut içeriği silmek olduğu için ekleme niyetiyle çelişir. Bu birleşimi kullanma: niyetin ekleme ise TRUNCATE_EXISTING verme. Resmî Files belgesindeki seçenek açıklamalarını okumak, her seçeneğin tam anlamını görmek için iyi bir alışkanlıktır.
Aynı günlük dosyasında üç davranış: üzerine yazma, ekleme, oluşturma

Farkı en net görmenin yolu, aynı gunluk.txt dosyasına dört adımda yazıp her adımdan sonra içeriğe bakmaktır. Aşağıdaki sınıf bunu yapar: seçeneksiz yazma, tekrar seçeneksiz yazma, APPEND ile ekleme, son olarak dosyayı silip önce yalnız APPEND, sonra CREATE ile birlikte deneme.
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
public class GunlukDemo {
static byte[] kayit(String metin) {
return (metin + System.lineSeparator()).getBytes(StandardCharsets.UTF_8);
}
static void yazdir(String baslik, Path yol) throws IOException {
System.out.println(baslik + " -> " + Files.readAllLines(yol, StandardCharsets.UTF_8));
}
public static void main(String[] args) {
Path dosya = Paths.get("gunluk.txt");
try {
// 1) Seçeneksiz: dosya yoksa oluşur
Files.write(dosya, kayit("Kayit 1"));
yazdir("1. adim", dosya);
// 2) Seçeneksiz tekrar: üzerine yazar
Files.write(dosya, kayit("Kayit 2"));
yazdir("2. adim", dosya);
// 3) APPEND: önceki içerik korunur
Files.write(dosya, kayit("Kayit 3"), StandardOpenOption.APPEND);
yazdir("3. adim", dosya);
// 4) Dosyayı sil, yalnız APPEND dene
Files.deleteIfExists(dosya);
try {
Files.write(dosya, kayit("Kayit 4"), StandardOpenOption.APPEND);
} catch (IOException e) {
System.out.println("4a hata -> " + e.getClass().getSimpleName() + " / " + e.getMessage());
}
// 4b) CREATE ile APPEND birlikte
Files.write(dosya, kayit("Kayit 4"),
StandardOpenOption.CREATE, StandardOpenOption.APPEND);
yazdir("4b adim", dosya);
} catch (IOException e) {
System.out.println("Beklenmeyen hata: " + e.getMessage());
}
}
}
Beklenen çıktı:
1. adim -> [Kayit 1]2. adim -> [Kayit 2]3. adim -> [Kayit 2, Kayit 3]4a hata -> NoSuchFileException / gunluk.txt4b adim -> [Kayit 4]
İkinci adımda "Kayit 1" kaybolur, çünkü seçenek verilmediğinde dosya her seferinde baştan yazılır. Üçüncü adımda APPEND eski içeriği korur ve yeni satırı sona ekler. Dördüncü adımda dosya olmadığı için yalnız APPEND yetmez; NoSuchFileException fırlar ve mesajı dosya yolunu içerir (burada yol göreli verildiği için gunluk.txt görünür). CREATE eklenince dosya yeniden oluşur ve kayıt içine yazılır. Dosyanın var olup olmamasından bağımsız çalışan günlük kodu için kalıcı seçim bu ikilidir.
IOException yönetimi ve alternatifler: FileWriter ile BufferedWriter
Files.write IOException bildiren bir metottur; çağıran kodun ya try-catch ile ya da metot imzasında throws ile bu durumu ele alması gerekir. Yukarıdaki örnekte olduğu gibi hatayı boş bir catch bloğunda yutmak yerine en azından mesajı yazdırmak, sorunu sonradan izlemeni sağlar.
Asıl karar şudur: günlük kaydı yazılamadığında program ne yapmalı? Log gibi yan işlevlerin başarısızlığı çoğu zaman ana işi çökertmemelidir; bu durumda hatayı yakalayıp bildirir ve akışa devam edersin. Kayıt işin kendisiyse (örneğin kullanıcı verisi saklıyorsan) hatayı yukarı fırlatmak daha doğru olabilir. Bu kararı bilinçli ver ve koda yansıt.
İki alternatif daha var:
- FileWriter: Yapıcıya ikinci parametre olarak
trueverirsen (new FileWriter("gunluk.txt", true)) ekleme kipinde açılır. Kodlama konusunda dikkatli ol: Charset almayan yapıcılarda varsayılan karakter kodlaması kullanılır ve bu, ortama göre değişebilir. Charset alan yapıcılar da bulunur; Türkçe karakterler için UTF-8'i açıkça vermeni öneririm. - BufferedWriter: Çok sayıda satırı tek tek yazacaksan dosyayı her satırda yeniden açmak yerine
Files.newBufferedWriter(yol, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.APPEND)ile bir kez aç. Seçenek vermezsen varsayılanlarFiles.writeile aynı mantıktadır (oluştur, varsa sıfırla, yaz); ekleme için seçenekleri yine sen belirtirsin. Yazıcıyıtry-with-resourcesile aç ki iş bitince otomatik kapansın.
Yazdığın kodun istisna yönetimi ve dosya işlemleri konusundaki eksiklerini görmek istersen ücretsiz Java bilgi testi ile seviyeni ölçüp hangi konulara dönmen gerektiğini belirleyebilirsin.
Hangi seçenek kombinasyonunu seçmeli? Kısa karar çerçevesi
Seçim, dosyanın her çalıştırmada ne yapması gerektiğine bağlıdır. Üç davranışı yan yana koyalım:
| Amaç | Seçenekler | Dosya yoksa | Dosya varsa |
|---|---|---|---|
| Her seferinde sıfırdan yazmak | Seçenek verilmez | Dosya oluşturulur ve yazılır | Önceki içerik silinir, baştan yazılır |
| Yalnızca var olan dosyaya eklemek | APPEND | NoSuchFileException fırlatılır | Metin dosyanın sonuna eklenir |
| Yoksa oluşturup eklemek | CREATE, APPEND | Dosya oluşturulur ve yazılır | Metin dosyanın sonuna eklenir |
Karar vermek için üç soru işini görür:
- Dosya her çalıştırmada sıfırdan mı başlamalı? Evetse seçenek vermemen yeterlidir.
- Dosyanın önceden var olduğu garanti mi? Garantiyse yalnızca
APPENDyeter. Garanti değilse ilk çalıştırmada hata alırsın. - Eksikse oluşturulsun mu? Evetse
CREATEileAPPENDbirlikte verilir.
Log tutan küçük projelerde program ilk kez çalıştığında dosya henüz bulunmaz, sonraki çalıştırmalarda ise eski kayıtların korunması istenir. Bu yüzden çoğu durumda CREATE ile APPEND birleşimi uygun olur. Yine de amacın farklıysa yukarıdaki sorular seni başka bir satıra götürebilir.
Yazmadan önce kontrol listesi
- Satır sonu eklendi mi? Eklemezsen yeni metin önceki satırın hemen ardına yapışır.
- UTF-8 karakter kümesi açıkça verildi mi? Türkçe karakterler için bu önemlidir.
IOExceptionele alındı mı?TRUNCATE_EXISTINGniyetsizce seçenek listesine girmedi mi? Bu seçenek dosyayı açarken boşaltmak içindir; ekleme yaparken eklemeyi unutma.
Dosya işlemlerini ve diğer Java konularını düzenli takip ve kişiye özel müfredatla çalışmak istersen birebir Java özel ders programı bu çalışma düzenine uygun bir seçenek olabilir.