Scanner ile Kullanıcı Girdisi
Şimdiye kadar yazdığımız programların hepsi tek yönlüydü — program konuştu, biz dinledik. Ama gerçek programlar interaktiftir: kullanıcıdan veri alır, işler ve sonuç üretir. Bu derste Java'da kullanıcıdan girdi almanın temel yolunu öğreneceksin: Scanner sınıfı.
Bir program, kullanıcıyla konuşamıyorsa monolog yapar. Scanner ile programlarına diyalog yeteneği kazandıracaksın.
Scanner Nedir?
Scanner, Java'nın standart kütüphanesinde bulunan bir sınıftır. java.util paketinin içinde yaşar. Adı üstünde: girdi kaynağını tarar (scan) ve içinden veri okur.
Analoji: Scanner'ı bir garson gibi düşün. Müşteriye (kullanıcıya) "Ne istersiniz?" diye sorar, cevabı alır ve mutfağa (programına) iletir. Garson yemek yapmaz, sadece sipariş alır.
Scanner sadece klavyeden değil, dosyalardan ve string'lerden de okuyabilir. Ama bu derste klavyeden (standart girdi — System.in) okumaya odaklanacağız.
İlk Scanner Kullanımı
import java.util.Scanner; // Scanner'ı import et
public class IlkScanner {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in); // Klavyeyi dinlemeye başla
System.out.print("Adın ne? "); // Kullanıcıya sor
String isim = scanner.nextLine(); // Cevabı oku
System.out.println("Merhaba, " + isim + "!"); // Cevabı kullan
scanner.close(); // İşin bitince kapat
}
}Çalıştırma:
Adın ne? Ali
Merhaba, Ali!Satır satır ne oldu:
`import java.util.Scanner;` → Scanner sınıfını programa dahil ettik. Bu satır olmadan Scanner kullanamazsın.
`Scanner scanner = new Scanner(System.in);` → Yeni bir Scanner nesnesi oluşturdum.
System.in= klavye girdisi.`System.out.print("Adın ne? ");` →
printlndeğilprintkullandık — böylece kullanıcı aynı satırda yazar.`scanner.nextLine();` → Kullanıcı bir satır yazıp Enter'a basana kadar bekler, sonra yazdığını String olarak döndürür.
`scanner.close();` → Scanner'ı kapattık. Kaynak sızıntısını önler.
Scanner Metodları
Scanner farklı veri tipleri için farklı metodlar sunar:
| Metod | Ne Okur | Dönüş Tipi | Örnek Girdi |
|---|---|---|---|
nextLine() | Satırın tamamını | String | Merhaba Dünya |
next() | Sonraki kelimeyi | String | Merhaba |
nextInt() | Tam sayı | int | 42 |
nextDouble() | Ondalıklı sayı | double | 3.14 |
nextLong() | Büyük tam sayı | long | 9000000000 |
nextFloat() | Ondalıklı sayı | float | 3.14 |
nextBoolean() | Boolean | boolean | true |
hasNextInt() | Sıradaki int mi? | boolean | — |
hasNextLine() | Başka satır var mı? | boolean | — |
Farklı Tipleri Okuma
import java.util.Scanner;
public class FarkliTipler {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Adınız: ");
String ad = scanner.nextLine();
System.out.print("Yaşınız: ");
int yas = scanner.nextInt();
System.out.print("Boyunuz (m): ");
double boy = scanner.nextDouble();
System.out.println("\n--- Bilgileriniz ---");
System.out.println("Ad: " + ad);
System.out.println("Yaş: " + yas);
System.out.println("Boy: " + boy + " m");
scanner.close();
}
}Çalıştırma:
Adınız: Zeynep
Yaşınız: 22
Boyunuz (m): 1.68
--- Bilgileriniz ---
Ad: Zeynep
Yaş: 22
Boy: 1.68 mnext() vs nextLine()
Bu ikisinin farkını anlamak önemli:
import java.util.Scanner;
public class NextVsNextLine {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("next() ile oku: ");
String kelime = scanner.next(); // Sadece ilk kelimeyi okur
System.out.println("Okunan: " + kelime);
scanner.nextLine(); // Kalan kısmı temizle (birazdan açıklayacağız)
System.out.print("nextLine() ile oku: ");
String satir = scanner.nextLine(); // Tüm satırı okur
System.out.println("Okunan: " + satir);
scanner.close();
}
}Girdi ve çıktı:
next() ile oku: Java çok güzel
Okunan: Java
nextLine() ile oku: Programlama eğlenceli
Okunan: Programlama eğlencelinext() boşluğa kadar okur (tek kelime). nextLine() Enter'a kadar okur (tüm satır).
Input Buffer Sorunu (En Önemli Konu!)
Bu, Scanner kullanırken herkesin başına gelen ve herkesin kafasını karıştıran bir sorundur. Dikkatli oku.
Sorun
nextInt(), nextDouble() gibi metodlar sayıyı okur ama Enter karakterini (\n) okumaz. Bu karakter buffer'da kalır. Hemen arkasından nextLine() çağırırsan, nextLine() buffer'daki \n'i okur ve boş string döndürür.
import java.util.Scanner;
public class BufferSorunu {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Yaşınız: ");
int yas = scanner.nextInt(); // Sayıyı okur, \n buffer'da kalır
System.out.print("Adınız: ");
String ad = scanner.nextLine(); // Buffer'daki \n'i okur — boş string!
System.out.println("Ad: '" + ad + "'"); // Boş!
System.out.println("Yaş: " + yas);
scanner.close();
}
}Çalıştırma:
Yaşınız: 25
Adınız: Ad: ''
Yaş: 25Kullanıcıya isim sorulmadı bile! nextLine() buffer'daki \n'i okuyup hemen döndü.
Çözüm: Buffer'ı Temizle
nextInt() veya nextDouble()'dan sonra fazladan bir nextLine() çağırarak buffer'ı temizle:
import java.util.Scanner;
public class BufferCozum {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Yaşınız: ");
int yas = scanner.nextInt();
scanner.nextLine(); // ← Buffer'ı temizle! Bu satır kritik.
System.out.print("Adınız: ");
String ad = scanner.nextLine(); // Artık düzgün çalışır
System.out.println("Ad: " + ad);
System.out.println("Yaş: " + yas);
scanner.close();
}
}Çalıştırma:
Yaşınız: 25
Adınız: Ali
Ad: Ali
Yaş: 25⚠️ Dikkat: Bu, Java'nın en bilinen Scanner tuzağıdır. nextInt(), nextDouble(), next() gibi metodlardan sonra nextLine() kullanacaksan, arada fazladan bir scanner.nextLine() çağrısı yap.
Alternatif Çözüm: Her Şeyi nextLine() ile Oku
Bazı geliştiriciler sorunu tamamen ortadan kaldırmak için her şeyi nextLine() ile okuyup sonra dönüştürür:
import java.util.Scanner;
public class HerSeyNextLine {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Yaşınız: ");
int yas = Integer.parseInt(scanner.nextLine()); // String → int
System.out.print("Boyunuz: ");
double boy = Double.parseDouble(scanner.nextLine()); // String → double
System.out.print("Adınız: ");
String ad = scanner.nextLine();
System.out.printf("%s, %d yaşında, %.2f m%n", ad, yas, boy);
scanner.close();
}
}Bu yaklaşım buffer sorununu tamamen ortadan kaldırır. Ama kullanıcı sayı yerine harf girerse NumberFormatException hatası fırlatır. İleride exception handling öğrendiğimizde bunu da ele alacağız.
Girdi Doğrulama (Basit)
Kullanıcıya güvenme. Sayı beklediğin yere metin girebilir. hasNextInt() gibi metodlarla kontrol edebilirsin:
import java.util.Scanner;
public class GirdiDogrulama {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Bir tam sayı girin: ");
if (scanner.hasNextInt()) {
int sayi = scanner.nextInt();
System.out.println("Girdiğiniz sayı: " + sayi);
} else {
System.out.println("Bu bir tam sayı değil!");
}
scanner.close();
}
}Çalıştırma:
Bir tam sayı girin: 42
Girdiğiniz sayı: 42
Bir tam sayı girin: abc
Bu bir tam sayı değil!Döngü ile kullanıcıdan doğru girdi alana kadar sorma:
import java.util.Scanner;
public class DogruGirdiAl {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int sayi = 0;
boolean gecerli = false;
while (!gecerli) {
System.out.print("Bir tam sayı girin: ");
if (scanner.hasNextInt()) {
sayi = scanner.nextInt();
gecerli = true;
} else {
System.out.println("Geçersiz! Lütfen sayı girin.");
scanner.next(); // Geçersiz girdiyi temizle
}
}
System.out.println("Teşekkürler! Girdiğiniz: " + sayi);
scanner.close();
}
}Locale Sorunu (Ondalık Ayırıcı)
Türkiye'de ondalık ayırıcı virgül (3,14), ABD'de nokta (3.14). Scanner, sistemin locale'ine göre davranır. Türkçe bir sistemde nextDouble() nokta beklemeyebilir.
import java.util.Scanner;
import java.util.Locale;
public class LocaleOrnegi {
public static void main(String[] args) {
// ABD locale'i ile Scanner oluştur (nokta = ondalık ayırıcı)
Scanner scanner = new Scanner(System.in).useLocale(Locale.US);
System.out.print("Bir ondalıklı sayı girin (nokta ile): ");
double sayi = scanner.nextDouble();
System.out.println("Girdiğiniz: " + sayi);
scanner.close();
}
}💡 İpucu: scanner.useLocale(Locale.US) kullanarak ondalık ayırıcının her zaman nokta olmasını sağlayabilirsin. Bu, kodunun farklı ülkelerdeki sistemlerde tutarlı çalışmasını garanti eder.
Mini Proje 1: Selamlama Programı
import java.util.Scanner;
public class Selamlama {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("=== Hoş Geldiniz! ===");
System.out.println();
System.out.print("Adınız: ");
String ad = scanner.nextLine();
System.out.print("Soyadınız: ");
String soyad = scanner.nextLine();
System.out.print("Doğum yılınız: ");
int dogumYili = Integer.parseInt(scanner.nextLine());
int yas = 2026 - dogumYili;
System.out.println();
System.out.println("=== Bilgileriniz ===");
System.out.printf("Ad Soyad: %s %s%n", ad, soyad);
System.out.printf("Yaş: %d%n", yas);
if (yas < 18) {
System.out.println("Henüz reşit değilsiniz.");
} else if (yas < 65) {
System.out.println("Çalışma çağındasınız.");
} else {
System.out.println("Emeklilik hakkınız var.");
}
scanner.close();
}
}Çalıştırma:
=== Hoş Geldiniz! ===
Adınız: Ayşe
Soyadınız: Demir
Doğum yılınız: 2001
=== Bilgileriniz ===
Ad Soyad: Ayşe Demir
Yaş: 25
Çalışma çağındasınız.Mini Proje 2: Basit Hesap Makinesi
import java.util.Scanner;
public class HesapMakinesi {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("╔═══════════════════════════╗");
System.out.println("║ BASİT HESAP MAKİNESİ ║");
System.out.println("╚═══════════════════════════╝");
System.out.println();
System.out.print("Birinci sayıyı girin: ");
double sayi1 = Double.parseDouble(scanner.nextLine());
System.out.print("İkinci sayıyı girin: ");
double sayi2 = Double.parseDouble(scanner.nextLine());
System.out.print("İşlem seçin (+, -, *, /): ");
String islem = scanner.nextLine().trim();
double sonuc = 0;
boolean gecerli = true;
switch (islem) {
case "+":
sonuc = sayi1 + sayi2;
break;
case "-":
sonuc = sayi1 - sayi2;
break;
case "*":
sonuc = sayi1 * sayi2;
break;
case "/":
if (sayi2 != 0) {
sonuc = sayi1 / sayi2;
} else {
System.out.println("Hata: Sıfıra bölme yapılamaz!");
gecerli = false;
}
break;
default:
System.out.println("Hata: Geçersiz işlem!");
gecerli = false;
}
if (gecerli) {
System.out.printf("%.2f %s %.2f = %.2f%n", sayi1, islem, sayi2, sonuc);
}
scanner.close();
}
}Çalıştırma:
╔═══════════════════════════╗
║ BASİT HESAP MAKİNESİ ║
╚═══════════════════════════╝
Birinci sayıyı girin: 15.5
İkinci sayıyı girin: 4.2
İşlem seçin (+, -, *, /): *
15.50 * 4.20 = 65.10Mini Proje 3: Not Ortalaması Hesaplama
import java.util.Scanner;
public class NotOrtalamasi {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Kaç ders var? ");
int dersSayisi = Integer.parseInt(scanner.nextLine());
double toplam = 0;
for (int i = 1; i <= dersSayisi; i++) {
System.out.printf("%d. dersin notu (0-100): ", i);
double not_ = Double.parseDouble(scanner.nextLine());
toplam += not_;
}
double ortalama = toplam / dersSayisi;
System.out.println("\n=== SONUÇ ===");
System.out.printf("Toplam: %.1f%n", toplam);
System.out.printf("Ortalama: %.2f%n", ortalama);
// Harf notu
String harfNotu;
if (ortalama >= 90) harfNotu = "AA";
else if (ortalama >= 80) harfNotu = "BA";
else if (ortalama >= 70) harfNotu = "BB";
else if (ortalama >= 60) harfNotu = "CB";
else if (ortalama >= 50) harfNotu = "CC";
else harfNotu = "FF";
System.out.println("Harf Notu: " + harfNotu);
if (ortalama >= 50) {
System.out.println("Durum: GEÇTİ ✓");
} else {
System.out.println("Durum: KALDI ✗");
}
scanner.close();
}
}Çalıştırma:
Kaç ders var? 3
1. dersin notu (0-100): 85
2. dersin notu (0-100): 72
3. dersin notu (0-100): 91
=== SONUÇ ===
Toplam: 248.0
Ortalama: 82.67
Harf Notu: BA
Durum: GEÇTİ ✓Scanner Kapatma ve Kaynak Yönetimi
Scanner'ı kapamak iyi bir alışkanlıktır. İki yöntem var:
Manuel Kapatma
Scanner scanner = new Scanner(System.in);
// ... kullanım ...
scanner.close(); // Manuel kapatTry-with-Resources (Önerilen)
Java 7'den itibaren try-with-resources kullanabilirsin. Blok bitince Scanner otomatik kapanır:
import java.util.Scanner;
public class TryWithResources {
public static void main(String[] args) {
try (Scanner scanner = new Scanner(System.in)) {
System.out.print("Bir sayı girin: ");
int sayi = scanner.nextInt();
System.out.println("Girdiğiniz: " + sayi);
} // scanner.close() otomatik çağrılır
}
}⚠️ Dikkat: System.in üzerindeki Scanner'ı kapattığında, System.in de kapanır ve tekrar açılamaz. Yani programda ikinci bir Scanner oluşturamazsın. Küçük programlarda sorun olmaz ama büyük projelerde Scanner'ı başta bir kere oluşturup tüm program boyunca kullanmak daha iyi.
Delimiter (Ayırıcı) Değiştirme
Scanner varsayılan olarak boşluk ve yeni satır karakterlerini ayırıcı olarak kullanır. Bunu değiştirebilirsin:
import java.util.Scanner;
public class DelimiterOrnegi {
public static void main(String[] args) {
// Virgülle ayrılmış veri oku
String veri = "Ali,25,Istanbul,Muhendis";
Scanner scanner = new Scanner(veri);
scanner.useDelimiter(",");
String isim = scanner.next();
int yas = scanner.nextInt();
String sehir = scanner.next();
String meslek = scanner.next();
System.out.printf("%s, %d yaşında, %s'da %s%n", isim, yas, sehir, meslek);
scanner.close();
}
}Çıktı:
Ali, 25 yaşında, Istanbul'da MuhendisBu özellik CSV benzeri formatları okurken çok işe yarar.
Scanner Alternatifleri (Kısa Bakış)
Scanner en basit yol ama tek yol değil:
BufferedReader (Daha Hızlı)
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class BufferedReaderOrnegi {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Adınız: ");
String isim = reader.readLine();
System.out.print("Yaşınız: ");
int yas = Integer.parseInt(reader.readLine());
System.out.printf("Merhaba %s, %d yaşındasın!%n", isim, yas);
}
}BufferedReader, Scanner'dan daha hızlıdır çünkü daha az işlem yapar. Ama kullanımı biraz daha zahmetli — her şeyi String olarak okur, tip dönüşümünü sen yaparsın.
Console Sınıfı (Parola Okuma)
import java.io.Console;
public class ConsoleOrnegi {
public static void main(String[] args) {
Console console = System.console();
if (console != null) {
String isim = console.readLine("Kullanıcı adı: ");
char[] parola = console.readPassword("Parola: "); // Ekranda gözükmez!
System.out.println("Giriş yapılıyor: " + isim);
}
}
}Console.readPassword() parolayı ekranda göstermeden okur. Güvenlik gerektiren uygulamalar için kullanılır. Ama IDE'lerin console'unda çalışmayabilir — terminalde çalıştırman gerekir.
Sık Yapılan Hatalar
1. Import Unutmak
// HATA — import yok
public class Test {
public static void main(String[] args) {
Scanner s = new Scanner(System.in); // Derleme hatası!
}
}Çözüm: Dosyanın başına import java.util.Scanner; ekle.
2. InputMismatchException
System.out.print("Sayı girin: ");
int sayi = scanner.nextInt();
// Kullanıcı "abc" yazarsa → InputMismatchException!Çözüm: hasNextInt() ile kontrol et veya nextLine() + Integer.parseInt() kullan.
3. Buffer Sorununu Unutmak
int yas = scanner.nextInt();
// scanner.nextLine(); ← BU SATIRI UNUTMAK
String isim = scanner.nextLine(); // Boş string döner!Çözüm: nextInt() veya nextDouble()'dan sonra fazladan scanner.nextLine() çağır.
Özet
Scanner,
java.utilpaketindeki bir sınıftır.import java.util.Scanner;ile dahil edilir venew Scanner(System.in)ile oluşturulur.`nextLine()` tüm satırı, `next()` tek kelimeyi, `nextInt()` tam sayıyı, `nextDouble()` ondalıklı sayıyı okur.
Input buffer sorunu en sık karşılaşılan tuzaktır:
nextInt()/nextDouble()sonrasınextLine()kullanacaksan, arada fazladan birscanner.nextLine()çağrısı yap.Girdi doğrulama için
hasNextInt(),hasNextDouble()gibi metodlar kullanılabilir.Locale sorunu:
scanner.useLocale(Locale.US)ile ondalık ayırıcıyı nokta olarak sabitleyebilirsin.Scanner kullanımı bitince `close()` ile kapatmak veya try-with-resources kullanmak iyi bir alışkanlıktır.
AI Asistan
Sorularını yanıtlamaya hazır