字节输出流FileOutputStream

创建输出流对象

OutputStream 流对象是一个抽象类,不能实例化。所以,我们要找一个具体的子类 :FileOutputStream。
查看FileOutputStream的构造方法:

  1. FileOutputStream(File file)
  2. FileOutputStream(String name)

创建字节输出流对象了做了几件事情:

  1. 调用系统功能去创建文件
  2. 创建字节输出流对象
  3. 把该字节输出流对象引用指向这个文件
  1. public class OutputStreamDemo {
  2. public static void main(String[] args) throws IOException {
  3. OutputStream fos = new FileOutputStream("demo1.txt");
  4. /*
  5. * 创建字节输出流对象了做了几件事情:
  6. * A:调用系统功能去创建文件
  7. * B:创建fos对象
  8. * C:把fos对象指向这个文件
  9. */
  10. //写数据
  11. fos.write("hello,IO".getBytes());
  12. fos.write("java".getBytes());
  13. //释放资源
  14. //关闭此文件输出流并释放与此流有关的所有系统资源。
  15. fos.close();
  16. /*
  17. * 为什么一定要close()呢?
  18. * A:让流对象变成垃圾,这样就可以被垃圾回收器回收了
  19. * B:通知系统去释放跟该文件相关的资源
  20. */
  21. //java.io.IOException: Stream Closed
  22. //fos.write("java".getBytes());
  23. }
  24. }
  • 为什么一定要close()呢?
  1. 让流对象变成垃圾,这样就可以被垃圾回收器回收了
  2. 通知系统去释放跟该文件相关的资源

写出数据

字节输出流操作步骤:

  1. 创建字节输出流对象
  2. 写数据
  3. 释放资源

FileOutputStream中的写出方法:

  1. public void write(int b) //写一个字节
  2. public void write(byte[] b) //写一个字节数组
  3. public void write(byte[] b,int off,int len) //写一个字节数组的一部分
  1. public class OutputStreamDemo2 {
  2. public static void main(String[] args) throws IOException {
  3. FileOutputStream fos = new FileOutputStream("demo2.txt");
  4. // 调用write()方法
  5. fos.write(97); //97 -- 底层二进制数据 -- 通过记事本打开 -- 找97对应的字符值 -- a
  6. //public void write(byte[] b):写一个字节数组
  7. byte[] bys={98,99,100,101};
  8. fos.write(bys);
  9. //public void write(byte[] b,int off,int len):写一个字节数组的一部分
  10. fos.write(bys,1,3);
  11. //释放资源
  12. fos.close();
  13. }
  14. }

如何实现数据的换行?不同的系统针对不同的换行符号识别是不一样的?

  1. windows:\r\n
  2. linux:\n
  3. Mac:\r
  1. public class OutputStreamDemo3 {
  2. public static void main(String[] args) throws IOException {
  3. // 创建一个向具有指定 name 的文件中写入数据的输出文件流。
  4. // 如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处。
  5. FileOutputStream fos = new FileOutputStream("demo2.txt",true);
  6. // 写数据
  7. for (int x = 0; x < 10; x++) {
  8. fos.write(("hello" + x).getBytes());
  9. fos.write("\r\n".getBytes());
  10. }
  11. //释放资源
  12. fos.close();
  13. }
  14. }

加入异常处理的字节输出流操作

  1. public class OutputStreamDemo4 {
  2. public static void main(String[] args) throws IOException {
  3. FileOutputStream fos = null;
  4. try {
  5. fos = new FileOutputStream("demo1.txt");
  6. fos.write("java".getBytes());
  7. } catch (FileNotFoundException e) {
  8. e.printStackTrace();
  9. } catch (IOException e) {
  10. e.printStackTrace();
  11. } finally {
  12. // 如果fos不是null,才需要close()
  13. if (fos != null) {
  14. // 为了保证close()一定会执行,就放到这里了
  15. try {
  16. fos.close();
  17. } catch (IOException e) {
  18. e.printStackTrace();
  19. }
  20. }
  21. }
  22. }
  23. }

字节输入流FileInputStream

  • 字节输入流操作步骤:
  1. 创建字节输入流对象
  2. 调用read()方法读取数据,并把数据显示在控制台
  3. 释放资源
  • 读取数据的方式:
  1. int read() //一次读取一个字节
  2. int read(byte[] b) //一次读取一个字节数组
  • 一次读取一个字节
  1. public class InputStreamDemo {
  2. public static void main(String[] args) throws IOException {
  3. InputStream fis=new FileInputStream("demo1.txt");
  4. int by = 0;
  5. // 读取,赋值,判断
  6. while ((by = fis.read()) != -1) {
  7. System.out.print((char) by);
  8. }
  9. // 释放资源
  10. fis.close();
  11. }
  12. }
  • 一次读取一个字节数组
  1. public class InputStreamDemo2 {
  2. public static void main(String[] args) throws IOException {
  3. FileInputStream fis=new FileInputStream("demo1.txt");
  4. //数组的长度一般是1024或者1024的整数倍
  5. byte[] bys = new byte[1024];
  6. int len = 0;
  7. while ((len = fis.read(bys)) != -1) {
  8. System.out.print(new String(bys, 0, len));
  9. }
  10. // 释放资源
  11. fis.close();
  12. }
  13. }

