22 Ekim 2018 Pazartesi

Scanner Sınıfı

Giriş
Şu satırı dahil ederiz.
import java.util.Scanner;
Scanner stream'den okuma yapmamızi sağlar. AutoCloseable olduğu için try/catch ile kullanılaibilir.

constructor - File
Şöyle yaparız
File file = ...
Scanner sc = new Scanner (file); 
constructor - Stream
Şöyle yaparız.
Scanner sc = new Scanner(System.in);
close metodu
Nesneyi ve sarmaladığı stream'i kapatır. Stream'den bir daha okuma yapılamaz. Şöyle yaparız.
try (Scanner scanner = new Scanner(..)) {
...
}

 Şu kod System.in kapatıldığı için hata verir.
Scanner sc=new Scanner(System.in);
sc.close();
Scanner sc1=new Scanner(System.in);
sc1.nextInt();
constructor - String
Şöyle yaparız.
String str = "...";

try (Scanner sc = new Scanner(str).useDelimiter(",|\n")) {
  ...
} catch (Exception e) {
  ...
}
findAll metodu
Java 9 ile geliyor. 4 satırı birden okumak için şöyle yaparız. \R "Unicode linebreak sequence" için kullanılır. findAll Stream<MatchResult> döner. MatchResult'ın yakaladığı group()'u bir daha satırlara ayırırız ve List'e çeviririz.
try(Scanner s = new Scanner(PATH)) {
    s.findAll("(.*\\R){1,4}")
     .map(mr -> Arrays.asList(mr.group().split("\\R")))
     .forEach(System.out::println);
}

hasNext metodu
Açıklaması şöyle
hasNext() blocks until there's input.
Ekrandan kullanıcı bitirinceye kadar sürekli veri okumak için şöyle yaparız.
System.out.println("Enter x1 or <crtl + z> to quit");
while (sc.hasNext()) {
  double x1 = sc.nextDouble();

  System.out.println("Please input the x2 number:");
  double x2 = sc.nextDouble();

    //...

  System.out.println("Enter x1 or <crtl + z> to quit");
}
hasNextDouble metodu
Şöyle yaparız.
while (sc.hasNextDouble()){
  double negNum = sc.nextDouble();
  ...       
}
hasNextInt metodu
Şöyle yaparız.
while (sc.hasNextInt()){
  int num = nsc.nextInt();
  ...       
}
Pozitif bir sayı okumak için şöyle yaparız.
int number;
do {
  System.out.println("Input Number ");
  while (!sc.hasNextInt()) {
    System.out.println(" not a number!");
    sc.next(); 
  }
  number = sc.nextInt();
} while (number <= 0);
locale metodu
Locale nesnesi döner. Şöyle yaparız.
Locale lc = new Scanner(System.in).locale();
nextX metodları
Bu metodları çağırmadan önce hasX ile okuma işleminin yapılıp yapılamayacağını kontrol etmek iyi olabilir. Eğer nextX çağrısı ile istenilen token tipi eşleşmezse
java.util.InputMismatchException
fırlatılır. Eğer stream'in sonuna geldiysek
java.util.NoSuchElementException
fırlatılır.

next metodu
Bir sonraki kelimeyi String olarak döndürür. Tüm satırı okumak istiyorsak nextLine() metodunu çağırmak gerekir.

Örnek
Şöyle yaparız.
String s="tree;dog;house;computer sience";
Scanner scanner = new Scanner(s).useDelimiter(";");
String a = scanner.next();
String b = scanner.next();
String c = scanner.next();
String d = scanner.next();
scanner.close();
Örnek
Dosyamız şöyle olsun
foo bar foo
bar baz
Her next()'i çağırışımızda foobarfoobarbar kelimelerini alırız

