Ders İçeriği

Java, dosya ve dizinlerle etkileşim kurmak için zengin bir giriş/çıkış (Input/Output - I/O) API'si sunar. Bu API, dosya okuma, yazma, oluşturma, silme ve dizin işlemleri gibi çeşitli görevleri yerine getirmemizi sağlar. Bu bölümde, Java'da dosya işlemlerinin temel prensiplerini ve yaygın olarak kullanılan sınıfları inceleyeceğiz.

Temel Kavramlar: Akışlar (Streams)

Java I/O, akışlar (streams) kavramına dayanır. Akış, bir veri kaynağı ile bir veri hedefi arasındaki veri akışını temsil eder. İki ana akış türü vardır:

  • Giriş Akışları (Input Streams): Veri kaynağından (örneğin bir dosya, ağ bağlantısı) veri okumak için kullanılır.
  • Çıkış Akışları (Output Streams): Veri hedefine (örneğin bir dosya, ağ bağlantısı) veri yazmak için kullanılır.

Akışlar ayrıca iki kategoriye ayrılır:

  • Bayt Akışları (Byte Streams): Bayt bayt veri okuma ve yazma işlemleri için kullanılır. İkili veriler (resimler, ses dosyaları vb.) için uygundur. InputStream ve OutputStream temel sınıflarıdır.
  • Karakter Akışları (Character Streams): Karakter karakter veri okuma ve yazma işlemleri için kullanılır. Metin verileri için uygundur ve karakter kodlamalarını (UTF-8, UTF-16 vb.) otomatik olarak ele alır. Reader ve Writer temel sınıflarıdır.

File Sınıfı

java.io.File sınıfı, dosya veya dizin yollarını temsil etmek ve dosya sistemi üzerinde işlemler yapmak için kullanılır. Dosyanın içeriğini okuma veya yazma yeteneği sağlamaz, sadece dosya veya dizinle ilgili meta verileri ve işlemleri (oluşturma, silme, yeniden adlandırma vb.) yönetir.

import java.io.File;

