JavaNIO-通道02 FileChannel 文件操作

2019-07-17  本文已影响0人  贪睡的企鹅

1 FileChannel 概述

2 FileChannel 类结构

image

核心功能

1 读取、写入和关闭通道文件。
2 以不影响通道当前位置(position)的方式,对文件中绝对位置的字节进行读取或写人。
3 MMAP,将文件中的某个区域直接映射到程序用户态内存中(用户态)。对于较大的文件,这通常比调用普通的 read ()或write ()方法更为高效。
4 强制对底层存储设备进行文件的更新(内存刷入磁盘),确保在系统崩溃时不丢失数据。
5 SendFile 零拷贝文件数据读写拷贝
6 可以锁定某个文件区域,以阻止其他程序对其进行访问。
7 多个并发线程可安全地使用文件通道。

3 核心API 使用

1 write(ByteBuffer buffer)

从给定缓冲区读取能数据(limit-position),从通道设置position位置写入。

写入案例

@Test
    public void test_write() throws Exception {


        RandomAccessFile readFile = new RandomAccessFile("write1.txt", "rw");
        RandomAccessFile writeFile = new RandomAccessFile("write1.txt", "rw");
        FileChannel fileChannel = writeFile.getChannel();
        FileChannel fileChannel2 = readFile.getChannel();


        /** 设置文件写入位置 **/
        fileChannel.position(0);
        try{
            ByteBuffer buffer=ByteBuffer.wrap("abcd".getBytes());

            /** 写入文件字节缓冲区数据 **/
            buffer.position(1);
            buffer.limit(2);
            /** 写入文件之前的fileChannel.position()位置 **/
            System.out.println ("fileChannel.position= " + fileChannel.position()) ;
            /** 将缓冲区中position->limist 数据写入到文件设置position位置 **/
            System.out.println ("write() size= " + fileChannel.write(buffer)) ;
            /** 写入文件之后的fileChannel.position()位置 **/
            System.out.println ("fileChannel.position= " + fileChannel.position()) ;

            System.out.println();

            /** 重置缓冲区 **/
            buffer.position(1);
            buffer.limit(2);
            System.out.println ("A fileChannel.position ()= " + fileChannel.position()) ;
            /** 将缓冲区中position->limist 数据写入到文件设置position位置 **/
            System.out.println ("write() size= " + fileChannel.write(buffer)) ;
            System.out.println ("A fileChannel.position ()= " + fileChannel.position()) ;


            ByteBuffer allocate = ByteBuffer.allocate(8);
            fileChannel2.read(allocate);
            System.out.println(new String(allocate.array()));
        }finally {
            readFile.close();
            fileChannel.close();
        }
    }
    
fileChannel.position= 0
write() size= 1
fileChannel.position= 1

A fileChannel.position ()= 1
write() size= 1
A fileChannel.position ()= 2
bb   

多线程同步案例

public void test_write2() throws Exception {
        RandomAccessFile readFile = new RandomAccessFile("write2.txt", "rw");
        FileChannel fileChannel = readFile.getChannel();
        try{
            IntStream.range(0,10).forEach(i->{
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            ByteBuffer buffer=ByteBuffer.wrap("abcd\r\n".getBytes());
                            System.out.println ("write() size= " + fileChannel.write(buffer)) ;
                        } catch (IOException e) {
                        }
                    }
                });
                thread.start();
                Thread thread2 = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            ByteBuffer buffer=ByteBuffer.wrap("1234\r\n".getBytes());
                            System.out.println ("write() size= " + fileChannel.write(buffer)) ;
                        } catch (IOException e) {
                        }
                    }
                });
                thread2.start();
            });
        }finally {

        }
        Thread.sleep(3000);
        readFile.close();
        fileChannel.close();
    }
    
//文件内容    
abcd
1234
1234
abcd
..省略

2 write(ByteBuffer buffer,long position)

从给定缓冲区读取能数据(limit-position),从函数设置position位置写入。

写入数据案例

@Test
    public void test_write3() throws Exception {
        RandomAccessFile readFile = new RandomAccessFile("write7.txt", "rw");
        RandomAccessFile writeFile = new RandomAccessFile("write7.txt", "rw");
        FileChannel fileChannel = writeFile.getChannel();
        FileChannel fileChannel2 = readFile.getChannel();
        try{
            /** 写入文件字节缓冲区数据 **/
            ByteBuffer buffer=ByteBuffer.wrap("--abcd".getBytes());
            buffer.position(2);

            /** 写入文件之前的fileChannel.position()位置 **/
            System.out.println ("fileChannel.position= " + fileChannel.position()) ;
            /** 将缓冲区中position->limist 数据从通道position位置写入 **/
            System.out.println ("write() size= " + fileChannel.write(buffer,0)) ;
            /** 写入文件之后的fileChannel.position()位置 **/
            System.out.println ("fileChannel.position= " + fileChannel.position()) ;


            System.out.println();
            /** 重置缓冲区 **/
            buffer.position(2);
            /** 写入文件之前的fileChannel.position()位置 **/
            System.out.println ("fileChannel.position= " + fileChannel.position()) ;
            /** 将缓冲区中position->limist 数据从通道position位置写入 **/
            System.out.println ("write() size= " + fileChannel.write(buffer,4)) ;
            /** 写入文件之后的fileChannel.position()位置 **/
            System.out.println ("fileChannel.position= " + fileChannel.position()) ;


            ByteBuffer allocate = ByteBuffer.allocate(8);
            fileChannel2.read(allocate);
            System.out.println(new String(allocate.array()));

        }finally {
            readFile.close();
            fileChannel.close();
        }
    }

fileChannel.position= 0
write() size= 4
fileChannel.position= 0

fileChannel.position= 0
write() size= 4
fileChannel.position= 0
abcdabcd    

多线程同步案例

@Test
    public void test_write4() throws Exception {
        RandomAccessFile readFile = new RandomAccessFile("write8.txt", "rw");
        FileChannel fileChannel = readFile.getChannel();
        try{
            IntStream.range(0,10).forEach(i->{
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            ByteBuffer buffer=ByteBuffer.wrap("abcd".getBytes());
                            System.out.println(fileChannel.position());
                            System.out.println ("write() size= " + fileChannel.write(buffer,fileChannel.position())) ;
                        } catch (IOException e) {
                        }
                    }
                });
                thread.start();
                Thread thread2 = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            ByteBuffer buffer=ByteBuffer.wrap("1234".getBytes());
                            System.out.println(fileChannel.position());
                            System.out.println ("write() size= " + fileChannel.write(buffer,fileChannel.position())) ;
                        } catch (IOException e) {
                        }
                    }
                });
                thread2.start();
            });
        }finally {

        }
        Thread.sleep(3000);
        readFile.close();
        fileChannel.close();
    }

//文件内容
abcd or 1234 //位置每次从0开始 下一次覆盖上一次

3 read(ByteBuffer buffer)

读取案例

从通道指定位置position读取通道数据(大小由缓冲区容量决定limit-position),写入到给定的缓冲区中

    @Test
    public void test_read() throws Exception {
        RandomAccessFile readFile = new RandomAccessFile("write1.txt", "rw");
        FileChannel fileChannel = readFile.getChannel();
        /** 从通道指定位置读取 **/
        fileChannel.position(0);
        try{
            ByteBuffer buffer=ByteBuffer.allocate(5);
            /** 从缓冲区指定位置写入 **/
            buffer.position(1);
            /** 从缓冲区写入限制位置 **/
            buffer.limit(5);
            /** 写入文件之前的fileChannel.position()位置 **/
            System.out.println ("fileChannel.position= " + fileChannel.position()) ;
            /** 从通道position位置开始读取buffer.remaining大小字节,从缓冲区position位置开始写入 **/
            System.out.println ("A fileChannel.readLength= " + fileChannel.read(buffer)) ;
            /** 写入文件之后的fileChannel.position()位置 **/
            System.out.println ("fileChannel.position= " + fileChannel.position()) ;
            System.out.println (buffer) ;
            System.out.println (new String(buffer.array())) ;
            buffer.clear();
            System.out.println ("A fileChannel.readLength= " + fileChannel.read(buffer)) ;
        }finally {
            readFile.close();
            fileChannel.close();
        }
    }

