CodeGym /Java Blogu /Rastgele /Klavyeden okuma: "readers"
John Squirrels
Seviye
San Francisco

Klavyeden okuma: "readers"

grupta yayınlandı
MERHABA! 3. Seviyedeki dersler ve görevler size konsolda öğeleri nasıl görüntüleyeceğinizi ve diğer yönde hareket ederek klavyeden verileri nasıl okuyacağınızı öğretti.
Klavyeden okuma: "okuyucu" - 1
Bunu başarmak için aşağıdaki karmaşık yapıyı kullanmayı bile öğrendiniz:

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Ancak henüz yanıtlamadığımız bir soru var.

Bu nasıl işliyor?

Gerçekte, programlar nadiren tamamen bağımsızdır. Diğer programlar, sistemler, İnternet vb. ile iletişim kurarlar. "İletişim kurmak" derken, esas olarak "veri alışverişi" ni kastediyoruz. Yani, bazı dış verileri alırlar ve ayrıca dahili program verilerini bir yere gönderirler. Veri alışverişi yapan programların örnekleri günlük yaşamda çoktur. Örneğin, birçok web sitesi kaydolmak yerine Facebook veya Twitter hesabınızı kullanarak oturum açmanıza izin verir. Bu durumda, iki program (örn. Twitter ve oturum açtığınız web sitesi) gerekli verileri değiştirir. Nihai sonuç, başarıyla oturum açmış olmanızdır. "Akış" kelimesiveri alışverişi sürecini açıklamak için kullanılır. Bu isim nereden geldi? Deneyimlerinize göre, bir "akarsu" programlamadan çok nehirlerle ve daha çok ilişkilendirilebilir. Bu bir tesadüf değil :) Akış, özünde hareket eden bir veri parçasıdır. Başka bir deyişle, programlamada akan su değil, bayt ve karakter biçimindeki verilerdir. Bir veri akışından veri bitleri alabilir ve sonra bunları kullanabiliriz. Yine su/akış benzetmesini kullanacağız: Çorba yapmak, ateşi söndürmek veya çiçeklerinizi sulamak için nehirden su alabilirsiniz. Akışlar, herhangi bir veri kaynağıyla çalışmanıza izin verir: İnternet, bilgisayarınızın dosya sistemi veya başka bir şey fark etmez. Akışlar evrensel bir araçtır. Bir programın herhangi bir yerden veri almasına (giriş akışları) ve herhangi bir yere göndermesine (çıkış akışları) izin verirler. Görevleri aynı: bir yerden veri alıp başka bir yere göndermek. İki tür akış vardır:
  1. Giriş akışları veri almak için kullanılır
  2. Çıkış akışları veri göndermek içindir.
Java'da bu akışlar InputStreamve OutputStreamsınıfları tarafından uygulanır. Ancak akışlar başka bir şekilde kategorize edilebilir. Girdi ve çıktı akışlarına ek olarak, bayt akışlarından ve karakter akışlarından da söz ediyoruz . Buradaki anlam yeterince açık olmalıdır: bayt akışı bilgiyi bir bayt dizisi olarak gönderirken, bir karakter akışı onu bir karakter kümesi olarak gönderir. Bu derste girdi akışları üzerinde duracağız. Dersin sonuna çıktı akışları hakkında bilgi içeren bir bağlantı koyacağım. Kendi başınıza okuyabilirsiniz :) Şimdi şu koda bir göz atın:

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Dersleri okurken, bu satırın oldukça korkutucu olduğunu düşünmediniz mi? :) Nasıl çalıştığını keşfettikten sonra durum böyle olmayacak. İşleri yoluna koyalım. Sondan başlayacağız. System.inbir InputStreamnesne, daha önce bahsettiğimiz sınıfın bir örneği. Bir sistem giriş cihazına (klavye) bağlı bir giriş akışıdır. Bu arada, bu akışa dolaylı olarak aşinasınız. Ne de olsa, sık sık onun "iş arkadaşını" kullanıyorsunuz - System.out! System.outsistem çıkış akışıdır. System.out.println()Sürekli olarak kullandığınız favori yönteminizle konsola veri çıkışı yapmak için kullanılır :) System.outkonsola veri göndermek için bir akıştır, oysaSystem.inklavyeden veri almak içindir. Her şey çok basit :) Üstelik bu devasa yapı olmadan da klavyeden veri okuyabiliyoruz. Basitçe şunu yazabiliriz: System.in.read();

public class Main {

   public static void main(String[] args) throws IOException {

       while (true) {
           int x = System.in.read();
           System.out.println(x);
       }
   }
}
Sınıfın InputStream(unutmayın, System.inbir InputStreamnesnedir) read()verileri okumanıza izin veren bir yöntemi vardır. Bir sorun var: karakterleri değil bytes okur . Sadece İngilizce harfleri kullanmak sıkıcı, bu yüzden klavyeden "魚" Çince karakterini okumayı deneyelim (buradan bu harfi kopyalayıp PC'de ctrl + v veya Mac'te Command + v kullanarak konsola yapıştırmanız yeterli ) . Bu karakter bu arada 'balık' anlamına geliyor. Konsol çıkışı: 233 173 154 10 Bu sembol ve diğer birçok Çince, bilgisayarın belleğinde 3 bayt yer kaplar (yalnızca 1 bayt yer kaplayan Latin harflerinin aksine). Bu durumda akıştan 4 bayt okunur: ilk üçü "魚" karakterini, diğer bayt ise yeni bir satırı (Enter) temsil eder. Dolayısıyla System.insade haliyle bizim için bir seçenek değil. İnsanlar (nadir istisnalar dışında!) baytları nasıl okuyacaklarını bilmiyorlar. Ama InputStreamReadersınıf kurtarmaya geliyor! Bunun ne tür bir hayvan olduğunu görelim.

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
InputStreamReaderSystem.in nesnesine geçiyoruz . Sınıf adı söylüyor! Bir nesne yaratıyoruz ve ona verileri okuyacağı bir giriş akışı iletiyoruz. Bu durumda... InputStreamReader

