1 FileChannel 概述
- FileChannel 类的主要作用是读取、写入、映射和操作文件的通道。该通道永远是阻塞
的操作。 - FileChannel 类在内部维护当前文件的position ,可对其进行查询和修改。
2 FileChannel 类结构
image核心功能
1 读取、写入和关闭通道文件。
2 以不影响通道当前位置(position)的方式,对文件中绝对位置的字节进行读取或写人。
3 MMAP,将文件中的某个区域直接映射到程序用户态内存中(用户态)。对于较大的文件,这通常比调用普通的 read ()或write ()方法更为高效。
4 强制对底层存储设备进行文件的更新(内存刷入磁盘),确保在系统崩溃时不丢失数据。
5 SendFile 零拷贝文件数据读写拷贝
6 可以锁定某个文件区域,以阻止其他程序对其进行访问。
7 多个并发线程可安全地使用文件通道。
3 核心API 使用
1 write(ByteBuffer buffer)
从给定缓冲区读取能数据(limit-position),从通道设置position位置写入。
- position > file.size 写入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位置写入。
- position > file.size 写入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),写入到给定的缓冲区中
- position > fileChannel.size 相当于不写入。
- 通道中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),写入到给定的缓冲区中。
- position > fileChannel.size 相当于不写入。
- 通道中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写入,
- position > file.size 写入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
...省略
6 write(ByteBuffer[] srcs, int offset, int length)
从给定缓冲区数组子序列读取数据(每个缓冲区写入数据=limit-position),从通道指定位置写入
@param srcs 写入通道字节缓冲区数组
@param offset 在缓冲区数组从哪个位置上缓冲区开始读取
@param length 从offset开始,读取多少个缓冲区
@return 通道写入的字节数
- position > file.size 写入position之前位置补空位。
- 通道中position伴随写入而移动。
- 多线程同步
写入案例
@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偏移,多线程同步
- position > file.size 写入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)之和)
- position > fileChannel.size 相当于不写入。
- 通道中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)之和)。
- position > fileChannel.size 相当于不写入。
- 通道中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 表示写入读取通道起始位置
- write(ByteBuffer buffer),read(ByteBuffer buffer)操作时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();
}
}
网友评论