带缓冲区的字节流BufferedOutputStream

  1. public class BufferedOutputStreamDemo {
  2. public static void main(String[] args) throws IOException {
  3. BufferedOutputStream bos=new
  4. BufferedOutputStream(new FileOutputStream("demo1.txt"));
  5. bos.write("hello".getBytes());
  6. bos.close();
  7. }
  8. }

带缓冲区的字节流BufferedInputStream

  1. public class BufferedInputStreamDemo {
  2. public static void main(String[] args) throws IOException {
  3. BufferedInputStream bis=new
  4. BufferedInputStream(new FileInputStream("demo1.txt"));
  5. int by=-1;
  6. while((by=bis.read())!=-1){
  7. System.out.print((char)by);
  8. }
  9. bis.close();
  10. }
  11. }

复制文件

  1. public class CopyFile {
  2. public static void main(String[] args) throws IOException {
  3. String strFile="国旗歌.mp4";
  4. String destFile="demo3.mp4";
  5. long start = System.currentTimeMillis();
  6. //copyFile(strFile,destFile); //共耗时:75309毫秒
  7. //copyFile2(strFile,destFile); //共耗时:153毫秒
  8. //copyFile3(strFile,destFile);//共耗时:282毫秒
  9. copyFile4(strFile,destFile);//共耗时:44毫秒
  10. long end = System.currentTimeMillis();
  11. System.out.println("共耗时:" + (end - start) + "毫秒");
  12. }
  13. /**
  14. * 基本字节流一次读写一个字节
  15. */
  16. public static void copyFile(String srcFile,String destFile) throws IOException {
  17. FileInputStream fis=new FileInputStream(srcFile);
  18. FileOutputStream fos=new FileOutputStream(destFile);
  19. int by=0;
  20. while((by=fis.read())!=-1){
  21. fos.write(by);
  22. }
  23. fis.close();
  24. fos.close();
  25. }
  26. /**
  27. * 基本字节流一次读写一个字节数组
  28. */
  29. public static void copyFile2(String srcFile,String destFile) throws IOException{
  30. FileInputStream fis=new FileInputStream(srcFile);
  31. FileOutputStream fos=new FileOutputStream(destFile);
  32. int len=0;
  33. byte[] bys=new byte[1024];
  34. while((len=fis.read(bys))!=-1){
  35. fos.write(bys,0,len);
  36. }
  37. fis.close();
  38. fos.close();
  39. }
  40. /**
  41. * 高效字节流一次读写一个字节
  42. */
  43. public static void copyFile3(String srcFile,String destFile) throws IOException{
  44. BufferedInputStream bis=new BufferedInputStream(new FileInputStream(srcFile));
  45. BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(destFile));
  46. int by=0;
  47. while((by=bis.read())!=-1){
  48. bos.write(by);
  49. }
  50. bis.close();
  51. bos.close();
  52. }
  53. /**
  54. * 高效字节流一次读写一个字节数组
  55. */
  56. public static void copyFile4(String srcFile,String destFile) throws IOException{
  57. BufferedInputStream bis=new BufferedInputStream(new FileInputStream(srcFile));
  58. BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(destFile));
  59. int len=0;
  60. byte[] bys=new byte[1024];
  61. while((len=bis.read(bys))!=-1){
  62. bos.write(bys,0,len);
  63. }
  64. bis.close();
  65. bos.close();
  66. }
  67. }

装饰者模式

Java I/O 使用了装饰者模式来实现。以 InputStream 为例,

  • InputStream 是抽象组件;
  • FileInputStream 是 InputStream 的子类,属于具体组件,提供了字节流的输入操作;
  • FilterInputStream 属于抽象装饰者,装饰者用于装饰组件,为组件提供额外的功能。例如 BufferedInputStream 为 FileInputStream 提供缓存的功能。

三、字节操作 - 图1

实例化一个具有缓存功能的字节流对象时,只需要在 FileInputStream 对象上再套一层 BufferedInputStream 对象即可。

  1. FileInputStream fileInputStream = new FileInputStream(filePath);
  2. BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);

DataInputStream 装饰者提供了对更多数据类型进行输入的操作,比如 int、double 等基本类型。