# Reader & Writer ## Reader Karakter akıÅlarından gelen verileri okumak için yazılmıŠsoyut bir sınıftır. Okuma iÅlemleri için gerekli bazı metotları tanımlamıÅtır. Bu metotlardan bazılarını inceleyelim: | **void** close() | AkıÅı kapatır. Bütün akıŠkaynakları iÅlem tamamlandıktan sonra kapatılmalıdır! | | -------------------------------- | ------------------------------------------------------------ | | **int** read() | AkıÅta bulunan sıradaki karakteri okur. EÄer dosyanın sonuna gelindiyse -1 döndürür. | | **int** read(**char**[ ] buffer) | Parametre olarak verilen dizinin boyutu kadar karakteri okur ve dizinin içine atar. Bu dizinin türünün **_InputStream_** sınıfındakinden farklı olarak **char** olduÄuna dikkatinizi çekerim. | | **boolean** ready() | AkıÅın okunmaya hazır olup olmadıÄını denetler. | | **long** skip(**int** n) | Parametre olarak verilen sayı kadar karakteri okumadan atlar. | ## Writer Karakter akıÅlarına veri yazmak için kullanılan soyut bir sınıftır. Yazma iÅlemleri için gerekli bazı metotları tanımlamıÅtır. Bu metotlardan bazılarını inceleyelim: | **void** close() | AkıÅı kapatır. **Bütün akıŠkaynakları iÅlem tamamlandıktan sonra kapatılmalıdır!** | | ---------------------------------- | ------------------------------------------------------------ | | **void** flush() | EÄer fiziksel olarak akıÅa yazılmamıŠkarakterler varsa, bunların yazılması için bir sinyal gönderir. | | **void** write(**int** c) | AkıÅa bir karakter yazar. Bu deÄeri parametre olarak alır. | | **void** write(**char**[ ] buffer) | Parametre olarak aldıÄı karakter dizisinin içindeki bütün karakterleri sırasıyla akıÅa yazar. Bu dizinin türünün OutputStream sınıfındakinden farklı olarak **char** olduÄuna dikkatinizi çekerim. | | **void** write(**String** s) | Parametre olarak aldıÄı metni akıÅa yazar. | | **Writer** append(**char** c) | Parametre olarak aldıÄı karakteri akıÅın sonuna ekler, daha sonra kendini döndürür. Zincirleme metotlar yazabilmek amacıyla eklenmiÅtir. | ## FileReader Metin dosyalarının içeriÄini okumak için bu sınıfı kullanırız. Sınıfın bir örneÄini alırken parametre olarak okuyacaÄımız dosyanın yolunu **_String_** veya **_File_** olarak veririz. EÄer okumak istediÄimiz dosya mevcut deÄilse **_FileNotFoundException_** fırlatılır. Åimdi **_FileInputStream_** baÅlıÄında yaptıÄımız örneÄi **_FileReader_** kullanarak tekrar yapalım: ```java File inputFile = new File("ornek_dosya.txt"); try { FileReader fileReader = new FileReader(inputFile); int c; while ((c = fileReader.read()) != -1) { System.out.print((char) c); } fileReader.close(); } catch (IOException ex) { System.out.println("Dosyayı okurken hata meydana geldi!"); } ``` Bu örnekte **_FileInputStream_** yerine **_FileReader_** kullandık. Ayrıca read() metoduyla okuduÄumuz int türündeki karakteri **char** türüne dönüÅtürdüÄümüze dikkat edin. ## FileWriter Metin dosyalarının içeriÄine yazmak için bu sınıfı kullanırız. Sınıfın bir örneÄini alırken parametre olarak okuyacaÄımız dosyanın yolunu **_String_** veya **_File_** olarak veririz. Ayrıca ikinci parametre olarak **boolean** türünde **_append_** isminde bir argüman veririz. Bu argüman dosyaya ekleme yapılıp yapılmayacaÄını tespit etmek için kullanılır. EÄer **true** verirsek ve yazmak istediÄimiz dosya mevcutsa; dosyanın içeriÄi korunur ve sonuna ekleme yapılır. EÄer **false** verirsek ve yazmak istediÄimiz dosya mevcutsa; dosyanın mevcut içeriÄi silinir ve üzerine yazılır. EÄer biz bu parametreyi vermezsek varsayılan deÄer olarak **false** kullanılır. ## CharArrayReader ve CharArrayWriter sınıfları Bir karakter dizisini tıpkı bir akıŠgibi okumak için **_CharArrayReader_** sınıfını kullanırız. Bir karakter dizisine tıpkı bir akıŠgibi yazmak için ise **_CharArrayWriter_** sınıfını kullanırız. ## InputStreamReader **_InputStream_** türündeki bir akıŠkaynaÄını **_Reader_** türüne dönüÅtürmek için bu sınıf kullanılır. EÄer parametre olarak aldıÄınız **_InputStream_** türündeki bir akıŠkaynaÄının karakter akıÅı olduÄunu biliyor ve **_Reader_** sınıfının iÅlevselliÄinden faydalanmak istiyorsanız bu sınıfı kullanmalısınız: ```java try { InputStream inputStream = new FileInputStream("ornek_dosya.txt"); Reader reader = new InputStreamReader(inputStream); } catch (IOException ex) { System.out.println("Bir hata meydana geldi!"); } ``` ## OutputStreamWriter **_OutputStream_** türündeki bir akıŠkaynaÄını **_Writer_** türüne dönüÅtürmek için bu sınıf kullanılır. EÄer parametre olarak aldıÄınız **_OutputStream_** türündeki bir akıŠkaynaÄının karakter akıÅı olduÄunu biliyor ve **_Writer_** sınıfının iÅlevselliÄinden faydalanmak istiyorsanız bu sınıfı kullanmalısınız: ```java try { OutputStream outputStream = new FileOutputStream("ornek_dosya.txt"); Writer writer = new OutputStreamWriter(outputStream); } catch (IOException ex) { System.out.println("Bir hata meydana geldi!"); } ``` ## BufferedReader ve BufferedWriter sınıfları **_BufferedInputStream_** ve **_BufferedOutputStream_** sınıflarının karakter akıÅları için kullanılan karÅılıklarıdır. Dosyaya yazma ve okuma iÅlemleri zaman açısından maliyetlidir. Neden Maliyetelidir; - Uygulamanın daha yavaÅ bir donanımla muhatap oluyor olması, - Her I/O iÅleminde byte dönüÅtürme iÅlemi yapıyor olması. - Dosya üzerinde yapılacak her iÅlemin bir sonraki iÅlemi beklemek zorunda olması Bunu yavaÅlıÄa çözem olarak Bellekte tampon bölge oluÅturup I/O iÅlemlerinin orada yönetilmesinde bulunmuÅ. Buffer sayesinde bir dosyadan okuma yaparken aynı anda veri yollayabilirsiniz. #### BufferedReader BufferedReader ile dosyayı `read()` metodu ile karakter karakter okuyabiliriz: ```java try { String fileName = "ornek_dosya.txt"; FileReader reader = new FileReader(fileName); BufferedReader bufferedReader = new BufferedReader(reader); int c; while ((c = bufferedReader.read()) != -1) { System.out.println("Char: " + (char) c); } bufferedReader.close(); } catch (IOException ex) { System.out.println("Bir hata meydana geldi!"); } ``` BufferedReader InputStreamReader'a kıyasla epey hızlı çalıÅır. Bunu buffer kullanarak baÅarır. `BufferedReader`ın bir baÅka avantajı , metin dosyasını yalnızca karakter karakter deÄil, satır satır da okumanıza ve iÅlemenize olanak tanıyan ek bir yöntem olarak `readLine()` metodunu sunmasıdır: ```java try { String fileName = "ornek_dosya.txt"; FileReader reader = new FileReader(fileName); BufferedReader bufferedReader = new BufferedReader(reader); String line; while ((line = bufferedReader.readLine()) != null) { System.out.println("Line: " + line); } bufferedReader.close(); } catch (IOException ex) { System.out.println("Bir hata meydana geldi!"); } ``` Java'da dosya okumak için kullanılan yöntemlerinin, okuma süresi üzerinde nasıl etkili olduÄunu görmek için 100 milyon baytlık bir dosya kullanılarak süreleri karÅılaÅtırılmıÅ.  **Buffer kullanmayan** ve **Buffer kullanan** yöntemler arasındaki büyük fark, **Buffer kullanan **yöntemlerin yukarıdaki Åemada kendi aralarındaki farkın görünmesini zorlaÅtırıyor. Bu nedenle, aÅaÄıda **Buffer kullanan** yöntemleri gösteren ikinci bir diyagramla yakından bakalım:  Biraz karıÅık gelmiÅ olabilir, buraya kadar bir çok sınıf ve metod kullandık. Bu sınıfların iliÅkilerini görsel olarak görmek size biraz yardımcı olacaktır.  Düz çizgiler, binary verilerin akıÅını temsil eder; kesikli çizgiler, metin verilerinin, yani karakterlerin akıÅını gösterir. #### BufferedWriter `BufferedWriter` 'a bir FileWriter verdikten sonra artık yapmamız gereken sadece dosyaya yazmak istediÄimiz veriyi write metoduna vermek. ```java try { String fileName = "ornek_dosya.txt"; FileWriter writer = new FileWriter(fileName); BufferedWriter bufferedWriter = new BufferedWriter(writer); String kodluyoruz="ÃÄrenmek için kodluyoruz"; bufferedWriter.write(kodluyoruz); bufferedWriter.close(); } catch (IOException ex) { System.out.println("Bir hata meydana geldi!"); } ``` Java'da dosyaya veri yazmak için kullanılan yöntemlerinin, yazma süresi üzerinde nasıl etkili olduÄunu görmek için 100 milyon baytlık bir dosya kullanılarak süreleri karÅılaÅtırılmıÅ:  **Buffer kullanmayan** ve **Buffer kullanan** yöntemler arasındaki büyük fark okumada olduÄu gibi burda da açıkça görünüyor. **Buffer kullanan** yöntemlerin kendi aralarındaki farkı da aÅaÄıdaki görselde görebiliyoruz:  Okuma yapmak için kullanılan sınıfların kendi aralarındaki iliÅkiyi görmek iÅinizi kolaylaÅtıracaktır:  [İlk üç görselin kaynaÄı](https://www.happycoders.eu/java/how-to-read-files-easily-and-fast/) [son üç görselin görselin kaynaÄı](https://www.happycoders.eu/java/how-to-write-files-quickly-and-easily/)