【Java学习笔记】IO流之字节流

目录

1.IO流的概述

2.IO流分类

2.1 按照数据流向

2.2 按照数据类型

3.IO流常用基类

3.1 字节流的抽象基类

3.2 字符流的抽象基类

4.字节输出流FileOutputStream

4.1 FileOutputStream的构造方法

4.2 字节输入流写数据的方式

5.字节输入流FileInputStream

5.1 FileInputStream的构造方法

5.2 FileInputStream的成员方法

6.字节缓冲输出流BufferedOutputStream

7.字节缓冲输入流BufferedInputStream

8.字节流四种方式复制MP4并测试效率


1.IO流的概述

  • IO流用来处理设备之间的数据传输,例如:上传文件和下载文件
  • Java对数据的操作是通过流的方式
  • Java用于操作流的对象都在IO包中

2.IO流分类

2.1 按照数据流向

  • 输入流:读取数据
  • 输出流:写入数据

2.2 按照数据类型

  • 字节流
  • 字符流

什么情况下选择字节流?又在哪种情况下选择字符流呢?

  • 如果数据所在的文件通过windows自带的记事本打开并能读懂里面的内容,就用字符流。其他用字节流。
  • 如果你什么都不知道,就用字节流

3.IO流常用基类

3.1 字节流的抽象基类

  • InputStream
  • OutputStream

3.2 字符流的抽象基类

  • Reader
  • Writer

注:由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀!

例如:

  • InputStream的子类FileInputStream,OutputStream的子类FileOutputStream
  • Reader的子类FileReader,Writer的子类FileWriter

4.字节输出流FileOutputStream

4.1 FileOutputStream的构造方法

  • FileOutputStream(File file):创建一个向指定File对象表示的文件中写入数据的文件输出流
  • FileOutputStream(String name):创建一个向具有指定名称的文件中写入数据的输出文件流

4.1.1 需求:向一个文件中写入数据"hello,io"

4.1.2 字节输出流的操作步骤?

  • 创建字节输出流对象
  • 写入数据
  • 释放资源

代码如下:

package cn.itcast_01;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 需求: 向一个文件中写入数据"hello,io"
 * 
 * @author HW
 */