fileChannel.position= 0
A fileChannel.readLength= 2
fileChannel.position= 2
java.nio.HeapByteBuffer[pos=3 lim=5 cap=5]
 bb  
A fileChannel.readLength= -1   

多线程同步案例

读取文件内容

read.txt
aaaalaaaa2aaaa3aaaa4aaaa5aaaa6aaaa7aaaa8aaaa9bbbblbbbb2bbbb3bbbb4bbbb5bbbb6bbbb7bbbb8bbbb9cccclcccc2cccc3cccc4cccc5cccc6cccc7cccc8cccc9
@Test
    public void test_read2() throws Exception {
        RandomAccessFile readFile = new RandomAccessFile("read.txt", "rw");
        FileChannel fileChannel = readFile.getChannel();
        try{
            IntStream.range(0,3).forEach(i->{
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            ByteBuffer buffer=ByteBuffer.allocate(5);
                            int readLength = fileChannel.read(buffer);
                            while (readLength!=-1){
                                System.out.println(new String(buffer.array(),0,readLength));
                                buffer.clear();
                                readLength = fileChannel.read(buffer);
                            }
                        } catch (IOException e) {
                        }
                    }
                });
                thread.start();
            });
        }finally {

        }
        Thread.sleep(3000);
        readFile.close();
        fileChannel.close();
    }
    
aaaal
aaaa2
aaaa3
aaaa4
aaaa5
aaaa7
..省略

4 read(ByteBuffer buffer,Long position)

从函数指定位置position读取通道数据(大小由缓冲区容量决定limit-position),写入到给定的缓冲区中。

读取案例

@Test
    public void test_read3() throws Exception {
        RandomAccessFile readFile = new RandomAccessFile("write7.txt", "rw");
        FileChannel fileChannel = readFile.getChannel();
        try{
            ByteBuffer buffer=ByteBuffer.allocate(5);
            buffer.position(1);
            buffer.limit(5);
            /** 写入文件之前的fileChannel.position()位置 **/
            System.out.println ("fileChannel.position= " + fileChannel.position()) ;
            /** 从通道position位置开始读取buffer.remaining大小字节,从缓冲区position位置开始写入 **/
            System.out.println ("A fileChannel.readLength= " + fileChannel.read(buffer,4)) ;
            /** 写入文件之前的fileChannel.position()位置 **/
            System.out.println ("fileChannel.position= " + fileChannel.position()) ;

            System.out.println (buffer) ;
            System.out.println (new String(buffer.array())) ;

        }finally {
            readFile.close();
            fileChannel.close();
        }
    }

fileChannel.position= 0
A fileChannel.readLength= 4
fileChannel.position= 0
java.nio.HeapByteBuffer[pos=5 lim=5 cap=5]
 abcd    

5 write(ByteBuffer[] srcs)

从给定缓冲区数组读取数据(总大小为每个缓冲区数据limit-position之和),从通道指定位置positio写入,

