13- Java IO ve NIO

### Java'da I/O ve NIO Kullanımı


Java'da I/O (Input/Output) işlemleri, veri okuma ve yazma işlemlerini gerçekleştirmek için kullanılır. Java'da I/O işlemleri genellikle iki ana paket üzerinden gerçekleştirilir: `java.io` ve `java.nio`. Aşağıda bu paketlerin kullanımı ve socket programlama ile ilgili detaylar bulunmaktadır.


---


### IO Sınıfları Kullanımı


Java'nın `java.io` paketi, dosya ve veri akışları ile çalışmak için gerekli sınıfları sağlar. Bu paket, iki ana kategoriye ayrılır: byte tabanlı ve karakter tabanlı I/O.


#### Byte Tabanlı I/O


1. **InputStream ve OutputStream Sınıfları**


- **`InputStream`**: Byte verilerini okur.

- **`OutputStream`**: Byte verilerini yazar.


##### `FileInputStream` ve `FileOutputStream` Kullanımı


```java

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;


public class ByteIOExample {

    public static void main(String[] args) {

        String inputFile = "input.txt";

        String outputFile = "output.txt";


        try (FileInputStream fis = new FileInputStream(inputFile);

             FileOutputStream fos = new FileOutputStream(outputFile)) {


            int byteData;

            while ((byteData = fis.read()) != -1) {

                fos.write(byteData);

            }

            System.out.println("Veri başarıyla kopyalandı!");

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}

```


- **`FileInputStream`**: Dosyadan byte okur.

- **`FileOutputStream`**: Dosyaya byte yazar.

- **`read()`**: Bir byte okur.

- **`write(byte)`**: Bir byte yazar.


#### Karakter Tabanlı I/O


1. **Reader ve Writer Sınıfları**


- **`Reader`**: Karakter verilerini okur.

- **`Writer`**: Karakter verilerini yazar.


##### `FileReader` ve `FileWriter` Kullanımı


```java

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;


public class CharIOExample {

    public static void main(String[] args) {

        String inputFile = "input.txt";

        String outputFile = "output.txt";


        try (FileReader fr = new FileReader(inputFile);

             FileWriter fw = new FileWriter(outputFile)) {


            int charData;

            while ((charData = fr.read()) != -1) {

                fw.write(charData);

            }

            System.out.println("Karakter verisi başarıyla kopyalandı!");

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}

```


- **`FileReader`**: Dosyadan karakter okur.

- **`FileWriter`**: Dosyaya karakter yazar.

- **`read()`**: Bir karakter okur.

- **`write(int)`**: Bir karakter yazar.


---


### NIO (New I/O) ve Non-Blocking I/O


Java NIO (New I/O), daha etkili ve performanslı I/O işlemleri için geliştirilmiş bir API'dir. NIO, daha düşük seviye I/O işlemlerini destekler ve non-blocking (engellemeyen) I/O işlemleri sağlar.


#### NIO Temel Sınıfları


1. **`FileChannel`**: Dosyalarla veri okuma ve yazma işlemleri sağlar.

2. **`ByteBuffer`**: Byte verilerini tamponda tutar.

3. **`Selectors`**: Non-blocking I/O işlemleri için seçici mekanizma sağlar.

4. **`SocketChannel`** ve **`ServerSocketChannel`**: Socket bağlantıları ile veri iletimi sağlar.


##### `FileChannel` Kullanımı


```java

import java.io.RandomAccessFile;

import java.nio.ByteBuffer;

import java.nio.channels.FileChannel;

import java.io.IOException;


public class FileChannelExample {

    public static void main(String[] args) {

        String inputFile = "input.txt";

        String outputFile = "output.txt";


        try (RandomAccessFile input = new RandomAccessFile(inputFile, "r");

             RandomAccessFile output = new RandomAccessFile(outputFile, "rw")) {


            FileChannel inChannel = input.getChannel();

            FileChannel outChannel = output.getChannel();


            ByteBuffer buffer = ByteBuffer.allocate(1024);

            int bytesRead;

            while ((bytesRead = inChannel.read(buffer)) != -1) {

                buffer.flip();

                outChannel.write(buffer);

                buffer.clear();

            }

            System.out.println("Veri başarıyla kopyalandı!");

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}

```


