JavaIO 使用缓冲字节流和文件字节流拷贝文件

文件字节流复制文件的原理是:读取一个个字节(或者字节数组),然后再写入文件中去。

缓冲字节流复制文件的原理是:读取一个个字节(或者字节数组)放到缓冲字节数组中,等到缓冲字节数组读满后,再把这几次读取到的字节一并写到文件中去。这样使用缓冲字节流,就能少写几次文件,进而节省时间

测试代码:

(1)批量读取比较:

public class TestBuffered_File
{
	public static void copyFileBufferd(File srcFile,File destFile,int bufsize) throws IOException
	{
		if(!srcFile.exists())
		{
			throw new FileNotFoundException("文件"+srcFile+"不存在");
		}
		if(!srcFile.isFile())
		{
			throw new IllegalArgumentException(srcFile+"不是文件");
		}
		//创建缓冲字节流对象,内部缓冲设置为bufSize
		BufferedInputStream in=new BufferedInputStream(
				new FileInputStream(srcFile),bufsize);
		BufferedOutputStream out=new BufferedOutputStream(
				new FileOutputStream(destFile),bufsize);
		int size=0;
		byte[] buffer=new byte[512];
		//读到字节串到内部缓存,默认缓冲区的大小是8192字节
		while((size=in.read(buffer))!=-1)
		{
			out.write(buffer,0,size);//把读取到的字节串写入到缓冲区,缓冲区写满会自动写入文件
//			out.flush();//刷新缓冲区写入文件
		}
		out.flush();//刷新缓冲区写入文件
		in.close();
		out.close();
	}
	/**
	 * 使用FileInputStream和FileOutputStream 按字节数组拷贝文件
	 * @param srcFile 源文件File对象
	 * @param targetFile 目标文件File对象
	 * @throws IOException
	 */
	public static void copyFileByBytes(File srcFile,File targetFile) throws IOException
	{
		if(!srcFile.exists())
		{
			throw new IllegalArgumentException( srcFile+"文件不存在");
		}
		if(!srcFile.isFile())
		{
			throw new IllegalArgumentException( srcFile+"不是文件");
		}
		FileInputStream in=new FileInputStream(srcFile);
		FileOutputStream out=new FileOutputStream(targetFile);
		byte[] buf=new byte[512];
		int size=0;
		while((size=in.read(buf, 0, buf.length))!=-1)
		{
			out.write(buf, 0, size);
			out.flush();//刷新写入文件中去。
		}
		in.close();
		out.close();
		
	}
	/**
	 * 把时间戳(long 毫秒数)转换为格式化时间字符串
	 * @param timeStamp long毫秒数
	 * @return 格式化时间字符串
	 */
	public static String timeStampToDateString(long timeStamp)
	{
		Date date = new Date(timeStamp);
		/*
			m  小时中的分钟数 
			s  分钟中的秒数  
			S  毫秒数  
		 */
		DateFormat format = new SimpleDateFormat("mm:ss:SS");
		String dateString=format.format(date);
		return dateString;
	}
	public static void main(String[] args)
	{
		String packagePath;
		try
		{
			//使用缓冲字节流拷贝文件
			long start=System.currentTimeMillis();//获取当前的时间戳
			packagePath = FilePath.getSrcPackagePath(TestBufferedCopy.class);
			copyFileBufferd(new File(packagePath+"李玉刚_刚好遇见你.mp3"),
					new File(packagePath+"李玉刚_刚好遇见你副本4.mp3"),1024*10);
			long end=System.currentTimeMillis();//获取复制后的时间戳
			
			System.out.println("使用缓冲字节流(每次读取字节数组512)拷贝文件用时(分钟:秒:毫秒):"
						+timeStampToDateString(end-start));
			//使用文件字节流,按字节数组拷贝文件
			start=System.currentTimeMillis();
			copyFileByBytes(new File(packagePath+"李玉刚_刚好遇见你.mp3"),
					new File(packagePath+"李玉刚_刚好遇见你副本5.mp3"));
			end=System.currentTimeMillis();
			System.out.println("使用文件字节流(每次读取字节数组512)拷贝文件用时(分钟:秒:毫秒):"
						+timeStampToDateString(end-start));
		
		} catch (UnsupportedEncodingException e1)
		{
			e1.printStackTrace();
		} catch (IOException e)
		{
			e.printStackTrace();
		}
	}
}

运行结果:

使用缓冲字节流(每次读取字节数组512)拷贝文件用时(分钟:秒:毫秒):00:00:34
使用文件字节流(每次读取字节数组512)拷贝文件用时(分钟:秒:毫秒):00:00:101

可见,每次读取相同的字节数组的条件下,缓冲字节流多了缓冲,进而减少写入文件的次数,从而比文件字节流用时少。

