InputStream Sınıfı java.io Class InputStream java.lang.Object java.io.InputStream Kılgıladığı Arayüzleri: Closeable, AutoCloseable Altsınıfları: AudioInputStream, ByteArrayInputStream, FileInputStream, FilterInputStream, ObjectInputStream, PipedInputStream, SequenceInputStream, StringBufferInputStream InputStream, InputStream sınıfı soyut bir sınıftır. Verinin kaynağının ne olduğu değil, o kaynaktan alınan veriye nasıl erişileceği daha önemlidir. InputStream sınıfı bu işi yapar. Alt sınıfları aşağıdaki tabloda belirtilmiştir. Anımsayacağınız gibi, Java’da bütün sınıflar Object sınıfından türetilir. Kaynaktaki veri tipine uyan altsınıf seçilir. Onunla kaynaktan gelecek veriler için bir giriş akımı yaratılır ve veri belleğe akıtılır. Farklı işlevlere sahip InputStream sınıfının altsınıfları aşağıdaki listeden görülebilir. Object InputStream FileInputStream PipedInputStream ByteArrayInputStream SequenceInputStream StringBufferInputStream (deprecated) ObjectInputStream AudioInputStream org.omg.CORBA.portable.InputStream FilterInputStream (abstract) BufferedInputStream CheckedInputStream CipherInputStream DataInputStream DeflaterInputStream DigestInputStream InflaterInputStream LineNumberInputStream (deprecated) ProgressMonitorInputStream PushbackInputStream 1 InputStream sınıfı veri girişi yapan bütün sınıfların üst sınıfıdır. Bunun alt sınıfları yukarıdaki şekilde görülmektedir. Bu sınıfın metotları aşağıda açıklanmıştır. Bu listeden görüldüğü gibi, InputStream sınıfının veri okuyan üç ayrı read() metodu vardır. • • • • • • • • • abstract int read() int read(byte[] b) int read(byte[] b, int off, int len) long skip(long n) int available() synchronized void mark(int readlimit) synchronized void reset() boolean markSupported() void close() abstract int read() Parametresiz read() metodu, giriş akımında sıradaki ilk byte’ı okur; ard arda kullanıldığında byte dizileri okuyacaktır. Bir byte bir karektere karşılık gelen ascii kodudur; 0 ile 255 arasında olan bir int değere sahiptir. Dolayısıyla, bir metin okunuyorsa, okunan byte’ların char tipine dönüştürülmesi gerekir. Giriş akımının sonuna gelindiğinde fonksiyon –1 değerini alır. Tabii, metin okumak için, java.io.InputStream yerine java.io.Reader sınıfı tercih edilmelidir. int read(byte[] b) Giriş akımından okuduğu byte verileri bufferdaki b arrayine yazar. Giriş akımının sonuna gelindiğinde –1 değerini alır. Đlk okunan byte b[0] bileşenine, ikinci okunan byte b[1] bileşenine, üçüncü okunan byte b[3] bileşenine yazılır ve böylece devam eder. Tabii, en çok b arrayinin uzunluğu kadar byte okuyabilir. int read(byte[] b, int off, int len) Önceki metoda çok benzer. Tek farkı şudur: Đlk okunan byte b[off] bileşenine, ikinci okunan byte b[off+1] bileşenine, üçüncü okunan byte b[off+2] bileşenine yazılır ve böyle devam eder. len parametresi okunacak maksimum byte sayısını belirtir. Dolayısıyla, en çok len sayıda byte okur. long skip(long n) Giriş akımından n tane byte atlanmasını sağlar. Fonksiyonun değeri atlanan byte sayısıdır. Giriş akımının sonuna gelinmişse, fonksiyon –1 değerini alır. int available() Giriş akımından okunabilecek byte sayısını verir. Kesintiye uğramadan okunabilecek veri olup olmadığını bilmek istediğimizde kullanabileceğimiz iyi bir araçtır. synchronized void mark(int readlimit) Giriş akımın neresinde bulunulduğunu işaretler. reset() metodu ile önceden işaretli (marked) yere dönülür, böylece son okunanlar tekrar okunabilir. synchronized void reset() Mark ile bir önce işaret edilen yere dönmeyi sağlar. 2 boolean markSupported() Veri akımının, mark/reset yapısını desteklenip desteklemediğini belirtir. boolean değer verir. void close() Giriş akımını kapatır ve bununla bağlantılı olan kaynakları serbest bırakır. InputStream nesnesinin işi bitince, onu işaret eden referans yok olur. Referansı yok olan nesneyi çöpçü (garbage collector) bellekten siler; böylece giriş akımı kendiliğinden kapanır. Bu nedenle, giriş akımını kapatmak için close() fonksiyonunu kullanmak zorunlu değildir. Ama, çöpçünün o işi yapmasını beklemeden, işi biten giriş akımını close() metodu ile kapatmak, söz konusu akımın kullandığı sistem kaynaklarını hemen serbest bırakacağı için, önerilen iyi bir alışkanlıktır. Java 1.5 ile gelen Scanner sınıfı yokken, yani Java 1.4 ve önceki sürümlerinde System.in ile ancak byte ya da byte dizileri okunabiliyordu. Okunan byte bir int olarak girdiği için, text okunurken her birisinin char tipine dönüştürülmesi gerektiğini söylemiştik. Bunu yapmak için şu kodlar yeterlidir: try { int xxx = System.in.read (); char c = (char) xxx; } catch (IOException e) {} Burada ikinci satır karekterin ascii kodunu okur, üçüncü satır onu char tipine dönüştürür. Bunu yapabilmesi için, klavyeden 8-bit ile kodlanmış karekter (örneğin ascii kodu) girileceği öngörülüyor. Java giriş/çıkış işlemlerinde oluşabilecek hatalar için daima yukarıdaki gibi bir try/catch bloku yazmak iyi bir alışkanlıktır. Bu yapıda try bloku okuma eylemini yapar. Bu sırada oluşabilecek hatayı catch bloku yakalar ve kullanıcıya iletir. Ardışık byte’ları okumak için, yukarıdaki kodlar bir döngü içine alınabilir: String str = ""; while (true) { try { int xxx = System.in.read (); if (xxx == -1) break; char c = (char) xxx; str = str + c; } catch (IOException e) {} } System.out.println ("Echo = " + str); System.in ile veri girişini daha etkin kılabilmek için, bunu InputStream sınıfı içine gömeriz, böylece o sınıfın daha güçlü metotlarını kullanabilme olanağı doğar. Alıştırmalar: 3 ByteArrayInputStream Sınıfı java.lang.Object java.io.InputStream java.io.ByteArrayInputStream Kılgıladığı Arayüzler: Closeable, AutoCloseable Bildirimi: public class ByteArrayInputStream extends InputStream Bir akımdan okunan byte’ların konulacağı bir buffer’a (verikabı) sahiptir. read() metodunun okuyacağı byte’ın sırasını belirleyen bir sayacı vardır. Bir ByteArrayInputStream akımını close() metodu ile kapatmanın etkisi yoktur; yani akım kapatılsa bile read() metodu hata atmadan çalışır. Örnek: import java.io.*; import java.io.ByteArrayInputStream; public class Demo { public static void main(String[] args) { String str = "Bu bir ByteArrayInputStream örneğidir."; // String sınıfının getBytes() metodu metinden byte okur byte[] byteArray = str.getBytes(); // ByteArrayInputStream nesnesi yarat ByteArrayInputStream bais = new ByteArrayInputStream(byteArray); int ch; // read() metodu ile ByteArrayInputStream akımından byte oku while ((ch = bais.read()) != -1) { System.out.print((char) ch); } } } Açıklamalar: 11. satırdaki byte[] 4 getBytes() metodu, String sınıfına aittir. str stringini byte dizisine dönüştürür (encoding). Bunu yaparken platformun öntanımlı charset’ini (alfabe) kullanır. Elde ettiği dizi ile byteArray adlı yeni bir byte array yaratmış olur. SequenceInputStream Sınıfı java.lang.Object java.io.InputStream java.io.SequenceInputStream Kılgıladığı Arayüzler: Closeable, AutoCloseable Bildirimi: public class SequenceInputStream extends InputStream Kurucuları: SequenceInputStream(Enumeration<? extends InputStream> e) Đkiden çok akımı uc uca ekleyip yeni bir SequenceInputStream akımı yaratır. Uc uca eklenen akımlar Enumeration tip olmalıdır. SequenceInputStream(InputStream s1, InputStream s2) Önce s1 akımını sonra s2 akımını okuyarak, ikisinden oluşan yeni bir SequenceInputStream akımı yaratır. Bir SequenceInputStream akımı başka akımların sırayla uc-uca eklenerek okunmasını sağlar. Önce ilk akımdan başlar, onun sonuna gelinince ikinci akımdan veri alır; o bitince üçüncü akımdan veri alır, böylece son akım bitene kadar süreç devam eder. Örnek: Bu örnek SequenceInputStream(InputStream s1, InputStream s2) kurucusunu kullanarak bir SequenceInputStream akımı yaratır. import java.io.*; public class Demo { public static void main(String args[]) throws Exception { String str1 = "Ankara"; String str2 = "Đstanbul"; byte[] b1 = str1.getBytes(); 5 byte[] b2 = str2.getBytes(); byte[] buf = new byte[50]; ByteArrayInputStream inputStream1 = new ByteArrayInputStream(b1); ByteArrayInputStream inputStream2 = new ByteArrayInputStream(b2); SequenceInputStream seqis = new SequenceInputStream(inputStream1, inputStream2); int okunanByte; while ((okunanByte = seqis.read(buf)) != -1) { System.out.print(new String(buf, 0, okunanByte)); } seqis.close(); } } /** AnkaraĐstanbul */ Örnek: Bu örnek SequenceInputStream(Enumeration<? extends InputStream> e) kurucusunu kullanarak bir SequenceInputStream akımı yaratır. import import import import import java.io.FileInputStream; java.io.InputStream; java.io.SequenceInputStream; java.util.Enumeration; java.util.Vector; public class Demo { public static void main(String[] args) throws Exception { FileInputStream fis1 = new FileInputStream("dosya1.txt"); FileInputStream fis2 = new FileInputStream("dosya2.txt"); FileInputStream fis3 = new FileInputStream("dosya3.txt"); Vector<InputStream> inputStreams = new Vector<InputStream>(); inputStreams.add(fis1); inputStreams.add(fis2); inputStreams.add(fis3); Enumeration<InputStream> enu = inputStreams.elements(); SequenceInputStream sis = new SequenceInputStream(enu); int birByte; while ((birByte = sis.read()) != -1) { System.out.write(birByte); } System.out.flush(); } } 6 Açıklamalar: Bu program, sırasıyla dosya1, dosya2 ve dosya3 ‘ü okumak için üç tane FileInputStream nesnesi yaratıyor. Sonra bunları bir vektor’e ekliyor. Vektörün öğelerini numaralıyor. Numaralanan öğeleri SequenceInputStream akımına akımına koyuyor. En sonunda, bunları bir döngü ile okuyup ekrana yazdırıyor. Örnek: Bu örnek SequenceInputStream(InputStream s1, InputStream s2) kurucusunu kullanarak bir SequenceInputStream akımı yaratır. import java.io.*; public class Demo { public static void main(String argv[]) { String str1 = "Kanun koymak, değiştirmek ve kaldırmak ile \n" + "Savaş ilânına karar vermek yasama erkinin önemli iki görevidir. \n"; String str2 = "Yargı yürütmeyi denetleyen ve vatandaşların yasal haklarını \n" + "kanun önünde koruması için çalışan erktir. \n"; byte[] buf = new byte[10]; System.out.println("TEST: Okuma"); try { ByteArrayInputStream is1 = new ByteArrayInputStream(str1.getBytes()); ByteArrayInputStream is2 = new ByteArrayInputStream(str2.getBytes()); SequenceInputStream sis = new SequenceInputStream(is1, is2); int okunanByte; while ((okunanByte = sis.read(buf)) != -1) { System.out.print(new String(buf, 0, okunanByte)); } sis.close(); System.out.println("BAŞARILI: Okuma"); } catch (IOException e) { System.out.println("BAŞARISIZ: Okuma: " + e); } } } /** TEST: Kanun Savaş Yargı 7 Okuma koymak, değiştirmek ve kaldırmak ile ilânına karar vermek yasama erkinin önemli iki görevidir. yürütmeyi denetleyen ve vatandaşların yasal haklarını kanun önünde koruması için çalışan erktir. BAŞARILI: Okuma */ StringBufferInputStream (Deprecated) Bu sınıf ve metotları Java 1.6 sürümünde iskartaya çıkarılmıştır (deprecated). Bunun yerine StringReader sınıfının kullanılması önerilmektedir. import java.io.*; public class Demo { public static void main(String[] args) throws Exception { StringBufferInputStream obj = new StringBufferInputStream("Ankara"); System.out.println("First character of the buffer : " + (char) obj.read()); System.out.println("Next character of the buffer : " + (char) obj.read()); System.out.println("Next character of the buffer : " + (char) obj.read()); obj.reset(); System.out .println("Üç karekter okunduktan sonra reset() yapılırsa, okunan karekter : " + (char) obj.read()); } } /** First character of the buffer : A Next character of the buffer : n Next character of the buffer : k Üç karekter okunduktan sonra reset() yapılırsa, okunan karekter : A */ PipedInputStream Sınıfı java.lang.Object java.io.InputStream java.io.PipedInputStream Kılgıladığı Arayüzler: 8 Closeable, AutoCloseable Bildirimi: public class PipedInputStream extends InputStream Bir thread ile buffer’a veri girişi başka bir thred ile buffer’dan veri çıkışı yapar. Bir su deposunun bir vanasından su girişi, başka bir vanasından sı çıkışı olmasına benzetilebilir. import java.io.*; public class Demo { public static void main(String args[]) throws Exception { byte[] b = {10, 20, 30, 40, 50}; PipedOutputStream poStream = new PipedOutputStream(); PipedInputStream piStream = new PipedInputStream(); //girişçıkışa bağlanıyor piStream.connect(poStream); //array'in bileşenleri yazdırılıyor poStream.write(b, 0, 5); //PipedInputStream akımı okunuyor ve ekrana yazdırılıyor for (int i = 0; i < b.length; i++) { System.out.println(piStream.read()); } // giriş akımı kapatılıyor poStream.close(); // çıkış akımı kapatılıyor piStream.close(); } } /** 10 20 30 40 50 */ FilterInputStream Sınıfı Ayrı bölümde ele alınmıştır. Đlgili bölüme bakınız. 9 FileInputStream Sınıfı Ayrı bölümde ele alınmıştır. Đlgili bölüme bakınız. AudioInputStream Sınıfı Ayrı bölümde ele alınmıştır. Đlgili bölüme bakınız. 10