new InputStreamReader(System.in)
...ona "verileri sistem giriş akışından (klavyeden) okuyacaksınız" diyoruz. Ancak tek işlevi bu değil! Yalnızca InputStreamReaderakıştan veri almaz. Ayrıca bayt akışlarını karakter akışlarına dönüştürür . Başka bir deyişle, artık verileri "birler ve sıfırlardan" "insan tarafından okunabilir bir dile" dönüştürmenize gerek yok. InputStreamreadersizin için her şeyi yapar Elbette InputStreamReaderkonsoldan veri okumakla sınırlı değil. Diğer yerlerden de veri okuyabilir. Örneğin, bir dosyadan:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

   public static void main(String[] args) throws IOException {
       InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("C:\\Users\\username\\Desktop\\testFile.txt"));
   }
}
FileInputStreamBurada bir (tek çeşit ) oluşturuyoruz InputStream, dosya yolundan geçiyoruz ve akışın kendisini InputStreamReader. Artık dosyadan veri okuyabilecek (tabii ki yolda gerçekten bir dosya varsa). InputStreamReaderVerileri okumak için sınıfın yöntemini de kullanırız read()(verilerin kaynağı önemli değildir: konsol, dosya veya başka bir yer). System.in.read()ile arasındaki fark nedir InputStreamReader.read()?\ Yine "魚" karakterini InputStreamReader. Size aslında şunun okuduğunu hatırlatıyorum System.in.read(): 233 173 154 10 Peki InputStreamReaderaynısı nasıl oluyor?

public class Main {

   public static void main(String[] args) throws IOException {

       InputStreamReader reader = new InputStreamReader(System.in);
       while (true) {
           int x = reader.read();
           System.out.println(x);
       }
   }
}
Konsol çıktısı: 39770 10 Fark hemen kendini gösterir. Son bayt (yeni satırı temsil eder) değişmeden kalır (10 sayısı), ancak "魚" karakteri tek bir "39770" koduna dönüştürüldü. Karakterleri okumanın anlamı budur! 39770'in "魚" harfini temsil ettiğine inanmıyorsanız, kendinizi ikna etmeniz çok kolay :)
import java.io.IOException;

public class Main {

   public static void main(String[] args) throws IOException {

       char x = 39770;
       System.out.println(x);
   }
}
Konsol çıktısı: Ama eğer InputStreamReaderbu kadar harikaysa, neden buna da ihtiyacımız var BufferedReader? InputStreamReaderverileri okumayı ve baytları karakterlere dönüştürmeyi bilir. Daha ne isteyebiliriz ki? Neden başka bir Okuyucu? :/ Cevap çok basit: daha fazla performans ve rahatlık için . Performansla başlayalım. Veri okurken BufferedReader, okuduğu karakterleri "depoladığı" arabellek adı verilen özel bir alan kullanır. Sonuçta programda bu karakterlere ihtiyaç duyulduğunda doğrudan veri kaynağından (klavye, dosya vb.) değil, tampondan alınacaktır. Bu, çok fazla kaynak tasarrufu sağlar. Bunun nasıl çalıştığını anlamak için büyük bir şirkette bir kurye hayal edin. Kurye bir ofiste oturuyor ve birisinin teslimat için paketleri getirmesini bekliyor. Her yeni paket aldığında, hemen yola çıkabilir. Ancak gün içinde çok sayıda paket olabilir. Ofis ile teslimat adresleri arasında çok sefer yapması gerekecekti. Bunun yerine kurye ofisine bir kutu koyar. Herkes paketlerini kutuya koyar. Artık kurye sakince kutuyu alıp adresten adrese gidebilir. Bu çok zaman kazandırır çünkü her seferinde ofise dönmesi gerekmez. Bu örnekte, kutu yalnızca bir arabellektir ve ofis bir veri kaynağıdır. Kuryenin teslimat yaparken tek bir koliden paket alması, her seferinde ofise gitmekten çok daha kolaydır. Benzinden de tasarruf edecek. Benzer şekilde, bir programda bir arabellekten veri almak, her seferinde veri kaynağına başvurmaktan çok daha az kaynak yoğundur. Sonuç olarak,BufferedReader+ tek InputStreamReaderbaşına daha hızlıdırInputStreamReader . Performansı değerlendirdik. Peki kolaylık? Ana avantajı, Bufferedreaderverileri bir seferde yalnızca bir karakter değil (bunu kendi yöntemiyle yapabilse de read()), aynı zamanda bir seferde tüm satırları da okuyabilmesidir! Bu yöntem kullanılarak yapılır readLine();

public class Main {

   public static void main(String[] args) throws IOException {

       BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
       String s = reader.readLine();
       System.out.println("We read this line from the keyboard:");
       System.out.println(s);
   }
}
Konsol çıktısı: CodeGym, Java öğrenmek için en iyi web sitesidir! Klavyeden şu satırı okuyoruz: CodeGym, Java öğrenmek için en iyi web sitesidir! Bu, özellikle büyük miktarda veri okurken kullanışlıdır. Bir veya iki satırlık metin karakter karakter okumak hala mümkündür. Ama "Savaş ve Barış"ta her seferinde bir harf okumak biraz problemli olur :)

Daha fazla okuma:

Yorumlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION