Java NIO

目录

FileChannel

读取文件

写入文件

目录

FileChannel

读取文件

写入文件

SocketChannel

ServerSocketChannel和Selector


SocketChannel

ServerSocketChannel


FileChannel

读取文件

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class Main {
    public static void main(String[] args) throws IOException {
        // 获取文件,"r"为只读模式
        RandomAccessFile file = new RandomAccessFile("D:/data/data.txt", "r");
        // 获取文件通道
        FileChannel channel = file.getChannel();
        // 分配一个容量为1024的字节缓冲区
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        // 循环从通道中读取内容到字节缓冲区
        while (channel.read(byteBuffer) != -1) {
            // 将字节缓冲区的position置为0,limit置为position,也就是将缓冲区由读入模式切换为写出模式,以便后面的get()进行数据取出
            byteBuffer.flip();
            // 检查在当前的position->limit之间,是否存在剩余元素
            while (byteBuffer.hasRemaining())
                // 如果存在,取出
                System.out.print((char) byteBuffer.get());
            // 清空已读取的数据
            byteBuffer.compact();
        }
        channel.close();
        file.close();
    }
}

写入文件

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class Main {
    public static void main(String[] args) throws IOException {
        // 获取文件,"rw"为读写模式
        RandomAccessFile file = new RandomAccessFile("D:/data/data.txt", "rw");
        // 获取文件通道
        FileChannel channel = file.getChannel();
        // 分配一个容量为1024的字节缓冲区
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        // 循环从通道中读取内容到字节缓冲区
        byteBuffer.put("hello".getBytes());
        //将字节缓冲区的position置为0,limit置为position,也就是将缓冲区由读入模式切换为写出模式。
        byteBuffer.flip();
        // 写出
        channel.write(byteBuffer);
        channel.close();
        file.close();
    }
}

SocketChannel

对于SocketChannel的数据读写,方式与FileChannel文件数据读写一样,区别在于获取通道的方式:

        SocketAddress address = new InetSocketAddress("vm01", 9999);
        SocketChannel channel = SocketChannel.open(address);

ServerSocketChannel和Selector

可使用选择器(Selector),对ServerSocketChannel进行注册,以下代码模拟了客户端和服务端,客户端输入字符串,服务端会接到请求并打印到console,先启动server。

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Set;

public class Server {

    public static void main(String[] args) {
        Server server = new Server();
        try {
            server.run();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private ServerSocketChannel channel;
    private Selector selector;
    private int capacity;

    public void run() throws IOException {
        init();
        while (true) {
            selector.select();
            Set<SelectionKey> keySet = selector.selectedKeys();
            Iterator<SelectionKey> iterator = keySet.iterator();
            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                iterator.remove();
                // 监听链接事件
                if (selectionKey.isAcceptable()) {
                    handleAcceptable(selector, channel);
                } else if (selectionKey.isReadable()) {
                    handleReadable(selectionKey);
                }
            }
        }
    }

    /**
     * 初始化ServerSocketChannel和selector,并注册
     *
     * @throws IOException
     */
    private void init() throws IOException {
        // 获取通道
        channel = ServerSocketChannel.open();
        SocketAddress address = new InetSocketAddress("127.0.0.1", 8888);
        // 绑定通道地址
        channel.bind(address);
        // 设置通道为非阻塞
        channel.configureBlocking(false);
        // 打开选择器
        selector = Selector.open();
        // 通道注册
        channel.register(selector, SelectionKey.OP_ACCEPT);
    }

    /**
     * 处理链接事件
     *
     * @param selector 选择器
     * @param channel  通道
     * @throws IOException
     */
    private void handleAcceptable(Selector selector, ServerSocketChannel channel) throws IOException {
        SocketChannel socketChannel = channel.accept();
        socketChannel.configureBlocking(false);
        // 注册可读事件
        socketChannel.register(selector, SelectionKey.OP_READ);

    }

    /**
     * 处理可读事件
     *
     * @param selectionKey 选择键
     * @throws IOException
     */
    private void handleReadable(SelectionKey selectionKey) throws IOException {
        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
        ByteBuffer readBuffer = ByteBuffer.allocate(capacity);
        StringBuilder builder = new StringBuilder();
        while (socketChannel.read(readBuffer) > 0) {
            readBuffer.flip();
            builder.append(StandardCharsets.UTF_8.decode(readBuffer));
        }
        if (builder.length() > 0) {
            System.out.println(builder);
        }
        // 继续注册可读事件
//        socketChannel.register(selector, SelectionKey.OP_READ);
    }

}
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;


public class Client {

    public static void main(String[] args) throws IOException, InterruptedException {
        SocketAddress address = new InetSocketAddress("127.0.0.1", 8888);
        SocketChannel channel = SocketChannel.open(address);
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine();
            if (!"".equals(line) && line != null) {
                Thread.sleep(2000);
                channel.write(StandardCharsets.UTF_8.encode(line));
            }
        }
        channel.close();
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柏舟飞流

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值