- **`FileChannel`**: Dosya ile veri okuma/yazma sağlar.

- **`ByteBuffer`**: Verileri tamponda tutar.

- **`flip()`**: Buffer'ı okuma moduna alır.

- **`clear()`**: Buffer'ı temizler.


#### Non-Blocking I/O (Non-Blocking I/O ve Selectors)


Non-blocking I/O işlemleri, thread'lerin I/O işlemleri sırasında bloklanmadan diğer işlemleri yapmasına olanak tanır.


##### `Selector` Kullanımı


```java

import java.io.IOException;

import java.nio.channels.*;

import java.net.InetSocketAddress;

import java.nio.ByteBuffer;


public class NonBlockingExample {

    public static void main(String[] args) {

        try (Selector selector = Selector.open();

             ServerSocketChannel serverSocketChannel = ServerSocketChannel.open()) {


            serverSocketChannel.bind(new InetSocketAddress(8080));

            serverSocketChannel.configureBlocking(false);

            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);


            while (true) {

                selector.select();

                for (SelectionKey key : selector.selectedKeys()) {

                    if (key.isAcceptable()) {

                        SocketChannel clientChannel = serverSocketChannel.accept();

                        clientChannel.configureBlocking(false);

                        clientChannel.register(selector, SelectionKey.OP_READ);

                    } else if (key.isReadable()) {

                        SocketChannel clientChannel = (SocketChannel) key.channel();

                        ByteBuffer buffer = ByteBuffer.allocate(256);

                        clientChannel.read(buffer);

                        buffer.flip();

                        System.out.println("Received: " + new String(buffer.array()).trim());

                    }

                }

                selector.selectedKeys().clear();

            }

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}

```


- **`Selector`**: Non-blocking I/O işlemleri için seçici.

- **`SelectionKey`**: Bir kanalın belirli I/O olaylarını temsil eder.

- **`select()`**: İlgili kanallarda olay olup olmadığını kontrol eder.

- **`register()`**: Kanalı seçiciye kaydeder.


---


### Socket Programlama


Java'da socket programlama, ağ üzerindeki iki uygulama arasında veri alışverişi sağlar. `java.net` paketi, socket programlama için gerekli sınıfları içerir.


#### Basit Bir TCP Socket Server ve Client


##### Server


```java

import java.io.IOException;

import java.io.PrintWriter;

import java.net.ServerSocket;

import java.net.Socket;


public class SocketServer {

    public static void main(String[] args) {

        try (ServerSocket serverSocket = new ServerSocket(12345)) {

            System.out.println("Server başlatıldı, bağlantı bekleniyor...");

            Socket clientSocket = serverSocket.accept();

            System.out.println("Client bağlı!");


            try (PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true)) {

                out.println("Merhaba, client!");

            }

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}

```


##### Client


```java

import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.io.IOException;

import java.net.Socket;


public class SocketClient {

    public static void main(String[] args) {

        try (Socket socket = new Socket("localhost", 12345);

             BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {


            String message = in.readLine();

            System.out.println("Server'dan gelen mesaj: " + message);

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}

```


- **`ServerSocket`**: Server tarafında socket oluşturur ve bağlantı kabul eder.

- **`Socket`**: Client tarafında socket oluşturur ve server ile bağlantı kurar.

- **`PrintWriter`**: Socket üzerinden veri gönderir.

- **`BufferedReader`**: Socket üzerinden veri okur.


---


### Özet


Bu ders notları, Java'da I/O ve NIO kullanımı, senkronizasyon, ve socket programlama konularını kapsamaktadır. `java.io` paketi, temel I/O işlemlerini sağlar, `java.nio` paketi ise daha performanslı ve non-blocking I/O işlemleri sunar. Socket programlama, ağ üzerinden veri alışverişi için kullanılır. Bu bilgilerle, Java'da çeşitli I/O ve ağ işlemlerini gerçekleştirebilirsiniz.