Java的Channel通道之FileChannel类详解

 更新时间:2023年10月24日 09:44:56   作者:liyong0829  
这篇文章主要介绍了Java的Channel通道之FileChannel类详解,FileChannel类是Java NIO中的一个重要类,用于在文件中进行读写操作,它提供了一种高效的方式来处理大文件和随机访问文件的需求,需要的朋友可以参考下

Channel(通道)之FileChannel类

  • FileChannel类的基本使用 获取FileChannel类的对象
  • java.nio.channels.FileChannel (抽象类):用于读、写文件的通道
  • FileChannel是抽象类,我们可以通过FileInputStream和FileOutputStream的getChannel()方法方便的获取一个它的子类对象。
FileInputStream fi=new FileInputStream(new File(src));
FileOutputStream fo=new FileOutputStream(new File(dst));
//获得传输通道channel
FileChannel inChannel=fi.getChannel();
FileChannel outChannel=fo.getChannel();

使用FileChannel类完成文件的复制

 public static void main(String[] args) throws Exception{
        FileInputStream fis = new FileInputStream("a.txt");
        FileOutputStream fos = new FileOutputStream("aCopy1.txt");
        // 获得FileChannel管道对象
        FileChannel c1 = fis.getChannel();
        FileChannel c2 = fos.getChannel();

        // 创建ByteBuffer数组
        ByteBuffer b = ByteBuffer.allocate(1000);

        // 循环读取数据
        while ((c1.read(b)) != -1){// 读取的字节会填充postion到limit位置之间
            // 重置 postion为0,limit为postion的位置
            b.flip();
            // 写出数据
            c2.write(b);// 会把postion到limit之间的数据写出
            // 还原
            b.clear();// positon为:0  limit为: capacity 用于下次读取
        }
        // 释放资源
        c2.close();
        c1.close();
        fos.close();
        fis.close();
        /*byte[] bys = new byte[8192];
        int len;
        while ((len = fis.read(bys)) != -1){
            fos.write(bys,0,len);
        }
        fos.close();
        fis.close();*/
    }

FileChannel结合MappedByteBuffer实现高效读写

MappedByteBuffer类

  • 使用FileChannel结合ByteBuffer实现的管道读写,但并不能提高文件的读写效率。
  • ByteBuffer有个抽象子类:MappedByteBuffer,它可以将文件直接映射至内存,把硬盘中的读写变成内存中的读写, 所以可以提高大文件的读写效率
  • 可以调用FileChannel的map()方法获取一个MappedByteBuffer,map()方法的原型: MappedByteBuffer map(MapMode mode, long position, long size); 说明:将节点中从position开始的size个字节映射到返回的MappedByteBuffer中

//复制2GB以下的文件 //map的第三个参数被限制在Integer.MAX_VALUE(字节) = 2G

public static void main(String[] args) throws Exception{
        //java.io.RandomAccessFile类,可以设置读、写模式的IO流类。
        //"r"表示:只读--输入流,只读就可以。
        RandomAccessFile r1 = new RandomAccessFile("a.txt","r");
        //"rw"表示:读、写--输出流,需要读、写。
        RandomAccessFile r2 = new RandomAccessFile("aCopy2.txt","rw");

        // 获得FileChannel管道对象
        FileChannel c1 = r1.getChannel();
        FileChannel c2 = r2.getChannel();

        // 获取文件的大小
        long size = c1.size();

        // 直接把硬盘中的文件映射到内存中
        MappedByteBuffer b1 = c1.map(FileChannel.MapMode.READ_ONLY, 0, size);
        MappedByteBuffer b2 = c2.map(FileChannel.MapMode.READ_WRITE, 0, size);

        // 循环读取数据
        for (long i = 0; i < size; i++) {
            // 读取字节
            byte b = b1.get();
            // 保存到第二个数组中
            b2.put(b);
        }
        // 释放资源
        c2.close();
        c1.close();
        r2.close();
        r1.close();
    }

//下例使用循环,将文件分块,可以高效的复制大于2G的文件

    public static void main(String[] args) throws Exception{
        //java.io.RandomAccessFile类,可以设置读、写模式的IO流类。
        //"r"表示:只读--输入流,只读就可以。
        RandomAccessFile r1 = new RandomAccessFile("H:\\资料.zip","r");
        //"rw"表示:读、写--输出流,需要读、写。
        RandomAccessFile r2 = new RandomAccessFile("H:\\资料2.zip","rw");

        // 获得FileChannel管道对象
        FileChannel c1 = r1.getChannel();
        FileChannel c2 = r2.getChannel();

        // 获取文件的大小
        long size = c1.size();

        // 每次期望复制500M
        int everySize = 1024*1024*500;

        // 总共需要复制多少次
        long count = size % everySize == 0 ? size/everySize : size/everySize+1;

        // 开始复制
        for (long i = 0; i < count; i++) {
            // 每次开始复制的位置
            long start = everySize*i;

            // 每次复制的实际大小
            long trueSize = size - start > everySize ? everySize : size - start;

            // 直接把硬盘中的文件映射到内存中
            MappedByteBuffer b1 = c1.map(FileChannel.MapMode.READ_ONLY, start, trueSize);
            MappedByteBuffer b2 = c2.map(FileChannel.MapMode.READ_WRITE, start, trueSize);

            // 循环读取数据
            for (long j = 0; j < trueSize; j++) {
                // 读取字节
                byte b = b1.get();
                // 保存到第二个数组中
                b2.put(b);
            }
        }

        // 释放资源
        c2.close();
        c1.close();
        r2.close();
        r1.close();
        
    }