public class FileOutputStreamDemo {
	public static void main(String[] args) {
		FileOutputStream fos = null;
		try {
			// 创建字节输出流对象
			fos = new FileOutputStream("fos.txt");
			// 写入数据
			String str = "hello,io";
			fos.write(str.getBytes());
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 释放资源
			// 只有在fos!=null的时候,才需要释放资源,否则会报空指针异常
			if(fos!=null){
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

4.1.3 创建字节输出流对象到底做了哪些事情?

  • 调用系统功能去创建文件
  • 创建字节输出流对象fos
  • 把字节输出流对象fos指向这个文件

4.1.4 数据写入成功后,为什么要关闭close()?

  • 让流对象变成垃圾,这样就可以被垃圾回收器回收了
  • 通知系统去释放跟该文件相关的资源    

4.2 字节输入流写数据的方式

  • public void write(int b):将指定字节写入此文件输出流
  • public void write(byte[] b):将 b.length个字节从指定 byte数组写入此文件输出流中
  • public void write(byte[] b,int off,int len):将指定 byte数组中从偏移量 off开始的 len个字节写入此文件输出流。

4.2.1 如何实现数据的换行?

代码如下:

package cn.itcast_01;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 *如何实现数据的换行?使用换行符\r\n
 * 
 * @author HW
 *
 */
public class FileOutputStreamDemo2 {
	public static void main(String[] args) {
		FileOutputStream fos = null;
		try {
			// 创建字节输出流对象fos
			fos = new FileOutputStream("fos.txt");
			
			// 将指定字节写入fos对象中
			fos.write(97);
			// 实现换行
			fos.write("\r\n".getBytes());
			
			// 将一个字节数组写入fos中
			byte[] b = { 97, 98, 99, 100, 101 };
			fos.write(b);
			fos.write("\r\n".getBytes());
			
			//将字节数组b的从1开始的3个字节写入fos中
			fos.write(b, 1, 3);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 释放资源
			if(fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

4.2.2 如何实现数据的追加写入?

 使用构造方法:

  • public FileOutputStream(File file, boolean append):创建一个向指定File对象表示的文件中写入数据的文件输出流,如果第二个参数为true,则将字节写入文件末尾处;
package cn.itcast_02;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/*
 * 如何实现数据的追加写入?
 * 
 * 使用构造方法:
 * public FileOutputStream(File file, boolean append):创建一个向指定File对象表示的文件中写入数据的文件输出流,如果第二个参数为true,则将字节写入文件末尾处;
 */
public class FileOutputStreamDemo2 {
	public static void main(String[] args) {
		// 声明字节输出流的引用
		FileOutputStream fos = null;
		try {
			// 生成一个代表字节输出流的对象,实现在末尾追加写入数据
			fos = new FileOutputStream("fos3.txt", true);
			// 调用write()方法,写入数据
			for (int x = 0; x < 10; x++) {
				fos.write(("Hello" + x).getBytes());
				// 实现数据换行
				fos.write("\r\n".getBytes());
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally{
			// 释放资源
			// 只有在fos!=null的时候,才需要释放资源,否则会报空指针异常
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

5.字节输入流FileInputStream

5.1 FileInputStream的构造方法

  • public FileInputStream(File file)
  • public FileInputStream(String name)

5.2 FileInputStream的成员方法

  • public int read():一次读取一个字节,如果读取到文件的末尾而没有更多的数据,则返回-1
  • public int read(byte[] b):一次读取一个字节数组,返回的是实际读取的字节数目(长度),如果读取到文件的末尾而没有更多的数据,则返回-1

字节输入流的操作步骤?

  • 创建字节输入流对象
  • 调用read()方法读取数据,并把数据显示在控制台
  • 释放资源

5.2.1 一次读取一个字节

  • public int read():一次读取一个字节,如果读取到文件的末尾而没有更多的数据,则返回-1

需求1:字节流复制文本文件,把当前目录下的srcFile.txt中的内容复制到当前项目下的destFile.txt中

代码如下:

package com.hw.inputstream;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * public int read():一次读取一个字节,如果读取到文件的末尾,则返回-1
 * 
 * 需求:字节流复制文本文件,把当前目录下的srcFile.txt中的内容复制到当前项目下的destFile.txt中 
 * 数据源:srcFile.txt
 * 目的地:destFile.txt
 * 
 * @author HW
 * 
 */
public class CopyFileDemo {
	public static void main(String[] args) {
		// 声明字节输入流的引用(数据源)
		FileInputStream fis = null;
		// 声明字节输出流的引用(目的地)
		FileOutputStream fos = null;

		try {
			// 生成代表字节输入流的对象
			fis = new FileInputStream("srcFile.txt");
			// 生成代表字节输出流的对象
			fos = new FileOutputStream("destFile.txt");

			// 读取数据,一次读取一个字节,如果读取到文件的末尾,则返回-1
			int b = 0;
			while ((b = fis.read()) != -1) {
				fos.write(b);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 释放资源
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

需求2:把D:\\develop\\images\\lover.jpg复制到当前项目目录下的sunset.jpg中

代码如下:

package com.hw.inputstream;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * public int read():一次读取一个字节的数据,如果读取到文件的末尾,则返回-1
 * 
 * 需求:把D:\\develop\\images\\lover.jpg复制到当前项目目录下的sunset.jpg中
 * 
 * @author HW
 * 
 */
public class CopyImageDemo {
	public static void main(String[] args) {
		// 声明字节输入流FileInputStream的引用
		FileInputStream fis = null;
		// 声明字节输出流FileOutputStream的引用
		FileOutputStream fos = null;

		try {
			// 生成代表字节输入流的对象
			fis = new FileInputStream("D:\\develop\\images\\lover.jpg");
			// 生成代表字节输出流 的对象
			fos = new FileOutputStream("sunset.jpg");

			// 复制图片
			// 一次读取一个字节的数据,如果读取到文件的末尾,则返回-1
			int b = 0;
			while ((b = fis.read()) != -1) {
				fos.write(b);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 释放资源
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

需求3:把D:\\develop\\images\\计算机基础.avi复制到当前项目目录下的video.avi中

代码如下:

package com.hw.inputstream;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * public int read():一次读取一个字节的数据,如果读取到文件的末尾,则返回-1
 * 
 * 需求:把D:\\develop\\images\\计算机基础.avi复制到当前项目目录下的video.avi中
 * 
 * @author HW
 * 
 */
public class CopyVideoDemo {
	public static void main(String[] args) {
		// 声明字节输入流的引用
		FileInputStream fis = null;
		// 声明字节输出流的引用
		FileOutputStream fos = null;

		try {
			// 生成代表字节输入流的对象
			fis = new FileInputStream("D:\\develop\\images\\计算机基础.avi");
			// 生成代表字节输出流的对象
			fos = new FileOutputStream("video.avi");

			// 复制视频
			// 一次读取一个字节的数据
			int b = 0;
			while ((b = fis.read()) != -1) {
				fos.write(b);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

	}
}

5.2.2 一次读取一个字节数组

  • public int read(byte[] b):一次读取一个字节数组,返回的是实际读取的字节数目(长度),如果读取到文件的末尾而没有更多的数据,则返回-1

需求1:把D:\\develop\\users.xml中的内容复制到当前项目目录下的E:\\student.xml中

代码如下:

package com.hw.inputstream;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * public int read(byte[] b):一次读取一个字节数组的数据,返回的是实际读取的字节的长度,如果读取到文件的末尾而没有更多的数据,则返回-1
 * 
 * 需求:把D:\\develop\\users.xml中的内容复制到当前项目目录下的E:\\student.xml中
 * 
 * @author HW
 */
public class CopyFileDemo {
	public static void main(String[] args) {
		// 声明字节输入流的引用
		FileInputStream fis = null;
		// 声明字节输出流的引用
		FileOutputStream fos = null;
		File file = null;

		try {
			// 生成代表字节输入流的对象
			fis = new FileInputStream("D:\\develop\\users.xml");

			// 生成代表字节输出流的对象
			fos = new FileOutputStream("E:\\student.xml");

			// 复制数据,一次读取一个字节数组的数据
			// 生成一个byte类型的数组
			byte[] b = new byte[1024];
			// 实际读取的字节长度
			int len = 0;
			while ((len = fis.read(b)) != -1) {
				fos.write(b, 0, len);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 释放资源
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

需求2:把D:\\develop\\images\\计算机基础.avi复制到当前项目目录下的video.avi中

代码如下:

package com.hw.inputstream;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * public int read(byte[] b):一次读取一个字节数组的数据,返回的是实际读取的字节长度,如果读取到文件的末尾,则返回-1
 * 
 * 需求:把D:\\develop\\images\\计算机基础.avi复制到当前项目目录下的video.avi中
 * 
 * @author HW
 */
public class CopyVideoDemo {
	public static void main(String[] args) {
		// 声明字节输入流的引用
		FileInputStream fis = null;
		// 声明字节输出流的引用
		FileOutputStream fos = null;

		try {
			// 生成代表字节输入流的对象
			fis = new FileInputStream("D:\\develop\\images\\计算机基础.avi");
			// 生成代表字节输出流的对象
			fos = new FileOutputStream("video.avi");

			// 复制视频,一次读取一个字节数组的数据
			// 生成一个byte类型的数组
			byte[] b = new byte[1024];
			// 实际读取的字节长度
			int len = 0;
			while ((len = fis.read(b)) != -1) {
				fos.write(b, 0, len);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 释放资源
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,这是加入了数组这样的缓冲区效果,java本身在设计的时候,也考虑到了这样的设计思想,所以提供了字节缓冲区流!

6.字节缓冲输出流BufferedOutputStream

具体用法,参考如下代码:

package com.hw.inputstream;

import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 字节缓冲输出流BufferedOutputStream
 * 
 * @author HW
 * 
 */
public class BufferedOutputStreamDemo {
	public static void main(String[] args) {
		// 声明BufferedOutputStream引用
		BufferedOutputStream bos = null;

		try {
			// 创建字节缓冲输出流对象
			bos = new BufferedOutputStream(new FileOutputStream("bos.txt"));
			// 写入数据
			bos.write("hello,bos!".getBytes());
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 释放资源
			if (bos != null) {
				try {
					bos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

7.字节缓冲输入流BufferedInputStream

具体用法,参考如下代码:

package com.hw.inputstream;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * 字节缓冲输入流BufferedInputStream
 * 
 * @author HW
 * 
 */
public class BufferedInputStreamDemo {
	public static void main(String[] args) {
		// 声明BufferedInputStream引用
		BufferedInputStream bis = null;

		try {
			// 创建字节缓冲输入流对象
			bis = new BufferedInputStream(new FileInputStream("bis.txt"));

			// 读取数据,一次读取一个字节数组
			// 生成一个byte类型的字节数组
			byte[] bytes = new byte[1024];
			// 实际读取的字节长度
			int len = 0;
			while ((len = bis.read(bytes)) != -1) {
				// 生成String类型的对象
				String str = new String(bytes, 0, len);
				System.out.println(str);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

8.字节流四种方式复制MP4并测试效率

需求:把D:\\develop\\images\\计算机基础.avi复制到当前项目目录下的video.avi中

字节流四种方式复制文件:FileInputStream&FileOutputStream,BufferedInputStream&BufferedOutputStream

  • 基本字节流一次读写一个字节
  • 基本字节流一次读写一个字节数组
  • 高效字节流一次读写一个字节
  • 高效字节流一次读写一个字节数组

代码如下:

package com.hw.inputstream;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 需求:把D:\\develop\\images\\计算机基础.avi复制到当前项目目录下的video.avi中
 * 
 * 字节流四种方式复制文件: 
 * FileInputStream & FileOutputStream 
 * 1.基本字节流一次读写一个字节,共耗时:46788毫秒
 * 2.基本字节流一次读写一个字节数组,共耗时:54毫秒
 * 
 * BufferedInputStream & BufferedOutputStream 
 * 3.高效字节流一次读写一个字节,共耗时:156毫秒
 * 4.高效字节流一次读写一个字节数组,共耗时:12毫秒
 * 
 * @author HW
 * 
 */
public class CopyVideoTest {
	public static void main(String[] args) {
		long start = System.currentTimeMillis();
		// method1("D:\\develop\\images\\计算机基础.avi", "video.avi");
		// method2("D:\\develop\\images\\计算机基础.avi", "video.avi");
		// method3("D:\\develop\\images\\计算机基础.avi", "video.avi");
		method4("D:\\develop\\images\\计算机基础.avi", "video.avi");
		long end = System.currentTimeMillis();
		System.out.println("共耗时:" + (end - start) + "毫秒");
	}
	
	// 高效字节流一次读取一个字节数组
	private static void method4(String srcStr, String destStr) {
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		
		try {
			// 创建字节缓冲输入/输出流对象
			bis = new BufferedInputStream(new FileInputStream(srcStr));
			bos = new BufferedOutputStream(new FileOutputStream(destStr));

			// 一次读取一个字节数组
			// 生成一个byte类型的数组
			byte[] bytes = new byte[1024];
			// 实际读取的字节长度
			int len = 0;
			while ((len = bis.read(bytes)) != -1) {
				bos.write(bytes);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 释放资源
			if (bos != null) {
				try {
					bos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			if (bis != null) {
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	// 高效字节流一次读取一个字节
	private static void method3(String srcStr, String destStr) {
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		
		try {
			// 创建字节缓冲输入/输出流对象
			bis = new BufferedInputStream(new FileInputStream(srcStr));
			bos = new BufferedOutputStream(new FileOutputStream(destStr));
			
			// 一次读取一个字节
			int  b = 0;
			while((b = bis.read()) != -1) {
				bos.write(b);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 释放资源
			if (bos != null) {
				try {
					bos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			if (bis != null) {
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	// 基本字节流一次读写一个字节数组
	private static void method2(String srcStr, String destStr) {
		FileInputStream fis = null;
		FileOutputStream fos = null;
		
		try {
			// 创建字节输入/输出流对象
			fis = new FileInputStream(srcStr);
			fos = new FileOutputStream(destStr);

			// 一次读取一个字节数组
			// 生成一个byte类型的数组
			byte[] bytes = new byte[1024];
			// 实际读取的字节长度
			int len = 0;
			while ((len = fis.read(bytes)) != -1) {
				fos.write(bytes);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 释放资源
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	// 基本字节流一次读写一个字节
	private static void method1(String srcStr, String destStr) {
		FileInputStream fis = null;
		FileOutputStream fos = null;
		
		try {
			// 创建字节输入/输出流对象
			fis = new FileInputStream(srcStr);
			fos = new FileOutputStream(destStr);
			
			// 读取数据,一次读取一个字节,如果读取到文件的末尾,则返回-1
			int b = 0;
			while ((b = fis.read()) != -1) {
				fos.write(b);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 释放资源
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_44679832/article/details/105393517