写入案例

 @Test
    public void test_batchwrite() throws Exception {
        RandomAccessFile readFile = new RandomAccessFile("write3.txt", "rw");
        FileChannel fileChannel = readFile.getChannel();
        RandomAccessFile writeFile = new RandomAccessFile("write3.txt", "rw");
        FileChannel fileChannel2 = writeFile.getChannel();
        /** 从通道指定位置写入 **/
        fileChannel.position(0);
        try{
            ByteBuffer buffer1=ByteBuffer.wrap("000001".getBytes());
            ByteBuffer buffer2=ByteBuffer.wrap("000002".getBytes());
            buffer1.position(2);
            buffer1.limit(6);
            buffer2.position(2);
            buffer2.limit(6);

            ByteBuffer[] buffers=new ByteBuffer[]{buffer1,buffer2};
            System.out.println ("A fileChannel.position ()= " + fileChannel.position());
            /** 将缓冲区数组中 每个缓冲区中position->limist 数据写入到文件设置position位置 **/
            Long writeLen = fileChannel.write(buffers);
            System.out.println ("A fileChannel.position ()= " + fileChannel.position());

            ByteBuffer allocate = ByteBuffer.allocate(writeLen.intValue());
            fileChannel2.read(allocate);
            System.out.println(new String(allocate.array()));
        }finally {
            readFile.close();
            fileChannel.close();
        }
    }

A fileChannel.position ()= 0
A fileChannel.position ()= 8
00010002    

线程同步案例

@Test
    public void test_batchwrite2() throws Exception {
        RandomAccessFile readFile = new RandomAccessFile("write4.txt", "rw");
        FileChannel fileChannel = readFile.getChannel();
        fileChannel.position(0);
        try{
            IntStream.range(0,10).forEach(i->{
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            ByteBuffer buffer1=ByteBuffer.wrap("00001\r\n".getBytes());
                            ByteBuffer buffer2=ByteBuffer.wrap("00002\r\n".getBytes());
                            buffer1.position(2);
                            buffer2.position(2);
                            ByteBuffer[] buffers=new ByteBuffer[]{buffer1,buffer2};
                            System.out.println ("write() size= " + fileChannel.write(buffers)) ;
                        } catch (IOException e) {
                        }
                    }
                });
                thread.start();
                Thread thread2 = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            ByteBuffer buffer1=ByteBuffer.wrap("0000a\r\n".getBytes());
                            ByteBuffer buffer2=ByteBuffer.wrap("0000b\r\n".getBytes());
                            buffer1.position(2);
                            buffer2.position(2);
                            ByteBuffer[] buffers=new ByteBuffer[]{buffer1,buffer2};
                            System.out.println ("write() size= " + fileChannel.write(buffers)) ;
                        } catch (IOException e) {
                        }
                    }
                });
                thread2.start();
            });
        }finally {

        }
        Thread.sleep(3000);
        readFile.close();
        fileChannel.close();
    }

001
002
00a
00b
...省略

6 write(ByteBuffer[] srcs, int offset, int length)

从给定缓冲区数组子序列读取数据(每个缓冲区写入数据=limit-position),从通道指定位置写入

@param  srcs 写入通道字节缓冲区数组

@param  offset 在缓冲区数组从哪个位置上缓冲区开始读取
     
@param  length 从offset开始,读取多少个缓冲区
     
@return  通道写入的字节数

写入案例

@Test
    public void test_batchwrite3() throws Exception {

        RandomAccessFile readFile = new RandomAccessFile("write5.txt", "rw");
        FileChannel fileChannel = readFile.getChannel();
        RandomAccessFile writeFile = new RandomAccessFile("write5.txt", "rw");
        FileChannel fileChannel2 = writeFile.getChannel();
        /** 从文件指定位置写入 **/
        fileChannel.position(0);
        try{
            ByteBuffer buffer1=ByteBuffer.wrap("abcd".getBytes());
            ByteBuffer buffer2=ByteBuffer.wrap("-1234x".getBytes());
            buffer2.position(1);
            buffer2.limit(5);
            ByteBuffer buffer3=ByteBuffer.wrap("5678".getBytes());
            ByteBuffer buffer4=ByteBuffer.wrap("efch".getBytes());

            /** 将缓冲区数组中 每个缓冲区中position->limist 数据写入到文件设置position位置 **/
            ByteBuffer[] buffers=new ByteBuffer[]{buffer1,buffer2,buffer3,buffer4};
            System.out.println ("A fileChannel.position ()= " + fileChannel.position());
            Long writeLen = fileChannel.write(buffers,1,3);
            System.out.println ("A fileChannel.position ()= " + fileChannel.position());

            ByteBuffer allocate = ByteBuffer.allocate(writeLen.intValue());
            fileChannel2.read(allocate);
            System.out.println(new String(allocate.array()));
        }finally {
            readFile.close();
            fileChannel.close();
        }
    }

