NIO读写文件

以下是使用NIO读写文件的demo

package com.example.demo;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class DealMediaDownload {
	
	static String txtUrl = "C:/Users/admin/Desktop/upFile/123.txt";
	static String saveTxtFile = "C:/Users/admin/Desktop/upFile/1213.txt";
	
	static String mediaUrl="C:/Users/admin/Desktop/upFile/1.mp4";
	static String saveMediaFile="C:/Users/admin/Desktop/upFile/11.mp4";
	
	public static void main(String[] args) {
		//ReadNIO(mediaUrl,saveMediaFile);
		ReadWriteNIO(txtUrl,saveTxtFile);
	}
	
	private static void ReadWriteNIO(String url,String targetUrl) {
		try (FileInputStream fis = new FileInputStream(url);
				FileOutputStream fos =new FileOutputStream(targetUrl,true); //true 是使得写入文件时不进行覆盖,而是追加内容
				FileChannel fi = fis.getChannel();
				FileChannel fo = fos.getChannel();
				){
			
			ByteBuffer bb = ByteBuffer.allocate(1024);
			System.out.println("限制是: " + bb.limit() + ", 容量是: " + bb.capacity() + ", 位置是: " + bb.position());
			
			int length =0;
			int i=0;
			/**
			 * 1.fi.read(bb) 通道读取文件数据存放到buffer缓存区中
			 * 2.bb.flip() 将缓冲区从写模式切换到读模式,主要是实现缓存区的指针位置从1023位回复到0位,以便从头开始读
			 * 3.fo.write(bb) 通道从buffer缓存区中读取数据写入到文件
			 * 4.bb.clear() 从读模式切换到写模式,不会清空数据,但后续写数据会覆盖原来的数据,即使有部分数据没有读,也会被遗忘; 
			 * 5. bb.compact() 从读数据切换到写模式,不会清空数据,会将所有未读的数据copy到缓冲区头部,后续写数据不会覆盖,而是在这些数据之后写数据
			 * **注:byteBuffer属性有 position,limit,capacity,在写入数据,比如写入10个长度的数据,position和limit值为10,capacity不变,使用flip()方法能使的postion=0,但是limit不改变,当从缓存区读取时,每次读取到limit的位置就结束了,无法充分利用整个缓存区,当读写使用同一个缓存区时,在写入数据后需调用clear()方法,清楚调limit的限制。**
			 */
			while((length=fi.read(bb))!=-1) {
				bb.flip();
				fo.write(bb);
				bb.compact();
				i++;
				
			}
			System.out.println("循环次数:"+i);
			System.out.println("完成");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
}


1.这一步其实是当我们刚开始初始化这个buffer数组的时候,开始默认是这样的
NIO读写文件_第1张图片
2、但是当你往buffer数组中开始写入的时候几个字节的时候就会变成下面的图,position会移动你数据的结束的下一个位置,这个时候你需要把buffer中的数据写到channel管道中,所以此时我们就需要用这个buffer.flip();方法,

NIO读写文件_第2张图片
3、当你调用完2中的方法时,这个时候就会变成下面的图了,这样的话其实就可以知道你刚刚写到buffer中的数据是在position—->limit之间,然后下一步调用clear();
NIO读写文件_第3张图片

4、这时底层操作系统就可以从缓冲区中正确读取这 5 个字节数据发送出去了。在下一次写数据之前我们在调一下 clear() 方法。缓冲区的索引状态又回到初始位置。(其实这一步有点像IO中的把转运字节数组 char[] buf = new char[1024]; 不足1024字节的部分给强制刷新出去的意思)

以下是NIO读取网络视频的demo(已修正可用)

public static void httpDownload(String httpUrl, String saveFile) {
		try (FileOutputStream fos =new FileOutputStream(saveFile,false);
				FileChannel fi = fos.getChannel();){
			URL url = new URL(httpUrl);
			URLConnection  conn = url.openConnection();
			conn.connect();
			ByteBuffer bb = ByteBuffer.allocate(2048);
			InputStream is = conn.getInputStream();
			int byteRead;
			//BufferedInputStream bis = new BufferedInputStream(is);
			byte[] b = new byte[2048];
			int j = 0;
			
			while((byteRead=is.read(b))!=-1) {
				System.out.print(b[2047]+",");
				//注:可能是视频的缘故,不允许有多的空数据,在put的时候需要指定数组是从start到end,防止空数据
				//不然下载的视频无法播放
				bb.put(b,0,byteRead);
				bb.flip();
				fi.write(bb);
				bb.clear();
				j++;
			}
			System.out.println("循环次数:"+j);
			fos.flush();
			System.out.println("done!");
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

以下是用IO读写视频

public static void httpDownload(String httpUrl, String saveFile) {
        // 1.下载网络文件
        try {
        	long start = System.currentTimeMillis();
        	 int byteRead;
        	 URL url= new URL(httpUrl);
            //2.获取链接
            URLConnection conn = url.openConnection();
            //3.输入流
            InputStream inStream = conn.getInputStream();
            //3.写入文件
            FileOutputStream fs = new FileOutputStream(saveFile);
            byte[] buffer = new byte[2048];
            int i=0;
            while ((byteRead = inStream.read(buffer)) != -1) {
            	System.out.print(buffer[2047]+",");
                fs.write(buffer, 0, byteRead);
                i++;
            }
            System.out.println("循环次数:"+i);
            inStream.close();
            fs.close();
            System.out.println("完成");
        } catch (IOException  e) {
            e.printStackTrace();
            System.out.println("失败");
        }
    }

你可能感兴趣的:(NIO读写文件)