本篇文章主要介绍java8之nio相关的编码级的设置,以及通道channels的使用,如何利用通道直接复制文件等,欢迎大家交流讨论!不多说作为码农直接上代码…
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.junit.Test;
/*
* 一、通道(Channel):用于源节点与目标节点的连接。在 Java NIO 中负责缓冲区中数据的传输。Channel 本身不存储数据,因此需要配合缓冲区进行传输。
*
* 二、通道的主要实现类
* java.nio.channels.Channel 接口:
* |--FileChannel
* |--SocketChannel
* |--ServerSocketChannel
* |--DatagramChannel
*
* 三、获取通道
* 1. Java 针对支持通道的类提供了 getChannel() 方法
* 本地 IO:
* FileInputStream/FileOutputStream
* RandomAccessFile
*
* 网络IO:
* Socket
* ServerSocket
* DatagramSocket
*
* 2. 在 JDK 1.7 中的 NIO.2 针对各个通道提供了静态方法 open()
* 3. 在 JDK 1.7 中的 NIO.2 的 Files 工具类的 newByteChannel()
*
* 四、通道之间的数据传输
* transferFrom()
* transferTo()
*
* 五、分散(Scatter)与聚集(Gather)
* 分散读取(Scattering Reads):将通道中的数据分散到多个缓冲区中
* 聚集写入(Gathering Writes):将多个缓冲区中的数据聚集到通道中
*
* 六、字符集:Charset
* 编码:字符串 -> 字节数组
* 解码:字节数组 -> 字符串
*
*/
public class Nio02 {
//字符集如何对字符进行编码与解码
@Test
public void test06(){
Charset charset=Charset.forName("GBK");
//获取编码器 解码器
CharsetEncoder encoder=charset.newEncoder();
CharsetDecoder decoder=charset.newDecoder();
CharBuffer ch=CharBuffer.allocate(1024);
ch.put("倒萨大法师帝国时代");
ch.flip();
//进行编码
try {
ByteBuffer by=encoder.encode(ch);
for(int i=0;i<18;i++){
System.out.println(by.get());
}
//解码
by.flip();
CharBuffer charb=decoder.decode(by);
System.out.println(charb.toString());
System.out.println("-----------------------------");
Charset ut=Charset.forName("UTF-8");
by.flip();
CharBuffer ch3=ut.decode(by);
System.out.println(ch3.toString());
} catch (CharacterCodingException e) {
e.printStackTrace();
}
}
//编码集 获取本地系统所支持的所有编码集
@Test
public void test05(){
Map<String, Charset> chare=Charset.availableCharsets();
Set<Entry<String,Charset>> set=chare.entrySet();
for(Entry<String, Charset> enMap:set){
System.out.println(enMap.getKey()+"--"+enMap.getValue());
}
}
//分散和聚集 将通道中的数据依次按顺序写入到多个缓冲区中 (聚集则相反)
@Test
public void test04() throws IOException{
try {
@SuppressWarnings("resource")
RandomAccessFile rAccessFile=new RandomAccessFile("1.txt", "rw");
//获取通道
FileChannel fChannel=rAccessFile.getChannel();
//分配指定的缓冲区
ByteBuffer buffer=ByteBuffer.allocate(200);
ByteBuffer buffer1=ByteBuffer.allocate(1024);
//分散读取
ByteBuffer[] byteBuffer={buffer,buffer1};
fChannel.read(byteBuffer);
for (ByteBuffer by : byteBuffer) {
//切换到读取模式
by.flip();
}
System.out.println(new String(byteBuffer[0].array(), 0, byteBuffer[0].limit()));
System.out.println("-----------------");
System.out.println(new String(byteBuffer[1].array(), 0, byteBuffer[1].limit()));
//聚集写入
@SuppressWarnings("resource")
RandomAccessFile wrAccessFile=new RandomAccessFile("2.txt", "rw");
//获取通道
FileChannel wChannel=wrAccessFile.getChannel();
wChannel.write(byteBuffer);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
//通道之间的数据传输(直接缓冲区)
@Test
public void test03(){
try {
FileChannel iChannel=FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
FileChannel oChannel=FileChannel.open(Paths.get("4.jpg"), StandardOpenOption.WRITE, StandardOpenOption.CREATE,StandardOpenOption.READ);
//下面这两个方法是相对应的 即从哪儿来 要到哪儿去
//iChannel.transferTo(0, iChannel.size(), oChannel);
oChannel.transferFrom(iChannel, 0, iChannel.size());
} catch (IOException e) {
e.printStackTrace();
}
//内存映射文件 相当于ByteBuffer.allocateDirect(1024)
}
//利用直接缓冲区完成文件复制(内存映射文件)
@Test
public void test02(){
try {
//读取文件 并放入通道
FileChannel iChannel=FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
FileChannel oChannel=FileChannel.open(Paths.get("3.jpg"), StandardOpenOption.WRITE, StandardOpenOption.CREATE,StandardOpenOption.READ);
//内存映射文件 相当于ByteBuffer.allocateDirect(1024)
MappedByteBuffer iBuffer=iChannel.map(MapMode.READ_ONLY, 0, iChannel.size());
MappedByteBuffer oBuffer=oChannel.map(MapMode.READ_WRITE, 0, iChannel.size());
//直接对缓冲区进行读写操作
byte[] by=new byte[iBuffer.limit()];
iBuffer.get(by);
oBuffer.put(by);
iChannel.close();
oChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//利用通道完成文件复制
@Test
public void test01() throws IOException{
FileInputStream inputStream=null;;
FileOutputStream outputStream=null;
FileChannel inChannel = null;
FileChannel outChannel=null;
//利用通道完成文件辅助
try {
inputStream=new FileInputStream("1.jpg");
outputStream=new FileOutputStream("2.jpg");
//获取通道
inChannel = inputStream.getChannel();
outChannel = outputStream.getChannel();
//分配制定大小的缓冲区
ByteBuffer byteBuffer=ByteBuffer.allocate(1024);
//将通道的数据存入缓冲区
while (inChannel.read(byteBuffer) !=-1) {
//切换读取数据模式
byteBuffer.flip();
//将缓冲区数据写入通道
outChannel.write(byteBuffer);
//关闭缓冲区
byteBuffer.clear();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally{
if(outChannel!=null){
try {
inChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(inChannel!=null){
try {
outChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(outputStream!=null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}