NIO簡單應用

NIO簡單應用

使用FileChannel完成文件複製

public class FileNIOCopyDemo {
    public static void main(String[] args) {
        nioCopyResourceFile();
    }

    /**
     * 複製兩個資源目錄下的文件
     */
    private static void nioCopyResourceFile() {
        String sourcePath = NioDemoConfig.sourcePath;
        String destPath = NioDemoConfig.destPath;
        nioCopyFile(sourcePath, destPath);
    }

    private static void nioCopyFile(String sourcePath, String destPath) {
        File srcFile = new File(sourcePath);
        File destFile = new File(destPath);
        try {
            if (!destFile.exists()) {
                destFile.createNewFile();
            }
            long startTime = System.currentTimeMillis();
            FileInputStream fis = null;
            FileOutputStream  fos = null;
            FileChannel inChannel = null;
            FileChannel outChannel = null;

            try {
                fis = new FileInputStream(srcFile);
                fos = new FileOutputStream(destFile);
                inChannel = fis.getChannel();
                outChannel = fos.getChannel();

                ByteBuffer buffer = ByteBuffer.allocate(1024);
                int length = 0;
                int outlength = 0;
                //從讀通道讀取數據到buffer
                while ((length = inChannel.read(buffer)) != -1) {
                    //切換buffer至讀模式
                    buffer.flip();
                    //將buffer內容寫入輸出channel
                    while ((outlength = outChannel.write(buffer)) != 0) {
                        System.out.println("寫入的字節數: " + outlength);
                    }
                    //切換buffer爲寫模式
                    buffer.clear();
                }
                //強制刷新到磁盤
                outChannel.force(true);
            } finally {
                closeUtil(outChannel);
                closeUtil(inChannel);
                closeUtil(fos);
                closeUtil(fis);
                Long endTime = System.currentTimeMillis();
                System.out.println("複製花費毫秒數: " + (endTime - startTime));
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void closeUtil(Closeable item) {
        if (item != null) {
            try {
                item.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }


}

使用SocketChannel發送文件

客戶端發送

public class NioSendClient {
    private Charset charset = Charset.forName("UTF-8");

    public static void main(String[] args) {
        NioSendClient client = new NioSendClient();//啓動客戶端連接
        client.sendFile();//傳輸文件

    }

    /**
     * 向服務器傳輸文件
     */
    private void sendFile() {
        try {
            //獲取源文件、目的文件路徑
            String srcPath = NioDemoConfig.sourcePath;
            String destPath = NioDemoConfig.destPath;
            //獲取源文件File對象
            File srcFile = new File(srcPath);
            if (!srcFile.exists()) {
                System.out.println("文件不存在");
                return;
            }
            //獲取源文件流
            FileInputStream fileInputStream = new FileInputStream(srcFile);
            //獲取源文件通道
            FileChannel fileChannel = fileInputStream.getChannel();
            //獲取Socket通道
            SocketChannel socketChannel = SocketChannel.open();
            //連接服務端
            socketChannel.connect(new InetSocketAddress(NioDemoConfig.SOCKET_SERVER_IP, NioDemoConfig.SOCKET_SERVER_PORT));
            //設置channel爲非阻塞
            socketChannel.configureBlocking(false);
            //自旋,等待連接完成
            while (!socketChannel.finishConnect()) {
                //不斷自旋、等待,或者做一些其他操作
            }
            System.out.println("Client成功連接服務器端");

            //發送文件名稱
            ByteBuffer fileNameByteBuffer = charset.encode(destPath);
            socketChannel.write(fileNameByteBuffer);

            //發送文件長度
            ByteBuffer buffer = ByteBuffer.allocate(NioDemoConfig.SEND_BUFFER_SIZE);
            buffer.putLong(srcFile.length());
            buffer.flip();
            socketChannel.write(buffer);
            buffer.clear();
            //發送文件內容
            System.out.println("開始傳輸文件");
            int length = 0;
            long progress = 0;
            while ((length = fileChannel.read(buffer)) > 0) {
                buffer.flip();
                socketChannel.write(buffer);
                buffer.clear();
                progress += length;
                System.out.println("| " + (100 * progress / srcFile.length()) + "% |");
            }

            //判斷文件傳輸結束,發送結束符至對端
            if (length == -1) {
                closeUtil(fileChannel);
                //在SocketChannel傳輸通道關閉前,儘量發送一個輸出結果標誌到對端
                socketChannel.shutdownOutput();
                closeUtil(socketChannel);
            }
            System.out.println("====== 文件傳輸成功 =======");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void closeUtil(Closeable item) {
        if (item != null) {
            try {
                item.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

使用DatagramChannel數據報通道發送數據

客戶端

public class UDPClient {
    public static void main(String[] args) throws IOException {
        new UDPClient().send();
    }

    public void send() throws IOException {
        //獲取DatagramChannel數據報通道
        DatagramChannel channel = DatagramChannel.open();
        //設置爲非阻塞
        channel.configureBlocking(false);
        //創建ByteBuffer
        ByteBuffer buffer = ByteBuffer.allocate(NioDemoConfig.SEND_BUFFER_SIZE);
        //掃描輸入
        Scanner scanner = new Scanner(System.in);
        //遍歷掃描到的內容,發送數據
        while (scanner.hasNext()) {
            String next = scanner.next();
            buffer.put(next.getBytes());
            channel.send(buffer, new InetSocketAddress(NioDemoConfig.SOCKET_SERVER_IP, NioDemoConfig.SOCKET_SERVER_PORT));
            buffer.clear();
        }
        //關閉數據報通道
        channel.close();

    }
}

服務端

public class UDPServer {
    public static void main(String[] args) throws IOException {
        new UDPServer().receive();
    }

    public void receive() throws IOException {
        //獲取數據報通道
        DatagramChannel channel = DatagramChannel.open();
        //設置爲非阻塞
        channel.configureBlocking(false);
        //綁定監聽地址
        channel.socket().bind(new InetSocketAddress(NioDemoConfig.SOCKET_SERVER_IP, NioDemoConfig.SOCKET_SERVER_PORT));
        //開啓一個通道選擇器
        Selector selector = Selector.open();
        //將通道註冊到選擇器
        channel.register(selector, SelectionKey.OP_READ);
        //通過選擇器,查詢IO事件
        while (selector.select() > 0) {
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            ByteBuffer buffer = ByteBuffer.allocate(NioDemoConfig.SEND_BUFFER_SIZE);

            //迭代IO事件
            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                //可讀事件,有事件到來
                if (selectionKey.isReadable()) {
                    //讀取數據報通道的數據
                    SocketAddress client = channel.receive(buffer);
                    buffer.flip();
                    System.out.println(new String(buffer.array(), 0, buffer.limit()));
                    buffer.clear();
                }
            }
            iterator.remove();
        }

    }
}

參考資料:《Netty、Redis、Zookeeper高併發實戰》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章