JavaNIO-FileChannel通道

一)FileChannel介绍

概述:用于读取,写入,映射和操作文件的通道。

          它只能通过调用getChannel()方式创建FileChannel对象,不能直接new FileChannel()。

优点:

1、对大文件操作支持比较好,文件访问和传输速度快。

2、支持多线程。

3、数据不易丢失。

 

二)FileChannel案例详解

方式一使用FileChannel通道类中的API

 

方法说明:

1、static FileChannel open(Path path, OpenOption... options)

打开或创建文件,返回文件通道以访问该文件。

2、static FileChannel open(Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs)

打开或创建文件,返回文件通道以访问该文件。

 

3、abstract long transferTo(long position, long count, WritableByteChannel target)

将该通道文件的字节传输到给定的可写字节通道。用来从FileChannel到其它通道的数据传输。

4、abstract long transferFrom(ReadableByteChannel src, long position, long count)

从给定的可读字节通道将字节传输到该通道的文件中。允许从源通道到FileChannel的数据传输。

 

源码实现:

/**
 * 方式一:直接使用通道类中的API
 */
public static void method1() {
    long start = System.currentTimeMillis();
		
    FileChannel in = null;
    FileChannel out =null;
    try {
        // 通过Paths获取源文件的路径,StandardOpenOption.READ 读取模式
        in = FileChannel.open(Paths.get("D:\\io\\446MB.rar"), StandardOpenOption.READ);
        out = FileChannel.open(Paths.get("D:\\io\\abab.rar"), StandardOpenOption.READ
					, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
			
        //把数据读到 输出通道中取,完成文件的复制
        //in.transferTo(0,in.size(),out);
			
        // 强制将此通道文件的任何更新写入包含该通道的存储设备。
        out.force(false);
        // 写出数据,写出的数据从输入通道中来
        out.transferFrom(in, 0, in.size());
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
		
    long end = System.currentTimeMillis();
    System.out.println("拷贝文件,总共耗时" + (end-start) + "ms");
}

 

方式二使用MappedByteBuffer字节缓冲器

 

方法说明:

1、abstract MappedByteBuffer map(FileChannel.MapMode mode, long position, long size)

将此频道文件的区域直接映射到内存中。

 

源码实现:

/**
 * 方式二:使用MappedByteBuffer字节缓冲器
 */
public static void method2() {
    long start = System.currentTimeMillis();
		
    FileChannel in = null;
    FileChannel out =null;
    try {
        // 通过Paths获取源文件的路径,StandardOpenOption.READ 读取模式
        in = FileChannel.open(Paths.get("D:\\io\\446MB.rar"), StandardOpenOption.READ);
        out = FileChannel.open(Paths.get("D:\\io\\abab.rar"), StandardOpenOption.READ
					, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
			
        // 操作内存映射文件(也就是这个缓冲区在物理内存中)
        MappedByteBuffer inByteBuffer = in.map(FileChannel.MapMode.READ_ONLY, 0, in.size());
        MappedByteBuffer outByteBuffer = out.map(FileChannel.MapMode.READ_WRITE, 0, in.size());
			
        // 直接对缓冲区进行读写操作
        byte[] bytes = new byte[inByteBuffer.limit()];
			
        inByteBuffer.get(bytes);
        outByteBuffer.put(bytes);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
		
    long end = System.currentTimeMillis();
    System.out.println("拷贝文件,总共耗时" + (end-start) + "ms");
}

 

方式三使用RandomAccessFile实例

 

方法说明:

1、RandomAccessFile(File file, String mode)

创建一个随机访问文件流从File参数指定的文件中读取,并可选地写入文件。

2、RandomAccessFile(String name, String mode)

创建随机访问文件流,以从中指定名称的文件读取,并可选择写入文件。

备注:mode的模式包含“r”、“rw”、“rws”、“rwd”共4种模式。

 

源码实现:

public static void method3() {
    long start = System.currentTimeMillis();
		
    RandomAccessFile randomFile = null;
    FileChannel inChannel = null;
    try {
        randomFile = new RandomAccessFile("D:\\io\\a.txt", "rw");
        inChannel = randomFile.getChannel();
			
        // 缓冲区
        ByteBuffer buf = ByteBuffer.allocate(48);
			
        int bytesRead = inChannel.read(buf);
        while (bytesRead != -1) {
            buf.flip(); // 从写模式转换成读模式
				
            // 打印
            while (buf.hasRemaining()) {
                System.out.print((char)buf.get());
            }
				
            buf.clear(); // 清理缓存,重新读写
            bytesRead = inChannel.read(buf);
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (inChannel != null) {
                inChannel.close();
            }
            if (randomFile != null) {
                randomFile.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    long end = System.currentTimeMillis();
    System.out.println("拷贝文件,总共耗时" + (end-start) + "ms");
}

 

方式四使用FileInputStream字节输入流和FileOutputStream字节输出流中getChannel()

 

源码实现:

/**
 * 方式四:使用FileInputStream字节输入流和FileOutputStream字节输出流中getChannel()
 */
public static void method4() {
    long start = System.currentTimeMillis();
		
    FileInputStream in = null;
    FileOutputStream out = null;
    FileChannel inChannel = null;
    FileChannel outChannel =null;
    try {
        // 创建文件输入输出流
        in = new FileInputStream("D:\\io\\6_81MB.xlsx");
        out = new FileOutputStream("D:\\io\\abcd.xlsx");
			
        // 文件输入输出流的getChannel()方法获取通道
        inChannel = in.getChannel();
        outChannel = out.getChannel();
			
        // 获取非直接缓冲区
        //ByteBuffer buf = ByteBuffer.wrap(new byte[1024*8]);
			
        ByteBuffer buf = ByteBuffer.allocate(256);
			
        int bytesRead = inChannel.read(buf);
        while (bytesRead != -1) {
            buf.flip(); // 从写模式转换成读模式
				
            // 将缓冲区中的数据写入通道中
            outChannel.write(buf);
				
            buf.clear(); // 清空缓冲区并返回对缓冲区的引用
            bytesRead = inChannel.read(buf);
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (inChannel != null) {
                inChannel.close();
            }
            if (outChannel != null) {
                outChannel.close();
            }
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
		
    long end = System.currentTimeMillis();
    System.out.println("拷贝文件,总共耗时" + (end-start) + "ms");
}

 

识别二维码关注个人微信公众号

本章完结,待续,欢迎转载!
 
本文说明:该文章属于原创,如需转载,请标明文章转载来源!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值