一、JavaNIO读取文件
1、使用缓冲区,非直接缓冲区读写文件
@Test
public void test3() {
FileInputStream fis = null;
FileOutputStream fos = null;
FileChannel fisChannel = null;
FileChannel fosChannel = null;
try {
// ServerSocketChannel open = ServerSocketChannel.open();
fis = new FileInputStream("1.jpg");
fos = new FileOutputStream("2.jpg");
fisChannel = fis.getChannel();
fosChannel = fos.getChannel();
// 分配指定大小的缓冲区
ByteBuffer buf = ByteBuffer.allocateDirect(1024);
// 将通道中的数据存取缓冲区
while (fisChannel.read(buf) != -1) {
// 读取信息
buf.flip();
fosChannel.write(buf);
buf.clear();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (fosChannel != null) {
try {
fosChannel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (fisChannel != null) {
try {
fisChannel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
2、使用直接缓冲区读写文件,速度快,不建议使用,占内存
@Test
public void test4() throws IOException {
// 读模式
FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
// StandardOpenOption.CREATE没有就创建,有就覆盖,StandardOpenOption.CREATE_NEW有就报错
FileChannel outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE, StandardOpenOption.READ,
StandardOpenOption.CREATE);
// 内存映射文件和ByteBuffer.allocateDirect(1024);直接获取缓冲区一模一样
// 缓存区目前在物理内存中,直接缓冲区只有ByteBuffer支持
MappedByteBuffer map = inChannel.map(MapMode.READ_ONLY, 0, inChannel.size());
MappedByteBuffer map2 = outChannel.map(MapMode.READ_WRITE, 0, inChannel.size());
// 直接操作缓冲区
byte[] bs = new byte[map.limit()];
map.get(bs);
map2.put(bs);
}
3、分散与读取,将通道中的内容分散到缓冲区中
/**
* 分散与读取,将通道中的内容分散到缓冲区中
*
* @throws FileNotFoundException
*/
@Test
public void test6() throws Exception {
// 分散读取
RandomAccessFile raf = new RandomAccessFile("1.txt", "rw");
// 获取通道
FileChannel channel = raf.getChannel();
// 分配指定大小缓冲区
ByteBuffer allocate = ByteBuffer.allocate(100);
ByteBuffer allocate2 = ByteBuffer.allocate(1000);
// 分散读取
ByteBuffer[] bio = { allocate, allocate2 };
channel.read(bio);
for (ByteBuffer byteBuffer : bio) {
// 改编读模式
byteBuffer.flip();
}
// 将缓冲区转换为数组,从第0个转换到limit
System.out.println(new String(bio[0].array(), 0, bio[0].limit()));
System.out.println("======================");
System.out.println(new String(bio[0].array(), 0, bio[1].limit()));
// 聚集写入
RandomAccessFile rsf = new RandomAccessFile("2.txt", "rw");
FileChannel channel2 = rsf.getChannel();
channel2.write(bio);
}
/**
* 通道之间传输数据,直接缓冲区复制文件
*
* @throws IOException
*/
@Test
public void test5() throws IOException {
// 读模式
FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
// StandardOpenOption.CREATE没有就创建,有就覆盖,StandardOpenOption.CREATE_NEW有就报错
FileChannel outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE, StandardOpenOption.READ,
StandardOpenOption.CREATE);
// 从哪到哪去
inChannel.transferTo(0, inChannel.size(), outChannel);
outChannel.transferFrom(inChannel, 0, inChannel.size());
inChannel.close();
outChannel.close();
}
/**
* 直接缓冲区进行文件费复制
*
* @throws IOException
*/
@Test
public void test4() throws IOException {
// 读模式
FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
// StandardOpenOption.CREATE没有就创建,有就覆盖,StandardOpenOption.CREATE_NEW有就报错
FileChannel outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE, StandardOpenOption.READ,
StandardOpenOption.CREATE);
// 内存映射文件和ByteBuffer.allocateDirect(1024);直接获取缓冲区一模一样
// 缓存区目前在物理内存中,直接缓冲区只有ByteBuffer支持
MappedByteBuffer map = inChannel.map(MapMode.READ_ONLY, 0, inChannel.size());
MappedByteBuffer map2 = outChannel.map(MapMode.READ_WRITE, 0, inChannel.size());
// 直接操作缓冲区
byte[] bs = new byte[map.limit()];
map.get(bs);
map2.put(bs);
}
/**
* 非直接缓冲区实现文件复制
*/
@Test
public void test3() {
FileInputStream fis = null;
FileOutputStream fos = null;
FileChannel fisChannel = null;
FileChannel fosChannel = null;
try {
// ServerSocketChannel open = ServerSocketChannel.open();
fis = new FileInputStream("1.jpg");
fos = new FileOutputStream("2.jpg");
fisChannel = fis.getChannel();
fosChannel = fos.getChannel();
// 分配指定大小的缓冲区
ByteBuffer buf = ByteBuffer.allocateDirect(1024);
// 将通道中的数据存取缓冲区
while (fisChannel.read(buf) != -1) {
// 读取信息
buf.flip();
fosChannel.write(buf);
buf.clear();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.close();
}
if (fis != null) {
fis.close();
}
if (fosChannel != null) {
fosChannel.close();
}
if (fisChannel != null) {
fisChannel.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Test
public void test1() {
ByteBuffer buf = ByteBuffer.allocate(1024);
// 可以操作数据的位置
System.out.println(buf.position());
// 可以操作数据的大小
System.out.println(buf.limit());
// 最大储存容量
System.out.println(buf.capacity());
String string = "asd";
buf.put(string.getBytes());
// 切换到读取数据模式
buf.flip();
// 可重复读数据
buf.rewind();
buf.clear();
// 标记位置
buf.mark();
// 回复到标记位置
buf.reset();
// 判断缓冲区中是否还有缓冲数据,如果有
if (buf.hasRemaining()) {
// 获取缓冲区中可以操作的数量
System.out.println(buf.remaining());
}
}