Gereksinimler ve Ön Hazırlık
Projemize başlamadan önce sisteminizde Java Development Kit (JDK) 17 veya daha güncel bir sürümün yüklü olduğundan emin olmalısınız. 2026 yılı standartlarında, uzun vadeli destek (LTS) sürümlerini kullanmak en güvenli yaklaşımdır.
- JDK 17+: Derleme ve çalıştırma işlemleri için gereklidir.
- IDE: IntelliJ IDEA, Eclipse veya VS Code gibi bir geliştirme ortamı önerilir.
- Temel Bilgi: Java'da
Scannersınıfı vejava.iopaketinin temel çalışma mantığına dair genel bir aşinalık yeterlidir.
Kurulumu doğrulamak için terminal veya komut satırına java -version yazarak sürümünüzü kontrol edebilirsiniz. Eğer çıktı alabiliyorsanız, geliştirme ortamınız hazırdır.
Adım 1: Kullanıcı Etkileşimi İçin Scanner Kullanımı
Java'da konsoldan veri okumak için java.util.Scanner sınıfını kullanırız. Not defteri uygulamamızın temelinde, kullanıcının girdiği notları yakalamak yatar. İlk adımda, kullanıcıya menü seçenekleri sunan basit bir yapı kuralım.
import java.util.Scanner;
public class NotDefteri {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Not Defteri Uygulamasına Hoş Geldiniz!");
System.out.println("Lütfen notunuzu girin:");
String not = scanner.nextLine();
System.out.println("Girdiğiniz not: " + not);
scanner.close();
}
}
Bu kod bloğu, kullanıcının klavyeden girdiği metni not değişkenine atar. scanner.nextLine() metodu, satır sonuna kadar olan tüm metni okur. scanner.close() kullanımı ise kaynak sızıntılarını önlemek için kritik öneme sahiptir.
Adım 2: Notları Dosyaya Yazma İşlemi
Notları sadece hafızada tutmak yeterli değildir; uygulama kapandığında verilerin kalıcı olması gerekir. Bunun için java.io.FileWriter sınıfını kullanarak notları bir metin dosyasına yazdıracağız. Dosya işlemleri sırasında oluşabilecek hatalar için try-catch bloklarını kullanmak zorunludur.
import java.io.FileWriter;
import java.io.IOException;
public void notuKaydet(String not) {
try (FileWriter writer = new FileWriter("notlar.txt", true)) {
writer.write(not + System.lineSeparator());
System.out.println("Not başarıyla kaydedildi.");
} catch (IOException e) {
System.err.println("Dosyaya yazılırken bir hata oluştu: " + e.getMessage());
}
}
Burada FileWriter kurucusuna verilen true parametresi, dosyanın üzerine yazmak yerine mevcut içeriğin sonuna ekleme (append) yapılmasını sağlar. System.lineSeparator() kullanımı ise platform bağımsız olarak yeni satıra geçilmesini garantiler.
Adım 3: Kayıtlı Notları Listeleme
Kaydettiğimiz notları geri okumak için java.nio.file.Files sınıfını kullanmak, modern Java uygulamalarında daha performanslı ve okunabilir bir yöntemdir. Bu yöntem, tüm satırları bir liste olarak okumamıza olanak tanır.
import java.nio.file.Files;
import java.nio.file.Paths;
import java.io.IOException;
import java.util.List;
public void notlariListele() {
try {
List satirlar = Files.readAllLines(Paths.get("notlar.txt"));
for (String satir : satirlar) {
System.out.println("- " + satir);
}
} catch (IOException e) {
System.out.println("Henüz kayıtlı not bulunamadı.");
}
}
Files.readAllLines metodu, dosyadaki tüm içeriği bir List yapısına dönüştürür. Eğer dosya mevcut değilse, IOException fırlatılır ve biz de kullanıcıya nazik bir uyarı mesajı gösteririz.
Adım 4: Uygulama Mantığını Birleştirme
Şimdi tüm parçaları birleştirerek bir menü yapısı oluşturalım. Kullanıcı 1'e bastığında not eklesin, 2'ye bastığında listelesin, 3'e bastığında ise çıkış yapsın.
import java.util.Scanner;
public class NotDefteriApp {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("\n1. Not Ekle\n2. Notları Listele\n3. Çıkış");
String secim = scanner.nextLine();
if (secim.equals("3")) break;
if (secim.equals("1")) {
System.out.print("Notunuz: ");
// Not kaydetme metodu çağrılır
} else if (secim.equals("2")) {
// Not listeleme metodu çağrılır
}
}
scanner.close();
}
}
Bu while(true) döngüsü, kullanıcı 3'ü seçene kadar uygulamanın çalışmaya devam etmesini sağlar. Bu yapı, basit konsol uygulamalarında standart bir kullanıcı arayüzü mantığıdır.
Yöntem Karşılaştırması
| Yöntem | Avantajı | Dezavantajı |
|---|---|---|
| FileWriter | Basit ve hızlıdır. | Büyük dosyalarda yavaş kalabilir. |
| Files.readAllLines | Modern ve okunabilir. | Çok büyük dosyalarda bellek sorunu yaratabilir. |
Kritik Güvenlik Uyarısı: Konsol uygulamalarında kullanıcıdan alınan verileri dosyaya yazarken, dosya yolları üzerinde "Path Traversal" (yol geçişi) saldırılarına dikkat edilmelidir. Kullanıcıdan alınan girdi doğrudan dosya ismi olarak kullanılmamalı, her zaman doğrulanmalıdır. Ayrıca, üretim ortamında hassas verileri düz metin (plain-text) olarak saklamak yerine şifreleme yöntemleri tercih edilmelidir.
Sıkça Sorulan Sorular
Not defteri uygulamam neden hata veriyor?
Genellikle dosya izinlerinden veya try-catch bloklarının eksikliğinden kaynaklanır. Dosyanın bulunduğu dizinde yazma izninizin olduğundan emin olun.
Daha fazla veri tipi ekleyebilir miyim?
Evet, notların yanına tarih eklemek için java.time.LocalDateTime sınıfını kullanabilirsiniz. Böylece notun ne zaman alındığını da kaydedebilirsiniz.
Verileri veritabanında tutmak daha mı iyi?
Küçük notlar için dosya sistemi yeterlidir. Ancak veri miktarı arttığında SQLite gibi hafif bir veritabanı kullanmak, veriye erişim hızını ve güvenliğini artıracaktır.
Neden Scanner yerine BufferedReader kullanmadık?
Scanner, başlangıç seviyesindeki kullanıcılar için daha sezgisel ve kolay bir sözdizimine sahiptir. BufferedReader daha performanslıdır ancak daha karmaşık bir yapı gerektirir.
Uygulamayı .jar dosyasına nasıl çeviririm?
IDE'niz üzerinden 'Build Artifacts' seçeneğini kullanarak projenizi çalıştırılabilir bir JAR dosyasına dönüştürebilir ve terminalden java -jar uygulama.jar komutuyla çalıştırabilirsiniz.
Uygulama Performansını İyileştirme ve Bellek Yönetimi
Küçük ölçekli not defteri uygulamalarında dosya okuma ve yazma işlemleri genellikle göz ardı edilebilir bir maliyete sahiptir. Ancak not sayınız binlere ulaştığında, her seferinde tüm dosyayı baştan okumak veya yazmak performans kayıplarına yol açabilir. Bu noktada Buffered I/O sınıflarını kullanmak, disk erişim sayısını azaltarak uygulamanızı hızlandıracaktır.
Aşağıdaki örnekte, dosya işlemlerini optimize etmek için BufferedWriter kullanımını inceleyebilirsiniz:
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public void notuKaydet(String not) {
// try-with-resources yapısı ile bellek sızıntılarını önlüyoruz
try (BufferedWriter writer = new BufferedWriter(new FileWriter("notlar.txt", true))) {
writer.write(not);
writer.newLine();
} catch (IOException e) {
System.err.println("Dosyaya yazılırken hata oluştu: " + e.getMessage());
}
}
Bellek yönetimini optimize etmek için şu stratejileri izleyebilirsiniz:
- Stream Kullanımı: Büyük dosyaları satır satır okuyarak bellekte (RAM) tüm içeriği tutmaktan kaçının.
- Kapatma İşlemleri: Dosya akışlarını (Streams) mutlaka
finallybloğunda veyatry-with-resourcesyapısı ile kapatın. - Döngü Optimizasyonu: Notları listelerken gereksiz nesne oluşturmaktan kaçının.
Uygulama İçin İleri Seviye Hata Ayıklama (Debugging) Teknikleri
Uygulamanız büyüdükçe, hataları bulmak zorlaşabilir. Sadece System.out.println kullanmak yerine, profesyonel hata yönetimi stratejileri geliştirmeniz gerekir. Özellikle dosya izinleri veya disk doluluğu gibi dış etkenlerden kaynaklanan hataları yönetmek için Custom Exception (Özel İstisna) sınıfları oluşturabilirsiniz.
Hata ayıklama sürecinde izleyebileceğiniz profesyonel bir yaklaşım:
- Loglama: Hataları konsola yazdırmak yerine bir
log.txtdosyasına tarih ve saat bilgisiyle kaydedin. - Input Validation: Kullanıcıdan gelen veriyi mutlaka kontrol edin. Boş veya geçersiz karakter içeren notları işleme almayın.
- Stack Trace Analizi: Hata oluştuğunda
e.printStackTrace()metodunu kullanarak hatanın kodun hangi satırında tetiklendiğini takip edin.
İpucu: Uygulamanızı geliştirirken "Defensive Programming" (Savunmacı Programlama) prensibini benimseyin. Yani, kullanıcının her zaman yanlış bir veri girebileceğini veya dosyanın silinmiş olabileceğini varsayarak kodunuzu yazın.
Örneğin, dosyanın varlığını kontrol eden bir metod eklemek, uygulamanın çökmesini engelleyecektir:
import java.io.File;
public boolean dosyaKontrol(String dosyaAdi) {
File file = new File(dosyaAdi);
if (!file.exists()) {
System.out.println("Not dosyası bulunamadı, yeni bir tane oluşturuluyor...");
return false;
}
return true;
}
Sonuç
Java ile konsol üzerinde not defteri oluşturmak, dosya giriş/çıkış işlemleri ve döngü yapılarını anlamak için harika bir pratik olmuştur. Bu uygulama, üzerine eklenebilecek not silme, not güncelleme veya tarih damgası ekleme gibi özelliklerle çok daha profesyonel hale getirilebilir. Bir sonraki adım olarak, bu verileri bir veritabanına (örneğin SQLite) taşımayı deneyerek "CRUD" (Create, Read, Update, Delete) mantığını tam anlamıyla kavrayabilirsiniz. Kodlama pratiği yapmaya devam edin, başarılar dilerim.


Yorumlar (0)
Yorum Yaz