ServerSocketChannel和SocketChannel创建连接

SocketChannel创建连接

  • 客户端:SocketChannel类用于连接的客户端,它相当于:Socket。

ServerSocketChanne创建连接

  • 服务器端:ServerSocketChannel类用于连接的服务器端,它相当于:ServerSocket 服务器代码
public class Server {
    public static void main(String[] args)  throws IOException{
		//创建对象
        //ServerSocket ss = new ServerSocket(8888);

        //创建
        ServerSocketChannel ssc = ServerSocketChannel.open();
        //服务器绑定端口
        ssc.bind(new InetSocketAddress(8888));

        //连接上客户端
        SocketChannel sc = ssc.accept();
       
        //服务器端接受数据
        //创建数组
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        //接收数据
        int len = sc.read(buffer);
        //打印结构
        System.out.println(new String(buffer.array(),0,len));

        //关闭资源
        sc.close();
    }
}

客户端代码

public class Client {
    public static void main(String[] args) {
        //创建对象
        //Socket s = new Socket("127.0.0.1",8888);

        //创建对象
        SocketChannel sc = SocketChannel.open();
        //连接服务器
        sc.connect(new InetSocketAddress("127.0.0.1",8888));

        //客户端发数据
        //创建数组
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        //数组中添加数据
        buffer.put("你好".getBytes());
        //切换
        buffer.flip();
        //发出数据
        sc.write(buffer);

        //关流
        sc.close();
    }
}

到此这篇关于Java的Channel通道之FileChannel类详解的文章就介绍到这了,更多相关Java的FileChannel类内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java中JS引擎实现的一句话木马

    Java中JS引擎实现的一句话木马

    这篇文章主要为大家介绍了如何利用Java中JS引擎实现的一句话木马,有需要的朋友可以借鉴参考下,希望能够有所帮助祝大家多多进步
    2022-02-02
  • 一文深入解析JDBC超时机制

    一文深入解析JDBC超时机制

    恰当的JDBC超时设置能够有效地减少服务失效的时间,下面这篇文章主要给大家介绍了关于JDBC超时机制的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2021-10-10
  • Java设计模式之责任链模式

    Java设计模式之责任链模式

    这篇文章介绍了Java设计模式之责任链模式,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-10-10
  • Java JSONObject与JSONArray对象案例详解

    Java JSONObject与JSONArray对象案例详解

    这篇文章主要介绍了Java JSONObject与JSONArray对象案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-09-09
  • Java分支结构和循环结构原理与用法详解

    Java分支结构和循环结构原理与用法详解

    这篇文章主要介绍了Java分支结构和循环结构原理与用法,结合实例形式分析了java分支结构、循环结构、跳转语句等相关概念、原理、使用技巧与操作注意事项,需要的朋友可以参考下
    2020-02-02
  • java实现两台服务器间文件复制的方法

    java实现两台服务器间文件复制的方法

    这篇文章主要介绍了java实现两台服务器间文件复制的方法,是对单台服务器上文件复制功能的升级与改进,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-01-01
  • Java基础之Stream流原理与用法详解

    Java基础之Stream流原理与用法详解

    从Java1.8开始提出了Stream流的概念,侧重对于源数据计算能力的封装,并且支持序列与并行两种操作方式。本文就来为大家详细讲讲Stream流原理与用法
    2022-08-08
  • IntelliJ IDEA语法报错

    IntelliJ IDEA语法报错"Usage of API documented as @since 1.6+"的解决

    今天小编就为大家分享一篇关于IntelliJ IDEA语法报错"Usage of API documented as @since 1.6+"的解决办法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-10-10
  • Java中ThreadLocal共享变量的使用

    Java中ThreadLocal共享变量的使用

    java.lang.ThreadLocal该类提供了线程局部变量,用于在当前线程中共享数据,本文主要介绍了Java中ThreadLocal共享变量的使用,具有一定的参考价值,感兴趣的可以了解一下
    2024-01-01
  • 面试题:Java 实现查找旋转数组的最小数字

    面试题:Java 实现查找旋转数组的最小数字

    这篇文章主要介绍了Java 实现查找旋转数组的最小数字,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-07-07

最新评论