public class FileIslemleri {
    public static void main(String[] args) {
        // Yeni bir File nesnesi oluşturma
        File dosya = new File("ornek.txt");

        try {
            // Dosya varsa sil, yoksa oluştur
            if (dosya.exists()) {
                System.out.println("Dosya zaten var. Siliniyor...");
                dosya.delete();
            }
            if (dosya.createNewFile()) {
                System.out.println("Dosya oluşturuldu: " + dosya.getName());
            } else {
                System.out.println("Dosya oluşturulamadı.");
            }

            // Dosya bilgileri
            System.out.println("Dosya yolu: " + dosya.getAbsolutePath());
            System.out.println("Yazılabilir mi: " + dosya.canWrite());
            System.out.println("Okunabilir mi: " + dosya.canRead());
            System.out.println("Boyut (bayt): " + dosya.length());

            // Dizin oluşturma
            File dizin = new File("yeni_dizin");
            if (dizin.mkdir()) {
                System.out.println("Dizin oluşturuldu: " + dizin.getName());
            }

            // Dizin içeriğini listeleme
            File mevcutDizin = new File("."); // Mevcut dizin
            String[] icerik = mevcutDizin.list();
            System.out.println("Mevcut dizin içeriği:");
            for (String eleman : icerik) {
                System.out.println(eleman);
            }

        } catch (Exception e) {
            System.err.println("Bir hata oluştu: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

Dosya Okuma ve Yazma

Metin Dosyaları İçin (Karakter Akışları)

  • FileWriter ve FileReader: Metin dosyalarına karakter bazında yazma ve okuma için kullanılır. Genellikle BufferedWriter ve BufferedReader ile birlikte kullanılarak performans artırılır.

    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    
    public class MetinDosyaIslemleri {
        public static void main(String[] args) {
            String dosyaAdi = "deneme.txt";
            String icerik = "Bu bir deneme metnidir.\nJava dosya işlemleri.";
    
            // Dosyaya Yazma
            try (BufferedWriter writer = new BufferedWriter(new FileWriter(dosyaAdi))) {
                writer.write(icerik);
                System.out.println("Dosyaya yazma başarılı.");
            } catch (IOException e) {
                System.err.println("Dosyaya yazarken hata oluştu: " + e.getMessage());
            }
    
            // Dosyadan Okuma
            try (BufferedReader reader = new BufferedReader(new FileReader(dosyaAdi))) {
                String satir;
                System.out.println("Dosya içeriği:");
                while ((satir = reader.readLine()) != null) {
                    System.out.println(satir);
                }
                System.out.println("Dosyadan okuma başarılı.");
            } catch (IOException e) {
                System.err.println("Dosyadan okurken hata oluştu: " + e.getMessage());
            }
        }
    }
    

Bayt Dosyaları İçin (Bayt Akışları)

  • FileOutputStream ve FileInputStream: İkili verilere (bayt dizileri) yazma ve okuma için kullanılır. Resim, ses veya diğer ikili dosyalar için uygundur.

    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class BaytDosyaIslemleri {
        public static void main(String[] args) {
            String kaynakDosya = "kaynak.jpg"; // Örnek bir resim dosyası
            String hedefDosya = "kopya.jpg";
    
            try (FileInputStream fis = new FileInputStream(kaynakDosya);
                 FileOutputStream fos = new FileOutputStream(hedefDosya)) {
    
                byte[] buffer = new byte[1024];
                int bytesRead;
                while ((bytesRead = fis.read(buffer)) != -1) {
                    fos.write(buffer, 0, bytesRead);
                }
                System.out.println("Dosya kopyalama başarılı.");
    
            } catch (IOException e) {
                System.err.println("Dosya işlemi sırasında hata oluştu: " + e.getMessage());
            }
        }
    }
    

NIO.2 (New I/O) API

Java 7 ile birlikte tanıtılan NIO.2 API, dosya sistemi işlemleri için daha modern ve esnek bir yaklaşım sunar. java.nio.file paketi altında yer alır ve özellikle büyük dosyalarla veya karmaşık dosya sistemi operasyonlarıyla çalışırken daha iyi performans ve daha temiz kod sağlar.

  • Path Sınıfı: Dosya veya dizin yollarını temsil eder. File sınıfına göre daha güçlü ve esnektir.
  • Files Sınıfı: Statik metotlar aracılığıyla dosya ve dizin işlemleri için yardımcı metotlar sunar.
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.List;
import java.io.IOException;

public class NIO2DosyaIslemleri {
    public static void main(String[] args) {
        Path dosyaYolu = Paths.get("nio_ornek.txt");

        // Dosyaya Yazma (tek satırda)
        try {
            Files.write(dosyaYolu, "NIO.2 ile yazılan ilk satır.\n".getBytes(), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
            Files.write(dosyaYolu, "İkinci satır.".getBytes(), StandardOpenOption.APPEND);
            System.out.println("NIO.2 ile dosyaya yazma başarılı.");
        } catch (IOException e) {
            System.err.println("NIO.2 yazma hatası: " + e.getMessage());
        }

        // Dosyadan Okuma (tüm satırları listeye alma)
        try {
            List<String> satirlar = Files.readAllLines(dosyaYolu);
            System.out.println("NIO.2 ile dosya içeriği:");
            for (String satir : satirlar) {
                System.out.println(satir);
            }
            System.out.println("NIO.2 ile dosyadan okuma başarılı.");
        } catch (IOException e) {
            System.err.println("NIO.2 okuma hatası: " + e.getMessage());
        }

        // Dosya kopyalama
        Path kaynak = Paths.get("nio_ornek.txt");
        Path hedef = Paths.get("nio_kopya.txt");
        try {
            Files.copy(kaynak, hedef, java.nio.file.StandardCopyOption.REPLACE_EXISTING);
            System.out.println("NIO.2 ile dosya kopyalama başarılı.");
        } catch (IOException e) {
            System.err.println("NIO.2 kopyalama hatası: " + e.getMessage());
        }

        // Dosya silme
        try {
            Files.deleteIfExists(hedef);
            System.out.println("NIO.2 ile dosya silme başarılı.");
        } catch (IOException e) {
            System.err.println("NIO.2 silme hatası: " + e.getMessage());
        }
    }
}

Java'da dosya işlemleri, uygulamaların dış dünya ile etkileşim kurması için temel bir yetenektir. Hangi API'yi kullanacağınız (eski I/O veya NIO.2), projenizin gereksinimlerine ve Java sürümüne bağlıdır. Genellikle, yeni projelerde NIO.2 API'sinin kullanılması önerilir. Bir sonraki derste Çoklu İş Parçacığı (Multithreading) konusunu inceleyeceğiz.