nextInt metodu
Şöyle yaparız
Scanner sc =new Scanner(System.in);
System.out.println("Enter your integer here");
int i = sc.nextInt();
nextLine metodu
Açıklaması şöyle. Satır sonuna kadar olan her şeyi okur.
Advances this scanner past the current line and returns the input that was skipped. This method returns the rest of the current line, excluding any line separator at the end. The position is set to the beginning of the next line.
Tüm satırı okumak için şöyle yaparız
Scanner sc = new Scanner(System.in);
System.out.print("Enter file path: ");
String filepath = sc.nextLine();
Boş string dönebilir. Şöyle kontrol ederiz.
String lastName = sc.nextLine();
if(lastName.isEmpty()){...}
Eğer aynı satırda int ve double varsa ve diğer satıra geçmek istiyorsak şöyle yaparız.
int i = sc.nextInt();double d = sc.nextDouble();sc.nextLine(); // This line
reset metodu
Açıklaması şöyle
Resets the "metadata" associated with the scanner - its whitespace, delimiter characters, and so on. It does not change the state of its input,
Ayrıca şöyle
Only "resets" locale, radix and delimiter settings. It does not do anything to the data it already read.
Şöyle yaparız.
sc.reset();
useDelimeter metodu
Açıklaması şöyle
useDelimiter
public Scanner useDelimiter(String pattern)
Sets this scanner's delimiting pattern to a pattern constructed from the specified String.
Ayraç düzenli ifadedir (regular expression - regex)

1.Satır satır alan okuma yapacaksak \n karakterini mutlaka dahil etmek gerekir. Şöyle yaparız.
sc.useDelimiter (",|\n");
Elimizde şöyle bir dosya olsun
JAKIE JOHNSON,2051.59
SAMUEL PAUL SMITH,10842.23
ELISE ELLISON,720.54
Birinci alan şöyledir
JAKIE JOHNSON,2051.59
^^^^^^^^^^^^^
İkinci alan şöyledir. Yeni satır da ayraç olduğu için satır sonunda okuma durur.
JAKIE JOHNSON,2051.59
              ^^^^^^^
Eğer yeni satırı ayraç olarak vermezsek şöyle olur. Okuma bir sonraki satırda durur ve hata oluşur!
JAKIE JOHNSON,2051.59
              ^^^^^^^
SAMUEL PAUL SMITH,10842.23
^^^^^^^^^^^^^^^^^
2. Eğer çift satır atlamak istersek şöyle yaparız.
Scanner sc = ...;
sc.useDelimiter("\n\n");   
3. Tek bir satırda alan okumak istersek şöyle yaparız.
// \\s* means 0 or more repetitions of any whitespace character 
 // fish is the pattern to find
sc.useDelimiter("\\s*fish\\s*");
Düzenli ifade olarak şu değerler kullanılabilir.
abc    Letters
123    Digits
\d      Any Digit
\D      Any Non-digit character
.       Any Character
\.      Period
[abc]   Only a, b, or c
[^abc]  Not a, b, nor c
[a-z]   Characters a to z
[0-9]   Numbers 0 to 9
\w      Any Alphanumeric character
\W      Any Non-alphanumeric character
{m}     m Repetitions
{m,n}   m to n Repetitions
*       Zero or more repetitions
+       One or more repetitions
?       Optional character
\s      Any Whitespace
\S      Any Non-whitespace character
^…$     Starts and ends
(…)     Capture Group
(a(bc)) Capture Sub-group
(.*)    Capture all
(ab|cd) Matches ab or cd
useLocale metodu
Şöyle yaparız.
sc.useLocale(Locale.US);
Diğer
Elimizde şöyle yardımcı metodlar olsun.
private Integer readInteger() {
  Integer value = null;
  while (value == null) {
    if (scanner.hasNextInt()) {
      value = scanner.nextInt();
    } else {
      scanner.next();
    }
  }

  return value;
}

private Double readDouble() {
  Double value = null;
  while (value == null) {
    if (scanner.hasNextDouble()) {
      value = scanner.nextDouble();
    } else {
      scanner.next();
    }
  }

  return value;
}
Her ikisni birleştirmek için şöyle yaparız.
private <T> T read(Predicate<Scanner> hasVal, Function<Scanner, T> nextVal) {
  T value = null;
  while (value == null) {
    if (hasVal.test(scanner)) {
      value = nextVal.apply(scanner);
    } else {
      scanner.next();
    }
  }

  return value;
}
Çağırmak için şöyle yaparız.
read(Scanner::hasNextInt, Scanner::nextInt);
read(Scanner::hasNextDouble, Scanner::nextDouble);
read(Scanner::hasNextFloat, Scanner::nextFloat);
// ...
Böylece kod şu hale gelir.
private Integer readInteger() {
  return read(Scanner::hasNextInt, Scanner::nextInt);
}

Hiç yorum yok:

Yorum Gönder