Java NIO学习篇之通道FileChannel详解

16 篇文章 0 订阅
15 篇文章 1 订阅

定义:

FileChannel是Java NIO对应于磁盘等存储设备文件操作的通道。

常用API详解:

获取FileChannel的API

/**
* 打开一个与文件的连接通道,用于进行文件操作。
* path:path,文件的路径对象,可用Path.get("文件路径"),获取。
* options:通道的操作参数。通常使用实现类枚举StandardOpenOption指定。
* attrs:创建文件时自动设置的文件属性的可选列表,比如读写执行。
*/
public static FileChannel open(Path path,
                                   Set<? extends OpenOption> options,
                                   FileAttribute<?>... attrs);

//打开一个与文件的连接通道,用于进行文件操作。并可以设置通道的操作参数options
public static FileChannel open(Path path, OpenOption... options)
                                 

demo:

public class FileChannelDemo {

    public static void main(String[] args) throws IOException {
//以读和写的方式打开与文件555.txt的连接的通道。
        FileChannel fileChannel = FileChannel.open(Paths.get("555.txt"),StandardOpenOption.READ,
                StandardOpenOption.WRITE);


//
        Set<OpenOption> openOptions = new HashSet<>();
        openOptions.add(StandardOpenOption.CREATE);
        openOptions.add(StandardOpenOption.READ);
        openOptions.add(StandardOpenOption.WRITE);
        
        Set<PosixFilePermission> fileAttributes = new HashSet<>();
        fileAttributes.add(PosixFilePermission.OWNER_READ);
        fileAttributes.add(PosixFilePermission.OWNER_WRITE);
        fileAttributes.add(PosixFilePermission.OWNER_EXECUTE);
        //以读和写和创建并打开与文件666.txt的连接的通道。并且创建的文件会赋予文件所属者读写执行的权限。
        FileChannel fileChannel1 = FileChannel.open(Paths.get("666.txt"),openOptions,
                PosixFilePermissions.asFileAttribute(fileAttributes));
        
    }
}

Java NIO学习篇之StandardOpenOption详解

Java NIO学习篇之StandardOpenOption详解

读写API:

//把文件数据通过通道读取到缓冲区dst中。返回读取到数据长度。返回-1表示到达文件尾。
public abstract int read(ByteBuffer dst) throws IOException;

//把文件数据通过通道读取到缓冲区数组dst中。返回读取到数据长度。返回-1表示到达文件尾。
//会依次读取到缓冲区数组中的缓冲区,知道把数据读完或者缓冲区不够大。
public final long read(ByteBuffer[] dsts) throws IOException;

//把文件数据通过通道读取到缓冲区数组dst中。返回读取到数据长度。返回-1表示到达文件尾。
//会依次读取到缓冲区数组中的缓冲区,知道把数据读完或者缓冲区不够大。
//可以设置读取到缓冲区数组中的哪些数组,假如dsts数组有5个缓冲区,offset=1 length=3,
//则只会把数据读取到缓冲区数组的下标 1,2,3三个缓冲区上,offset代表下标,length代表长度
public abstract long read(ByteBuffer[] dsts, int offset, int length);

//把文件数据通过通道读取到缓冲区数组dst中。
//以上的读取数组方法读取一个字节数据FileChannel中的游标会右移一位,但是这个方法不会移动游标。
//也就是重复读取还是读取那些数据。
public abstract int read(ByteBuffer dst, long position) throws IOException;


demo:

 public static void testRead() throws IOException {
        FileChannel fileChannel = FileChannel.open(Paths.get("5555.txt"),StandardOpenOption.READ);

        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

        System.out.println("==================>>read(ByteBuffer dst)<<=====================");
        //读取时从文件的总数据字节第二位开始读取
        fileChannel.read(byteBuffer,1);
        byteBuffer.flip();
        System.out.println("position = " + fileChannel.position());
        System.out.println(new String(byteBuffer.array()));

        byteBuffer.clear();

        System.out.println("==================>>read(ByteBuffer dst, long position)<<=====================");
        fileChannel.read(byteBuffer);
        byteBuffer.flip();
        System.out.println("position = " + fileChannel.position());
        System.out.println(new String(byteBuffer.array()));
    }

结果:
在这里插入图片描述
文件内容:
在这里插入图片描述
解释:
第一个读取时使用read(ByteBuffer dst, long position)方法进行读取,position设置为1,所以文件的第一个字节数据I被跳过了。并且读完后通道的偏移量仍然为0。

//把缓冲区中的position到limit-1的数据通过通道写到文件中去。返回写的数据长度。
public abstract int write(ByteBuffer src) throws IOException;

