使用FileChannel读取下载文件
使用FileChannel读取下载文件
- 前言
- 一、FileChannel是什么?
- 二、FileChannal的方法介绍
-
- 1.open
- 2.read
- 3.write
- 4.lock()与tryLock()
- 三、FileChannel下载网络图片
- 总结
- 参考链接
前言
FileChannal的理解和使用场景
对于文件的复制,平时我们都是使用输入输出流进行操作,利用源文件创建出一个输入流,然后利用目标文件创建出一个输出流,最后将输入流的数据读取写入到输出流中。这样也是可以进行操作的。但是利用fileChannel是很有用的一个方式。它能直接连接输入输出流的文件通道,将数据直接写入到目标文件中去。而且效率更高。
1.多线程情况下读取文件流
2.特定的大文件的读取等操作
一、FileChannel是什么?
FileChannel是通过创建channal 通道,操作一个文件。除了有读写操作之外,还有裁剪特定大小文件truncate(),强制在内存中的数据刷新到硬盘中去force(),对通道上锁lock()等功能
二、FileChannal的方法介绍
1.open
创建一个文件,并且返回一个channal,允许我们进入文件,对文件进行读写操作。
FileChannel.open(new File("D:\\hello.txt").toPath(), StandardOpenOption.CREATE_NEW);
StandardOpenOption 包含多种文件操作属性,比如:
READ(读),WRITE(写),SYNC/DSYNC (同步或异步IO)
当然,我们还可以通过FileOutputStream 文件流直接获取channal
File file=new File("D:\\hello.txt");FileOutputStream fileOutputStream = new FileOutputStream(file);FileChannel channel = fileOutputStream.getChannel();
2.read
代码如下(示例):
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);//读取1024字节内容到byteBuffer钟fileChannel.read(byteBuffer);
3.write
代码如下(示例):
//写数据到channelfileChannelOutput.write(byteBuffer);
4.lock()与tryLock()
lock()与tryLock()方法都是尝试去获取在某一文件上的独有锁(以下简称独有锁),可以实现进程间操作的互斥。区别在于lock()会阻塞(blocking)方法的执行,tryLock()则不会。
测试代码:
private void processLockTest() { try { File file = new File(getFilesDir().getAbsolutePath() + File.separator + "lock.lock"); FileOutputStream fos = new FileOutputStream(file); FileLock fl = null; boolean loop = true; int time = 0; LogUtil.log(android.os.Process.myPid() + " " + "while start" + " " + file.getAbsolutePath()); while (loop) { time++; LogUtil.log(android.os.Process.myPid() + " " + "loop 次数:" + time); if (fl == null) { LogUtil.log(android.os.Process.myPid() + " " + "tryLock before" + " " + file.getAbsolutePath()); try { fl = fos.getChannel().tryLock(); } catch (Exception e) { e.printStackTrace(); LogUtil.log(android.os.Process.myPid() + " " + "tryLock IOException" + " " + e.toString()); } LogUtil.log(android.os.Process.myPid() + " " + "tryLock after" + " " + file.getAbsolutePath()); } if (fl != null) { while (loop) { Thread.sleep(2000); time++; if (time == 5) { fl.release(); } if (time == 10) { loop = false; } if (fl != null) { LogUtil.log(System.currentTimeMillis() + " " + android.os.Process.myPid() + " " + "got"); } else { LogUtil.log(System.currentTimeMillis() + " " + android.os.Process.myPid() + " " + "fl is null"); } } } else { LogUtil.log(System.currentTimeMillis() + " " + android.os.Process.myPid() + " " + "ungot"); } Thread.sleep(2000); } LogUtil.log(android.os.Process.myPid() + " " + "while over"); } catch (Throwable t) { }}
三、FileChannel下载网络图片
该处使用的url网络请求的数据。
/** * * @param uri 网络图片地址 * @param filePath 下载目录 * @param fileName 下载文件名 */ public static void downLoadImage(String uri, String filePath,String fileName) { ReadableByteChannel readableByteChannel = null; FileChannel fileChannel = null; File file; URL url; FileOutputStream fileOutputStream = null; try { url = new URL(uri); //首先从 URL stream 中创建一个 ReadableByteChannel 来读取网络文件 readableByteChannel = Channels.newChannel(url.openStream()); String path = filePath + fileName; file = new File(path); if (!file.getParentFile().exists() && !file.getParentFile().isDirectory()) { file.getParentFile().mkdirs(); } //通过 ReadableByteChannel 读取到的字节会流动到一个 FileChannel 中,然后再关联一个本地文件进行下载操作 fileOutputStream = new FileOutputStream(file); fileChannel = fileOutputStream.getChannel(); //最后用 transferFrom()方法就可以把 ReadableByteChannel 获取到的字节写入本地文件 fileChannel.transferFrom(readableByteChannel, 0, Long.MAX_VALUE); } catch (Exception e) { e.printStackTrace(); } finally { try { if (null != readableByteChannel) { readableByteChannel.close(); } if (null != fileChannel) { fileChannel.close(); } if (null != fileOutputStream) { fileOutputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } }
测试下载图片
public static void main(String[] args) throws IOException { String fileUrl = "https://img.pconline.com.cn/images/upload/upc/tx/itbbs/1308/16/c8/24543026_1376637095791_mthumb.jpg"; downLoadImage(fileUrl,"D:/test/","hello.jpg"); }
总结
利用filechannel使用的时间比普通的读取输入时间缩短了将近一半。尤其是在进行大文件复制的时候,filechannel显得更加有优势
参考链接
链接:
Java之FileChannel类的理解和使用.姚镜堂
ava之FileChannel类的理解和使用 -----java 流NIO的使用.fight_man001