A fileChannel.position ()= 0
A fileChannel.position ()= 12
12345678efch    

线程同步案例

 public static ByteBuffer[] getByteBufferArray(String str1,String str2){
        ByteBuffer buffer1=ByteBuffer.wrap(str1.getBytes());
        ByteBuffer buffer2=ByteBuffer.wrap(str2.getBytes());
        ByteBuffer[] buffers=new ByteBuffer[]{buffer1,buffer2};
        return  buffers;
    }

    @Test
    public void test_batchwrite4() throws Exception {
        RandomAccessFile readFile = new RandomAccessFile("write6.txt", "rw");
        FileChannel fileChannel = readFile.getChannel();
        fileChannel.position(0);
        try{
            IntStream.range(0,10).forEach(i->{
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            ByteBuffer[] buffers=getByteBufferArray("aaaa","bbbb");
                            System.out.println ("write() size= " + fileChannel.write(buffers,0,2)) ;
                        } catch (IOException e) {
                        }
                    }
                });
                thread.start();
                Thread thread2 = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            ByteBuffer[] buffers=getByteBufferArray("xxxx","yyyy");
                            System.out.println ("write() size= " + fileChannel.write(buffers,0,2)) ;
                        } catch (IOException e) {
                        }
                    }
                });
                thread2.start();
            });
        }finally {

        }
        Thread.sleep(3000);
        readFile.close();
        fileChannel.close();
    }
    
aaaabbbbaaaabbbbxxxxyyyyaaaabbbbaaaabbbbxxxxyyyyxxxxyyyyaaaabbbbxxxxyyyyxxxxyyyyaaaabbbbaaaabbbbxxxxyyyyxxxxyyyyaaaabbbbxxxxyyyyxxxxyyyyaaaabbbbaaaabbbbxxxxyyyy    

7 write(ByteBuffer[] dsts)

从给定缓冲区数组读取数据(每个缓冲区写入数据=limit-position),从通道指定位置写入,通道中position偏移,多线程同步

写入案例

 @Test
    public void test_batchwrite() throws Exception {
        RandomAccessFile readFile = new RandomAccessFile("write3.txt", "rw");
        FileChannel fileChannel = readFile.getChannel();
        RandomAccessFile writeFile = new RandomAccessFile("write3.txt", "rw");
        FileChannel fileChannel2 = writeFile.getChannel();
        /** 从通道指定位置写入 **/
        fileChannel.position(0);
        try{
            ByteBuffer buffer1=ByteBuffer.wrap("000001".getBytes());
            ByteBuffer buffer2=ByteBuffer.wrap("000002".getBytes());
            buffer1.position(2);
            buffer1.limit(6);
            buffer2.position(2);
            buffer2.limit(6);

            ByteBuffer[] buffers=new ByteBuffer[]{buffer1,buffer2};
            System.out.println ("A fileChannel.position ()= " + fileChannel.position());
            /** 将缓冲区数组中 每个缓冲区中position->limist 数据写入到文件设置position位置 **/
            Long writeLen = fileChannel.write(buffers);
            System.out.println ("A fileChannel.position ()= " + fileChannel.position());

            ByteBuffer allocate = ByteBuffer.allocate(writeLen.intValue());
            fileChannel2.read(allocate);
            System.out.println(new String(allocate.array()));
        }finally {
            readFile.close();
            fileChannel.close();
        }
    }

A fileChannel.position ()= 0
A fileChannel.position ()= 8
00010002    

