网络编程NIO:BIO和NIO详解,看不懂你打我( 二 )

  • CharBuffer:存储字符数据到缓冲区
  • IntBuffer:存储整型数据到缓冲区
  • ShortBuffer:存储短整型数据到缓冲区
  • LongBuffer:存储长整型数据到缓冲区
  • FloatBuffer:存储浮点型数据到缓冲区
  • DoubleBuffer:存储双精度浮点型数据到缓冲区
  • ByteBuffer
    在Buffer的所有子类中 , 最常用的还是ByteBuffer , 它的常用方法:
    网络编程NIO:BIO和NIO详解,看不懂你打我文章插图
    通道(Channel)在NIO程序中服务器端和客户端之间的数据读写不是通过流 , 而是通过通道来读写的 。
    通道类似于流 , 都是用来读写数据的 , 但它们之间也是有区别的:
    • 通道是双向的 , 即可以读也可以写 , 而流是单向的 , 只能读或写
    • 通道可以实现异步读写数据
    • 通道可以从缓冲区读数据 , 也可以把数据写入缓冲区
    java中channel的相关类在java.nio.channel包下 。 Channel是一个接口 , 其常用的实现类有:
    • FileChannel:用于文件的数据读写 , 其真正的实现类为FileChannelImpl
    • DatagramChannel:用于UDP的数据读写 , 其真正的实现类为DatagramChannelImpl
    • ServerSocketChannel:用于监听TCP连接 , 每当有客户端连接时都会创建一个SocketChannel , 功能类似ServerSocket , 其真正的实现类为ServerSocketChannelImpl
    • SocketChannel:用于TCP的数据读写 , 功能类似节点流+Socket , 其真正的实现类为SocketChannelImpl
    FileChannelFileChannel主要用于对本地文件进行IO操作 , 如文件复制等 。 它的常用方法有:
    网络编程NIO:BIO和NIO详解,看不懂你打我文章插图
    在文件传输流中有个属性channel , 它默认是空的 , 可以通过流中的getChanel()方法根据当前文件流的属性生成对应的FileChannel 。
    public FileChannel getChannel() {synchronized (this) {if (channel == null) {channel = FileChannelImpl.open(fd, path, false, true, append, this);}return channel;}}}下面是通道使用的代码实例:
    public class NIOChannel {public static void main(String[] args) throws IOException {}//将数据写入目标文件public static void writeFile() throws IOException{String str = "Hello, gofy";//创建文件输出流FileOutputStream fileOutputStream = new FileOutputStream("f:\\file.txt");//根据文件输出流生成文件通道FileChannel fileChannel = fileOutputStream.getChannel();//创建字节缓冲区 , 并将字符串转成字节存入ByteBuffer byteBuffer = ByteBuffer.allocate(1024);byteBuffer.put(str.getBytes());//注意 , 在存入后需要进行写出操作时 , 需将缓冲区翻转byteBuffer.flip();//将缓冲区数据写入通道fileChannel.write(byteBuffer);//将文件输出流关闭(该方法同时会关闭通道)fileOutputStream.close();}//从文件中读取数据public static void readFile() throws IOException{//创建文件输入流File file = new File("f:\\file.txt");FileInputStream fileInputStream = new FileInputStream(file);//根据文件输入流生成文件通道FileChannel fileChannel = fileInputStream.getChannel();//创建字节缓冲区 , 大小为文件大小ByteBuffer byteBuffer = ByteBuffer.allocate((int)file.length());//将通道数据读入缓冲区fileChannel.read(byteBuffer);//同样 , 在读入后需要取出缓冲区内所有数据时 , 需将缓冲区翻转byteBuffer.flip();System.out.println(new String(byteBuffer.array()));fileInputStream.close();}//将文件数据传输到另一个文件public static void readAndWriteFile() throws IOException{//创建文件输入流和文件输出流 , 并生成对应的通道FileInputStream fileInputStream = new FileInputStream("file1.txt");FileChannel inputStreamChannel= fileInputStream.getChannel();FileOutputStream fileOutputStream = new FileOutputStream("file2.txt");FileChannel outputStreamChannel = fileOutputStream.getChannel();//创建字节缓冲区ByteBuffer byteBuffer = ByteBuffer.allocate(1024);//进行数据读取while (true){//在读取前需清除缓冲区byteBuffer.clear();//将文件输入的通道的数据读入缓冲区int read = inputStreamChannel.read(byteBuffer);//当read为-1时 , 即通道数据已读取完毕if (read == -1){break;}//将缓冲区翻转后 , 将缓冲区数据写入文件输出的通道byteBuffer.flip();outputStreamChannel.write(byteBuffer);}fileInputStream.close();fileOutputStream.close();}//文件的复制粘贴public static void copyAndPaste() throws IOException{//复制的文件输入流FileInputStream fileInputStream = new FileInputStream("f:\\a.jpg");FileChannel srcChannel = fileInputStream.getChannel();//粘贴的文件输出流FileOutputStream fileOutputStream = new FileOutputStream("f:\\b.jpg");FileChannel targetChannel = fileOutputStream.getChannel();//使用transferFrom进行复制粘贴targetChannel.transferFrom(srcChannel, 0, srcChannel.size());fileInputStream.close();fileOutputStream.close();}}