Yazdığımız bilgisayar programlarındaki veriler (değişkenler, nesneler vb.) bilgisayarın ana belleğinde (RAM) tutulur ve program kapatıldığında veya bilgisayarın gücü kesildiğinde tamamen silinir. Bir e-ticaret uygulamasındaki müşteri listesini veya oynadığınız bir oyunun kayıt dosyasını düşündüğünüzde, bu verilerin kalıcı olması gerektiği açıktır. İşte verilerin kalıcı hale getirilerek sabit disk, USB bellek veya benzeri depolama birimlerinde saklanabilmesi için dosyalara (files) ihtiyaç duyarız.
Java, programların dış dünyayla iletişim kurması (Girdi/Çıktı veya I/O) için son derece esnek ve güçlü bir altyapı sunar. Bu rehberimizde, Java’da dosya ve klasör yönetiminin nasıl yapıldığını, verilere nasıl ulaşılacağını ve metin belgelerine nasıl veri yazılıp okunacağını sıfırdan, örneklerle öğreneceğiz.
1. Java’da Akış (Stream) Mantığı Nedir?
Java’da I/O (Girdi/Çıktı) işlemleri “akış” (stream) adı verilen bir soyutlama üzerinden gerçekleştirilir. Bir akışı, verilerin içinden geçtiği bir boru hattı olarak düşünebilirsiniz. Bir akış, veri üreten (örneğin klavye veya bir dosya) bir kaynağı temsil edebileceği gibi, verinin gönderileceği (örneğin ekran veya bir dosya) bir hedefi de temsil edebilir.
Java, akışları temel olarak ikiye ayırır:
- Byte Akışları (Byte Streams): Verileri 8-bitlik byte’lar halinde işler. Resimler, ses dosyaları veya çalıştırılabilir programlar gibi makine formatındaki veriler için kullanılır (
FileInputStream,FileOutputStreamgibi sınıflar),. - Karakter Akışları (Character Streams): İnsanlar tarafından okunabilen metinleri işlemek için özel olarak tasarlanmıştır. Verileri doğrudan karakterler olarak okur ve yazar (
FileReader,FileWritergibi sınıflar),.
Başlangıç düzeyinde metin (txt) dosyalarıyla çalışacağımız için, bu rehberde karakter akışlarına odaklanacağız.
2. File Sınıfı ile Dosya ve Klasör Yönetimi
Bir dosya veya dizinle (klasörle) işlem yapmadan önce, Java’da onun varlığını temsil edecek bir nesneye ihtiyacımız vardır. java.io paketi içinde yer alan File sınıfı tam olarak bu işi yapar. File nesnesi oluşturmak, dosyayı açmak veya oluşturmak demek değildir; yalnızca o dosyanın veya klasörün yolunu (path) Java’ya tanıtmaktır.
import java.io.File;
public class DosyaYonetimi {
public static void main(String[] args) {
// Dosyanın yolunu belirterek bir File nesnesi oluşturuyoruz
File dosya = new File("deneme.txt");
// Dosyanın diskte gerçekten var olup olmadığını kontrol edelim
if (dosya.exists()) {
System.out.println("Dosya Adı: " + dosya.getName());
System.out.println("Dosya Boyutu: " + dosya.length() + " byte");
System.out.println("Bu bir klasör mü? " + dosya.isDirectory());
} else {
System.out.println("Böyle bir dosya henüz diskte bulunmuyor.");
}
}
}
File Sınıfının Faydalı Metotları:
exists(): Dosya veya klasörün var olup olmadığını boolean (true/false) olarak döndürür.delete(): Varsa dosyayı siler ve başarılı olursatruedöndürür,.mkdir()vemkdirs(): Yeni bir klasör (dizin) oluşturmak için kullanılır.list(): Eğer nesne bir klasörü işaret ediyorsa, içindeki dosyaların isimlerini birStringdizisi olarak döndürür,.
(Not: Windows sistemlerinde dizin yollarında ters eğik çizgi \ kullanılırken, Unix tabanlı sistemlerde (Mac/Linux) düz eğik çizgi / kullanılır. Java her iki kullanımı da doğru şekilde yorumlayabilen platform bağımsız bir yapıya sahiptir.)
3. Dosyaya Veri Yazma (FileWriter Kullanımı)
Metin dosyalarına veri yazmak için java.io.FileWriter sınıfı kullanılır. Ancak dosya işlemleri doğası gereği risklidir. Örneğin, dosya başka bir program tarafından kilitlenmiş olabilir veya diskinizde yer kalmamış olabilir. Bu yüzden Java, I/O işlemlerinde mecburi olarak istisna yönetimini (Exception Handling) kullanmamızı zorunlu kılar. Hata durumlarında IOException fırlatılır,.
Geçmişte (JDK 7 öncesi), açılan bir dosyayı işimiz bittiğinde finally bloğu kullanarak close() metodu ile manuel kapatmak zorundaydık; aksi halde dosya havada asılı kalır ve bellek sızıntılarına (memory leak) yol açardı,.
Günümüzde ise modern Java’nın sunduğu try-with-resources (kaynaklarla try) yapısını kullanıyoruz,. Bu yapı, parantez içinde açılan dosyayı (kaynağı), işlem bitince kendi kendine otomatik olarak kapatır ve kodu çok daha temiz hale getirir,,.
Örnek: Dosyaya Metin Yazma
import java.io.FileWriter;
import java.io.IOException;
public class DosyayaYazma {
public static void main(String[] args) {
String metin = "Merhaba! Bu satır Java ile dosyaya yazdırıldı.\n" +
"Bu da dosyanın ikinci satırı.";
// try-with-resources ile FileWriter kullanıyoruz (otomatik kapanır)
try (FileWriter yazar = new FileWriter("ornek_dosya.txt")) {
yazar.write(metin);
System.out.println("Dosyaya yazma işlemi başarıyla tamamlandı!");
} catch (IOException e) {
System.out.println("Dosyaya yazılırken bir hata oluştu: " + e.getMessage());
}
}
}
Bu program çalıştırıldığında projenizin ana dizininde ornek_dosya.txt adında bir belge oluşacak ve içine metniniz yazılacaktır.
4. Dosyadan Veri Okuma (FileReader ve BufferedReader Kullanımı)
Dosyadaki metni okumak için karakter tabanlı okuma sağlayan FileReader sınıfını kullanırız. Fakat dosyayı harf harf (karakter karakter) okumak performans açısından oldukça yavaştır. Daha verimli bir okuma yapmak ve metni satır satır çekebilmek için FileReader nesnesini bir BufferedReader sınıfıyla sarmalarız (wrap ederiz).
Örnek: Dosyadan Satır Satır Veri Okuma
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.IOException;
public class DosyadanOkuma {
public static void main(String[] args) {
// try-with-resources bloğu içinde BufferedReader oluşturuluyor
try (BufferedReader okuyucu = new BufferedReader(new FileReader("ornek_dosya.txt"))) {
String satir;
System.out.println("--- DOSYA İÇERİĞİ ---");
// readLine() metodu dosya sonuna gelindiğinde null döndürür
while ((satir = okuyucu.readLine()) != null) {
System.out.println(satir);
}
} catch (IOException e) {
System.out.println("Dosya okunurken hata oluştu: " + e.getMessage());
}
}
}
Yukarıdaki kod, diskteki belgeyi bulur, belleğe alır ve readLine() metodu sayesinde içerik bitene kadar her bir satırı sırayla ekrana yazdırır.
5. İleri Düzey İpucu: NIO.2 (New I/O) ile Kolay Dosya İşlemleri
JDK 7 (Java 7) sürümüyle birlikte Java, dosya işlemlerini devasa boyutta kolaylaştıran NIO.2 (New I/O) kütüphanesini tanıttı,. Klasik java.io.File yerine, daha modern olan java.nio.file.Path arayüzünü ve onlarca pratik metot barındıran Files sınıfını hayata geçirdi,.
Eğer çok karmaşık işlemler yapmıyorsanız, dosya kopyalamak, silmek veya tüm içeriği tek satırda okumak/yazmak için NIO.2 kütüphanesi harikadır.
Örneğin eski usulle uzun uzun while döngüleri kurmak yerine, NIO ile dosya kopyalama işlemini tek bir satırda şöyle yapabilirsiniz:
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.io.IOException;
public class NioKopyalama {
public static void main(String[] args) {
Path kaynak = Paths.get("ornek_dosya.txt"); // Orijinal dosya
Path hedef = Paths.get("kopya_dosya.txt"); // Kopyası
try {
// Kaynaktan hedefe kopyala. Üzerine yazmaya izin ver (REPLACE_EXISTING)
Files.copy(kaynak, hedef, StandardCopyOption.REPLACE_EXISTING);
System.out.println("Kopyalama başarılı!");
} catch (IOException e) {
System.out.println("Hata: " + e);
}
}
}
Ayrıca Files.readAllLines() gibi metotlar yardımıyla, bir dosyanın içindeki tüm satırları anında bir Liste (List) olarak çekebilirsiniz.
Sonuç
Java’da dosya işlemleri yapmak başlangıçta kalabalık sınıf adlarıyla göz korkutucu görünse de, mantığı kavrandığında bir legonun parçalarını birleştirmek kadar kolaydır.
- Klasik yönetimler için
File, - Okuma için
FileReader(veBufferedReader), - Yazma için
FileWriter, - Modern, kısa ve gelişmiş operasyonlar için
NIO (Path ve Files)sınıflarını tercih edebilirsiniz.
Yeni öğrendiğiniz bu sınıfları kendi bilgisayarınızda (IDE’nizde) deneyerek ve try-with-resources bloğunu alışkanlık haline getirerek programlamada verilerinizi kolaylıkla kalıcı hale getirmeye başlayabilirsiniz!