多线程同步案例

 @Test
    public void test_batchwrite2() throws Exception {
        RandomAccessFile readFile = new RandomAccessFile("write4.txt", "rw");
        FileChannel fileChannel = readFile.getChannel();
        fileChannel.position(0);
        try{
            IntStream.range(0,10).forEach(i->{
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            ByteBuffer buffer1=ByteBuffer.wrap("00001\r\n".getBytes());
                            ByteBuffer buffer2=ByteBuffer.wrap("00002\r\n".getBytes());
                            buffer1.position(2);
                            buffer2.position(2);
                            ByteBuffer[] buffers=new ByteBuffer[]{buffer1,buffer2};
                            System.out.println ("write() size= " + fileChannel.write(buffers)) ;
                        } catch (IOException e) {
                        }
                    }
                });
                thread.start();
                Thread thread2 = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            ByteBuffer buffer1=ByteBuffer.wrap("0000a\r\n".getBytes());
                            ByteBuffer buffer2=ByteBuffer.wrap("0000b\r\n".getBytes());
                            buffer1.position(2);
                            buffer2.position(2);
                            ByteBuffer[] buffers=new ByteBuffer[]{buffer1,buffer2};
                            System.out.println ("write() size= " + fileChannel.write(buffers)) ;
                        } catch (IOException e) {
                        }
                    }
                });
                thread2.start();
            });
        }finally {

        }
        Thread.sleep(3000);
        readFile.close();
        fileChannel.close();
    }

文件内容
001
002
00a
00b
00a

8 read(ByteBuffer[] dsts)

将此通道指定position位置读取数据,写入字节缓冲区数组中(写入大小等于每个缓冲区容量(limit-position)之和)

读取案例

@Test
    public void test_batchread() throws Exception {
        RandomAccessFile readFile = new RandomAccessFile("write3.txt", "rw");
        FileChannel fileChannel = readFile.getChannel();
        /** 从通道指定位置读取 **/
        fileChannel.position(0);
        try{
            ByteBuffer buffer1=ByteBuffer.allocate(5);
            ByteBuffer buffer2=ByteBuffer.allocate(5);
            /** 从缓冲区指定位置写入 **/
            buffer1.position(1);
            /** 从缓冲区指定位置写入 **/
            buffer2.position(1);
            ByteBuffer[] buffers=new ByteBuffer[]{buffer1,buffer2};

            /** 写入文件之前的fileChannel.position()位置 **/
            System.out.println ("fileChannel.position= " + fileChannel.position()) ;
            System.out.println ("A fileChannel.read= " +  fileChannel.read(buffers));
            /** 写入文件之后的fileChannel.position()位置 **/
            System.out.println ("fileChannel.position= " + fileChannel.position()) ;

            System.out.println(buffer1);
            System.out.println(new String(buffer1.array()));
            System.out.println(buffer2);
            System.out.println(new String(buffer2.array()));
            buffer1.clear();
            buffer2.clear();

            System.out.println ("A fileChannel.read= " +  fileChannel.read(buffers));

        }finally {
            readFile.close();
            fileChannel.close();
        }
    }

fileChannel.position= 0
A fileChannel.read= 8
fileChannel.position= 8
java.nio.HeapByteBuffer[pos=5 lim=5 cap=5]
 0001
java.nio.HeapByteBuffer[pos=5 lim=5 cap=5]
 0002
A fileChannel.read= -1    

线程同步案例

001/r/n
002/r/n
一行5个字节
@Test
    public void test_batchread2() throws Exception {
        RandomAccessFile readFile = new RandomAccessFile("write4.txt", "rw");
        FileChannel fileChannel = readFile.getChannel();
        try{
            IntStream.range(0,5).forEach(i->{
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            ByteBuffer buffer1=ByteBuffer.allocate(5);
                            ByteBuffer buffer2=ByteBuffer.allocate(5);
                            ByteBuffer[] buffers=new ByteBuffer[]{buffer1,buffer2};
                            long readLength = fileChannel.read(buffers);
                            while (readLength!=-1){
                                synchronized (ReadAndWriteMethodTest.class ){
                                    for (int i = 0; i < buffers.length; i++) {
                                        System.out.println(new String(buffers[i].array()));
                                    }

                                }
                                buffer1.clear();
                                buffer2.clear();
                                readLength = fileChannel.read(buffers);
                            }
                        } catch (IOException e) {
                        }
                    }
                });
                thread.start();
            });
        }finally {
        }
        Thread.sleep(3000);
        readFile.close();
        fileChannel.close();
    }

