Channel
: Channel 和 IO 中的 Stream(流)是差不多一个等级的。只不过 Stream 是单向的,譬如:InputStream, OutputStream。并且Channel是非阻塞式的。通道可以用来读取和写入数据,通道类似于之前的输入/输出流,但是程序不会直接操作通道的,所有的内容都是先读到或写入到缓冲区中,再通过缓冲区中取得获写入的。
此时读取分为两种情况:
通用的关闭流方法
//通用关闭流和通道的方法
//所有可以被关闭的流和通道都实现了Closeable接口
public static void close(Closeable closeable)
{
if(closeable!=null)
{
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//字节流拷贝文件实现
public static void noBufferStreamCopy(File src, File tar)
{
InputStream in=null;
OutputStream out=null;
try
{
in=new FileInputStream(src);
out=new FileOutputStream(tar);
//每次读取一个字节
Integer len;
//文件读取完毕返回-1
while((len=in.read())!=-1)
{
out.write(len);
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
close(in);
close(out);
}
}
//字节缓冲流拷贝文件实现
public static void bufferStreamCopy(File src,File tar)
{
BufferedInputStream bis=null;
BufferedOutputStream bos=null;
//使用装饰器模式
try {
bis = new BufferedInputStream(new FileInputStream(src));
bos=new BufferedOutputStream(new FileOutputStream(tar));
//准备一个缓存区,大小为1024个字节
byte[] buffer=new byte[1024];
int len;
//一次性读取1024个字节
while((len=bis.read(buffer))!=-1)
{
bos.write(buffer,0,len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
close(bis);
close(bos);
}
}
//FileChannel拷贝文件
public static void nioBufferCopy(File src,File tar)
{
FileChannel fin=null;
FileChannel fout=null;
try {
fin=new FileInputStream(src).getChannel();
fout=new FileOutputStream(tar).getChannel();
//准备一个缓冲区
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
while(fin.read(byteBuffer)!=-1)//将数据写入缓冲区,一次最多写入1024个字节
{
//将当前缓冲区从写模式转换为读模式
byteBuffer.flip();
//一直读取到缓冲区没有数据剩余为止
while (byteBuffer.hasRemaining())
{
//从缓冲区中读取数据,写入通道中
fout.write(byteBuffer);
}
//将当前缓冲区从读模式转换为写模式
byteBuffer.clear();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
close(fin);
close(fout);
}
}
//通道间传输完成文件拷贝
public static void nioTransferCopy(File src,File tar)
{
FileChannel fin=null;
FileChannel fout=null;
try {
fin=new FileInputStream(src).getChannel();
fout=new FileOutputStream(tar).getChannel();
//记录当前总共传输的字节数
Long transferredBytes= 0L;
//记录需要拷贝文件的字节总数
Long size=fin.size();
while(transferredBytes!=size)
{
//transferTo函数每次返回当前总共拷贝了多少个字节
transferredBytes+=fin.transferTo(0,size,fout);
}
} catch (IOException e) {
e.printStackTrace();
}
finally {
close(fin);
close(fout);
}
}
public class Main
{
public static void main(String[] args) {
final String prefix=System.getProperty("user.dir")+System.getProperty("file.separator");
File src=new File(prefix+"src.txt");
File tar=new File(prefix+"tar.txt");
//测试字节流拷贝文件
CopyFile.nioTransferCopy(src,tar);
}
public static class CopyFile
{
//字节流拷贝文件实现
public static void noBufferStreamCopy(File src, File tar)
{
InputStream in=null;
OutputStream out=null;
try
{
in=new FileInputStream(src);
out=new FileOutputStream(tar);
//每次读取一个字节
Integer len;
//文件读取完毕返回-1
while((len=in.read())!=-1)
{
out.write(len);
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
close(in);
close(out);
}
}
//字节缓冲流拷贝文件实现
public static void bufferStreamCopy(File src,File tar)
{
BufferedInputStream bis=null;
BufferedOutputStream bos=null;
//使用装饰器模式
try {
bis = new BufferedInputStream(new FileInputStream(src));
bos=new BufferedOutputStream(new FileOutputStream(tar));
//准备一个缓存区,大小为1024个字节
byte[] buffer=new byte[1024];
int len;
//一次性读取1024个字节
while((len=bis.read(buffer))!=-1)
{
bos.write(buffer,0,len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
close(bis);
close(bos);
}
}
//FileChannel拷贝文件
public static void nioBufferCopy(File src,File tar)
{
FileChannel fin=null;
FileChannel fout=null;
try {
fin=new FileInputStream(src).getChannel();
fout=new FileOutputStream(tar).getChannel();
//准备一个缓冲区
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
while(fin.read(byteBuffer)!=-1)//将数据写入缓冲区,一次最多写入1024个字节
{
//将当前缓冲区从写模式转换为读模式
byteBuffer.flip();
//一直读取到缓冲区没有数据剩余为止
while (byteBuffer.hasRemaining())
{
//从缓冲区中读取数据,写入通道中
fout.write(byteBuffer);
}
//将当前缓冲区从读模式转换为写模式
byteBuffer.clear();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
close(fin);
close(fout);
}
}
//通道间传输完成文件拷贝
public static void nioTransferCopy(File src,File tar)
{
FileChannel fin=null;
FileChannel fout=null;
try {
fin=new FileInputStream(src).getChannel();
fout=new FileOutputStream(tar).getChannel();
//记录当前总共传输的字节数
Long transferredBytes= 0L;
//记录需要拷贝文件的字节总数
Long size=fin.size();
while(transferredBytes!=size)
{
//transferTo函数每次返回当前总共拷贝了多少个字节
transferredBytes+=fin.transferTo(0,size,fout);
}
} catch (IOException e) {
e.printStackTrace();
}
finally {
close(fin);
close(fout);
}
}
}
//通用关闭流和通道的方法
//所有可以被关闭的流和通道都实现了Closeable接口
public static void close(Closeable closeable)
{
if(closeable!=null)
{
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
对于小文件拷贝而言,nio优势也还可以,对于大文件而言,nio的优势相对比较明显,并且大家要注意缓冲区大小的选择
在Selector上面注册三个Channel
channel可以在上面四个状态中来回切换
SelectionKey:该对象可以作为当前注册在selector上的channel的唯一标识,通过这个对象也可以获取到当前channel的一些信息
下面展示SelectionKey对象的一些方法:
通过select()函数可以返回当前处于可操作状态下的channel
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/m0_53157173/article/details/121767106
内容来源于网络,如有侵权,请联系作者删除!