//把缓冲区数组中的多个缓冲区依次通过管道写到文件中去,offset与length与read对应方法大致。
public abstract long write(ByteBuffer[] srcs, int offset, int length)

//把缓冲区数组中的多个缓冲区依次通过管道写到文件中去。
public final long write(ByteBuffer[] srcs) throws IOException

//读取缓冲区的数组通过通道写到文件中去,可指定读取缓冲区的position偏移量。假如缓冲区当前
//position为0,position参数为1,那么最终缓冲区数据读取0+1 到limit-1 的数据。
public abstract int write(ByteBuffer src, long position) throws IOException;
其他API:
//关闭通道
public final void close();

//返回文件的大小
public abstract long size() throws IOException;

//返回此文件字节数据的偏移量。
public abstract long position();

//设置此文件字节数据的偏移量。如果设置地比文件大size大,就会在读取时读到文件尾。返回-1.
public abstract FileChannel position(long newPosition)

//强制将数据刷到存储设备上,如果metaData为false只刷数据,如果metaData为true,刷数据与元数据(权限等)
public abstract void force(boolean metaData);

//判断通道是否还打开着,没有关闭。
 public final boolean isOpen();


//返回一个直接缓冲区MappedByteBuffer
//mode设置直接缓冲区的权限。
//position从通道的文件数据游标position开始。
//size表示要写到缓冲区的数据的长度
public abstract MappedByteBuffer map(MapMode mode,
                                         long position, long size)
        throws IOException;



public static class MapMode {

        /**
         * 只读模式
         */
        public static final MapMode READ_ONLY
            = new MapMode("READ_ONLY");

        /**
         * 读写模式
         */
        public static final MapMode READ_WRITE
            = new MapMode("READ_WRITE");

        /**
         * 写时复制模式
         */
        public static final MapMode PRIVATE
            = new MapMode("PRIVATE");

        private final String name;

        private MapMode(String name) {
            this.name = name;
        }

       
        public String toString() {
            return name;
        }

    }

使用MappedByteBuffer 实现文件复制:

public static void testMapMode() throws IOException {
        FileChannel readFileChannel = FileChannel.open(Paths.get("5555.txt"),StandardOpenOption.READ);
        FileChannel writeFileChannel = FileChannel.open(Paths.get("5555_copy.txt"),StandardOpenOption.READ,StandardOpenOption.WRITE,
                StandardOpenOption.CREATE_NEW);

        MappedByteBuffer readMap = readFileChannel.map(FileChannel.MapMode.READ_ONLY, 0, readFileChannel.size());

        MappedByteBuffer writeMap = writeFileChannel.map(FileChannel.MapMode.READ_WRITE,0,readFileChannel.size());


        byte[] array = new byte[readMap.remaining()];

        
        readMap.get(array);

        //无需通道直接进行文件写
        writeMap.put(array);

        writeFileChannel.close();
        readFileChannel.close();

    }
transferTo和transferFrom

/**
* 把本通道打开的文件的数据传输到目标通道target中。
* 可以指定本通道的position文件数据游标和要传输的数据大小size。如果position比本通道打开的文件大,就没有字节转移。
* 传输是使用直接内存以零拷贝的方式进行传输。
* 该传输不会改变本通道的position值。
*/
public abstract long transferTo(long position, long count,
                                    WritableByteChannel target)
        throws IOException;

/**
* 把src通道打开的文件的数据传输到本通道中
* 可以指定转移写入的本通道的文件的position位置,和要转移的数据长度size。如果position比本通道打开的文件大,就没有字节转移。
* 传输是使用直接内存以零拷贝的方式进行传输。
* 该传输不会改变src通道的position值
*/
public abstract long transferFrom(ReadableByteChannel src,
                                      long position, long count)
        throws IOException;

demo:

public static void testTransfer() throws IOException {
        
        FileChannel readFileChannel = FileChannel.open(Paths.get("5555.txt"),StandardOpenOption.READ);

        //把文件5555复制一份 6666.txt
        FileChannel writeFileChannel = FileChannel.open(Paths.get("6666.txt"),StandardOpenOption.CREATE,StandardOpenOption.WRITE);
        readFileChannel.transferTo(0,readFileChannel.size(),writeFileChannel);


        //把文件5555复制一份 7777.txt
        FileChannel rfc = FileChannel.open(Paths.get("7777.txt"),StandardOpenOption.CREATE,StandardOpenOption.WRITE);
        rfc.transferFrom(readFileChannel,0,readFileChannel.size());

    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值