001

002

00a
    

9 read(ByteBuffer[] dsts, int offset, int length)

     * @param  dsts
     *         要写入的缓冲区数组
     *
     * @param  offset
     *         在缓冲区数组从哪个位置上缓冲区开始写入
     *
     * @param  length
     *         从offset开始,写入多少个缓冲区
     *
     * @return 从通道读取的字节数

将数据从此通道读取,写入到给定缓冲区数组子序列中(写入大小<=每个缓冲区容量(limit-position)之和)。

读取案例

文件内容

12345678efch
 @Test
    public void test_batchread3() throws Exception {
        RandomAccessFile readFile = new RandomAccessFile("write5.txt", "rw");
        FileChannel fileChannel = readFile.getChannel();
        /** 从文件指定位置读取 **/
        fileChannel.position(0);
        try{
            ByteBuffer buffer0=ByteBuffer.allocate(5);
            ByteBuffer buffer1=ByteBuffer.allocate(5);
            ByteBuffer buffer2=ByteBuffer.allocate(5);
            ByteBuffer buffer3=ByteBuffer.allocate(5);
            /** 从缓冲区指定位置写入 **/
            buffer1.position(1);
            /** 从缓冲区指定位置写入 **/
            buffer2.position(1);
            /** 从缓冲区指定位置写入 **/
            buffer3.position(2);
            ByteBuffer[] buffers=new ByteBuffer[]{buffer0,buffer1,buffer2,buffer3};

            System.out.println ("fileChannel.position= " + fileChannel.position()) ;
            System.out.println ("A fileChannel.read= " +  fileChannel.read(buffers,1,3));
            System.out.println ("fileChannel.position= " + fileChannel.position()) ;

            System.out.println(buffer1);
            System.out.println(new String(buffer1.array()));
            System.out.println(buffer2);
            System.out.println(new String(buffer2.array()));
            System.out.println(buffer3);
            System.out.println(new String(buffer3.array()));
            buffer1.clear();
            buffer2.clear();
            buffer3.clear();
        }finally {
            readFile.close();
            fileChannel.close();
        }
    }

fileChannel.position= 0
A fileChannel.read= 11
fileChannel.position= 11
java.nio.HeapByteBuffer[pos=5 lim=5 cap=5]
 1234
java.nio.HeapByteBuffer[pos=5 lim=5 cap=5]
 5678
java.nio.HeapByteBuffer[pos=5 lim=5 cap=5]
  efc    

线程通同步案例

@Test
    public void test_batchread4() throws Exception {
        RandomAccessFile readFile = new RandomAccessFile("write6.txt", "rw");
        FileChannel fileChannel = readFile.getChannel();
        try{
            IntStream.range(0,5).forEach(i->{
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            ByteBuffer buffer1=ByteBuffer.allocate(4);
                            ByteBuffer buffer2=ByteBuffer.allocate(4);
                            ByteBuffer[] buffers=new ByteBuffer[]{buffer1,buffer2};
                            long readLength = fileChannel.read(buffers,0,2);
                            while (readLength!=-1){
                                synchronized (ReadAndWriteMethodTest.class ){
                                    for (int i = 0; i < buffers.length; i++) {
                                        System.out.println(new String(buffers[i].array()));
                                    }

                                }
                                buffer1.clear();
                                buffer2.clear();
                                readLength = fileChannel.read(buffers);
                            }
                        } catch (IOException e) {
                        }
                    }
                });
                thread.start();
            });
        }finally {
        }
        Thread.sleep(3000);
        readFile.close();
        fileChannel.close();
    }

aaaa
bbbb
aaaa
bbbb
xxxx
yyyy
aaaa
bbbb

