java NIO编程(一)

文章参考摘抄自:https://ifeve.com/java-nio-all/

一、java NIO特性:

Channels and Buffers

Channel主要的实现:

  • FileChannel    从文件中读写数据
  • DatagramChannel    通过UDP读写网络中的数据
  • SocketChannel      通过TCP读写网络中的数据
  • ServerSocketChannel  监听新进来的TCP连接,对每一个新进来的连接都会创建一个SocketChannel。

Buffer实现:

  • ByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

  MappedByteBuffer,用于表示内存映射文件

标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。

Non-blocking IO

可以采用多线程从通道读取数据并处理。

Selectors

可以监听多个通道的事件,如连接打开,同时单线程也可监听多个数据通道。要使用Selector,得向Selector注册Channel,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新连接进来,数据接收等。

还有Pipe和FileLock

        基本上,所有的 IO 在NIO 中都从一个Channel 开始。Channel 有点象流。 数据可以从Channel读到Buffer中,也可以从Buffer 写到Channel中。

 

二、文件读写案例:

 

a、通过使用一个InputStream、OutputStream或RandomAccessFile来获取一个FileChannel实例

b、从FileChannel中读取数据至Buffer中;返回的int值表示了有多少字节被读到了Buffer中。如果返回-1,表示到了文件末尾。

c、用完FileChannel后必须将其关闭。

public static  void chanelTest() {
        RandomAccessFile aFile = null;
        try {
            aFile = new RandomAccessFile("D:\\笔记\\dblink.txt", "rw");
            FileChannel inChannel = aFile.getChannel();

            ByteBuffer buf = ByteBuffer.allocate(48);

            int bytesRead = inChannel.read(buf);
            while (bytesRead != -1) {

            System.out.println("Read " + bytesRead);
            buf.flip();

            while(buf.hasRemaining()){
            System.out.print((char) buf.get());

          // channel.write(buf);  //文件写入
            }

            buf.clear();
            bytesRead = inChannel.read(buf);
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            try {
                aFile.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

 

三、特殊用法

FileChannel的position方法

    在FileChannel的某个特定位置进行数据的读/写操作。也可以通过调用position(long pos)方法设置FileChannel的当前位置。

long pos = channel.position();

channel.position(pos +123);

FileChannel的size方法

返回该实例所关联文件的大小。

long fileSize = channel.size();

FileChannel的truncate方法

截取文件 指定长度并删除其余部分。channel.truncate(1024);

FileChannel的force方法

将通道里尚未写入磁盘的数据强制写到磁盘上。

transferFrom()

FileChannel的transferFrom()方法可以将数据从源通道传输到FileChannel中;position表示从position处开始向目标文件写入数据,count表示最多传输的字节数,如果源通道的剩余空间小于 count 个字节,则所传输的字节数要小于请求的字节数。在SoketChannel的实现中,SocketChannel只会传输此刻准备好的数据(可能不足count字节)。因此,SocketChannel可能不会将请求的所有数据(count个字节)全部传输到FileChannel中。

如:

    RandomAccessFile fromFile = new RandomAccessFile("fromFile.txt", "rw");
    FileChannel      fromChannel = fromFile.getChannel();
    RandomAccessFile toFile = new RandomAccessFile("toFile.txt", "rw");
    FileChannel      toChannel = toFile.getChannel();
    long position = 0;
    long count = fromChannel.size();

transferTo()

将数据从FileChannel传输到其他的channel中。

RandomAccessFile fromFile = new RandomAccessFile("fromFile.txt", "rw");
FileChannel      fromChannel = fromFile.getChannel();

RandomAccessFile toFile = new RandomAccessFile("toFile.txt", "rw");
FileChannel      toChannel = toFile.getChannel();
long position = 0;
long count = fromChannel.size();
fromChannel.transferTo(position, count, toChannel);

 

 

附中文乱码处理:

文件读取到后,写入时做编码处理:

  1. Charset charset = Charset.forName("GBK");

  2. CharsetDecoder charDecoder = charset.newDecoder();

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个使用 Java NIO(New I/O)进行网络编程的简单示例: ```java import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class NIOExample { public static void main(String[] args) throws IOException { // 创建一个线程池用于处理客户端连接 ExecutorService executor = Executors.newFixedThreadPool(10); // 创建 ServerSocketChannel 并绑定端口 ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.bind(new InetSocketAddress("localhost", 8080)); System.out.println("Server started on port 8080"); while (true) { // 接受客户端连接 SocketChannel socketChannel = serverSocketChannel.accept(); // 使用线程池处理客户端连接 executor.execute(() -> handleClient(socketChannel)); } } private static void handleClient(SocketChannel socketChannel) { try { ByteBuffer buffer = ByteBuffer.allocate(1024); // 读取客户端发送的数据 int bytesRead = socketChannel.read(buffer); while (bytesRead != -1) { buffer.flip(); while (buffer.hasRemaining()) { System.out.print((char) buffer.get()); } buffer.clear(); bytesRead = socketChannel.read(buffer); } // 响应客户端 String response = "Hello from server"; ByteBuffer responseBuffer = ByteBuffer.wrap(response.getBytes()); socketChannel.write(responseBuffer); // 关闭连接 socketChannel.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` 这个示例创建了一个简单的服务器,监听本地的 8080 端口。当客户端连接时,会使用线程池处理连接,并读取客户端发送的数据。然后,服务器会向客户端发送 "Hello from server" 的响应,并关闭连接。 请注意,这只是一个简单的示例,实际的网络编程可能涉及更复杂的逻辑和处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值