(2)逐个字节读取比较:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.lan.filepath.FilePath;

public class TestBuffered_FileByByte
{
	public static void copyFileBufferdByByte(File srcFile, File destFile, int bufsize)
			throws IOException
	{
		if (!srcFile.exists())
		{
			throw new FileNotFoundException("文件" + srcFile + "不存在");
		}
		if (!srcFile.isFile())
		{
			throw new IllegalArgumentException(srcFile + "不是文件");
		}
		// 创建缓冲字节流对象,内部缓冲设置为bufSize
		BufferedInputStream in = new BufferedInputStream(
				new FileInputStream(srcFile), bufsize);
		BufferedOutputStream out = new BufferedOutputStream(
				new FileOutputStream(destFile), bufsize);
		int size = 0;
		// 读到字节串到内部缓存,默认缓冲区的大小是8192字节
		while ((size = in.read()) != -1)
		{
			out.write(size);// 把读取到的字节写入到缓冲区,缓冲区写满会自动写入文件
		}
		out.flush();// 刷新缓冲区写入文件
		in.close();
		out.close();
	}
	/**
	 * 使用FileInputStream和FileOutputStream 按字节数组拷贝文件
	 * 
	 * @param srcFile
	 *            源文件File对象
	 * @param targetFile
	 *            目标文件File对象
	 * @throws IOException
	 */
	public static void copyFileByByte(File srcFile, File targetFile)
			throws IOException
	{
		if (!srcFile.exists())
		{
			throw new IllegalArgumentException(srcFile + "文件不存在");
		}
		if (!srcFile.isFile())
		{
			throw new IllegalArgumentException(srcFile + "不是文件");
		}
		FileInputStream in = new FileInputStream(srcFile);
		FileOutputStream out = new FileOutputStream(targetFile);
		int size = 0;
		while ((size = in.read()) != -1)
		{
			out.write(size);
		}
		in.close();
		out.close();

	}
	/**
	 * 把时间戳(long 毫秒数)转换为格式化时间字符串
	 * 
	 * @param timeStamp
	 *            long毫秒数
	 * @return 格式化时间字符串
	 */
	public static String timeStampToDateString(long timeStamp)
	{
		Date date = new Date(timeStamp);
		/*
		 * m 小时中的分钟数 s 分钟中的秒数 S 毫秒数
		 */
		DateFormat format = new SimpleDateFormat("mm:ss:SS");
		String dateString = format.format(date);
		return dateString;
	}
	public static void main(String[] args)
	{
		String packagePath;
		try
		{
			// 使用缓冲字节流拷贝文件
			long start = System.currentTimeMillis();// 获取当前的时间戳
			packagePath = FilePath.getSrcPackagePath(TestBufferedCopy.class);
			copyFileBufferdByByte(new File(packagePath + "李玉刚_刚好遇见你.mp3"),
					new File(packagePath + "李玉刚_刚好遇见你副本6.mp3"), 1024 * 10);
			long end = System.currentTimeMillis();// 获取复制后的时间戳

			System.out.println("使用缓冲字节流(逐个字节)拷贝文件用时(分钟:秒:毫秒):"
					+ timeStampToDateString(end - start));
			// 使用文件字节流,按字节数组拷贝文件
			start = System.currentTimeMillis();
			copyFileByByte(new File(packagePath + "李玉刚_刚好遇见你.mp3"),
					new File(packagePath + "李玉刚_刚好遇见你副本7.mp3"));
			end = System.currentTimeMillis();
			System.out.println("使用文件字节流(逐个字节)拷贝文件用时(分钟:秒:毫秒):"
					+ timeStampToDateString(end - start));

		} catch (UnsupportedEncodingException e1)
		{
			e1.printStackTrace();
		} catch (IOException e)
		{
			e.printStackTrace();
		}
	}
}

运行结果:

使用缓冲字节流(逐个字节)拷贝文件用时(分钟:秒:毫秒):00:00:279
使用文件字节流(逐个字节)拷贝文件用时(分钟:秒:毫秒):00:35:982

可以看到逐个字节逐个字节的来拷贝文件,使用文件字节流要读一个字节写一个字节,耗时很大。虽然也是每次读取一个字节一个字节的读取,但是使用缓冲字节流读取满缓冲,才写一次文件,也就是读取1024 * 10次,才写一次文件。相比于使用文件字节流节省了1024 * 10-1次写文件的操作。这样就节省更多的时间。

总结:

(1) 如果使用文件字节流,复制文件,每次读取一个数组,写一个数组,比每次读取一个字节,写一个字节更快。

(2) 使用缓冲字节流比文件字节流更快(多分配内存(缓冲)):每次读取一个数组放到一个大的数组中去(缓冲),然后大的数组(缓冲)满了再一次性写入。



你可能感兴趣的:(java)