10 position(int newPosition)

position 表示写入读取通道起始位置

@Test
    public void test_position() throws Exception {
        RandomAccessFile readFile = new RandomAccessFile("write9.txt", "rw");
        RandomAccessFile writeFile = new RandomAccessFile("write9.txt", "rw");
        FileChannel fileChannel = readFile.getChannel();
        FileChannel fileChannel2 = writeFile.getChannel();
        try{
            /** 写入文件字节缓冲区数据 **/
            ByteBuffer buffer=ByteBuffer.wrap("--abcd".getBytes());
            buffer.position(2);
            /** 将缓冲区中position->limist 数据写入到文件设置position位置 **/
            System.out.println ("write() size= " + fileChannel.write(buffer)) ;
            System.out.println(fileChannel.position());
            System.out.println(fileChannel.size());
            /** 重置缓冲区 **/
            buffer.position(2);
            /** 将缓冲区中position->limist 数据写入到文件设置position位置 **/
            System.out.println ("write() size= " + fileChannel.write(buffer)) ;
            System.out.println(fileChannel.position());
            System.out.println(fileChannel.size());

            ByteBuffer allocate = ByteBuffer.allocate(8);
            fileChannel2.read(allocate);
            System.out.println(new String(allocate.array()));

        }finally {
            readFile.close();
            fileChannel.close();
        }
    }

write(ByteBuffer buffer, long position),read(ByteBuffer buffer, long position)操作时position不会移动

@Test
    public void test_position2() throws Exception {
        RandomAccessFile readFile = new RandomAccessFile("write10.txt", "rw");
        RandomAccessFile writeFile = new RandomAccessFile("write10.txt", "rw");
        FileChannel fileChannel = readFile.getChannel();
        FileChannel fileChannel2 = writeFile.getChannel();
        try{
            /** 写入文件字节缓冲区数据 **/
            ByteBuffer buffer=ByteBuffer.wrap("--abcd".getBytes());
            buffer.position(2);
            /** 将缓冲区中position->limist 数据写入到文件设置position位置 **/
            System.out.println ("write() size= " + fileChannel.write(buffer,fileChannel.position())) ;
            System.out.println(fileChannel.position());
            System.out.println(fileChannel.size());
            /** 重置缓冲区 **/
            buffer.position(2);
            /** 将缓冲区中position->limist 数据写入到文件设置position位置 **/
            System.out.println ("write() size= " + fileChannel.write(buffer,fileChannel.position())) ;
            System.out.println(fileChannel.position());
            System.out.println(fileChannel.size());

            ByteBuffer allocate = ByteBuffer.allocate(8);
            fileChannel2.read(allocate);
            System.out.println(new String(allocate.array()));

        }finally {
            readFile.close();
            fileChannel.close();
        }
    }

11 force(boolean metaData)

让缓冲区的数据写入磁盘时,如果metaData传人值为true ,则需要将文件元数据进行更改也写入磁盘

@Test
    public void test_force() throws Exception {
        RandomAccessFile writeFile = new RandomAccessFile("write12.txt", "rw");
        FileChannel fileChannel = writeFile.getChannel();
        try{
            /** 写入文件字节缓冲区数据 **/
            ByteBuffer buffer=ByteBuffer.wrap("1111111111".getBytes());
            long begin = System.currentTimeMillis();
            for (int i=0;i<=5000;i++){
                fileChannel.write(buffer);
                fileChannel.force(true);
                buffer.clear();
            }
            long end = System.currentTimeMillis();
            System.out.println(end-begin);


            ByteBuffer buffer1=ByteBuffer.wrap("22222222222".getBytes());
            begin = System.currentTimeMillis();
            for (int i=0;i<=5000;i++){
                fileChannel.write(buffer1);
                buffer1.clear();
            }
            end = System.currentTimeMillis();
            System.out.println(end-begin);


        }finally {
            writeFile.close();
            fileChannel.close();
        }
    }
上一篇 下一篇

猜你喜欢

热点阅读