Java IO 学习笔记

1.核心类
  • File                     文件类
  • InputStream       字节输入流
  • OutputStream     字节输出流
  • Reader               字符输入流
  • Writer                字符输出流
  • Closeable           关闭流接口
  • Flushable           刷新流接口
  • Serializable        序列化接口


2.流分类
  • 输入流:数据源到程序(InputStream、Reader读进来)
  • 输出流:程序到目的地(OutputStream、Writer写进去)
  • 节点流:可以直接从数据源或 目的地读写数据
  • 处理流:不直接连接到数据源或目的地,是其他流进行封装。目的主要是简化操作和提高性能
  • 节点流和处理流的关系:
    • 节点流处于IO操作的第一线,所有操作必须用过他们进行
    • 处理流可以对其他流进行处理(提高效率或操作灵活性)
  • 字节流:按照字节读取数据(InputStream、OutputStream)
  • 字符流:按照字符读取数据(Reader、Writer),因为文件编码的不同,从而有了对字符进行高效操作的字符流对象。
    • 原理:底层还是基于字节流操作,自动搜寻了指定的码表

image

image

3.File常用API及文件编码

文件路径推荐表示法:

          1.path= “D:/XXX/XXX/XXX.png”;

          2.path=”D:”+File.separator+”java300”+File.separator+”XXX.png”;

API

  • pathSeparator   separator                               路径|路径分隔符
  • File(String parent,String child)                        构造器
  • File(File parent,String child)                           
  • File(String name)
  • getName()                                                    文件名、路径名
  • getPath()
  • getAbsolutePath()
  • getParent
  • exists()                                                       判断状态
  • isFile()
  • isDirectorv()
  • length()                                                     文件长度
  • createNewFile()                                         创建新文件
  • delete()                                                    删除文件
  • mkdir()                                                    创建目录,需要确保上级目录存在,不存在时创建失败
  • mkdirs()                                                   创建目录,当父目录不存在时一同创建
  • list()                                                        下级名称
  • listFiles()                                                  下级File
  • listRoots()                                                根路径



4.IO流读写操作
  • InputStream                字节输入流的父类,数据单位为字节
    • int  read()
    • void  close()
  • OutputStream              字节输出流的父类,数据单位为字节
    • void  write(int)
    • void flush()
    • void close()
  • Reader                        字符输入流的父类,数据单位为字符
    • int  read()
    • void close()
  • Writer                         字符输出流的父类,数据单位为字符
    • void  write(String)
    • void  flush()
    • void  close()


5.代码段

输入流代码演示

  1 package wangyue;
  2 
  3 import java.io.*;
  4 
  5 public class IoStudy02 {
  6     public static void main(String[] args) {
  7         //1.创建源
  8         File file = new File("test");
  9         //2.创建流
 10         InputStream is = null;
 11         try {
 12             is = new FileInputStream(file);
 13             byte[] flush = new byte[30];//缓冲容器
 14             int len;//接收长度
 15             while ((len = is.read(flush)) != -1) {
 16                 String str = new String(flush, 0, len);
 17                 System.out.println(str);
 18             }
 19         } catch (FileNotFoundException e) {
 20             e.printStackTrace();
 21         } catch (IOException e) {
 22             e.printStackTrace();
 23         }finally {
 24             if (is != null) {
 25                 try {
 26                     is.close();
 27                 } catch (IOException e) {
 28                     e.printStackTrace();
 29                 }
 30             }
 31         }
 32     }
 33 }
 34 

输出流代码演示

  1 package wangyue;
  2 
  3 import java.io.*;
  4 
  5 public class IoStudy03 {
  6     public static void main(String[] args) {
  7         //1.创建源
  8         File dest = new File("output.txt");
  9         //2.选择流
 10         OutputStream os = null;
 11         try {
 12             os = new FileOutputStream(dest);
 13             //3.操作
 14             String msg = "向文件中写入一些没什么用的东西";
 15             byte[] datas = msg.getBytes();//字符串--》字节数组  (编码)
 16             os.write(datas, 0, datas.length);
 17             //刷新流,避免有数据存在在缓存中。即使os.close() 也会刷新流,此处也再刷新一次
 18             os.flush();
 19         } catch (FileNotFoundException e) {
 20             e.printStackTrace();
 21         } catch (IOException e) {
 22             e.printStackTrace();
 23         }finally {
 24             if (os != null) {
 25                 try {
 26                     os.close();
 27                 } catch (IOException e) {
 28                     e.printStackTrace();
 29                 }
 30             }
 31         }
 32 
 33     }
 34 }
 35 

文件拷贝

  1 package wangyue;
  2 
  3 import java.io.*;
  4 
  5 public class IoStudy04 {
  6     public static void main(String[] args) {
  7         //1.创建源
  8         File src = new File("C:/Users/86178/Desktop/微信截图_20191006134845.png");
  9         File dest = new File("C:/Users/86178/Desktop/copy.png");
 10         //2.选择流
 11         InputStream is = null;
 12         OutputStream os = null;
 13         try {
 14             is = new FileInputStream(src);
 15             os = new FileOutputStream(dest,false);
 16             //3.操作
 17             byte[] flush = new byte[1024];
 18             int len;
 19             while ((len = is.read(flush)) != -1) {
 20                 os.write(flush, 0, len);
 21             }
 22             //刷新流,避免有数据存在在缓存中。即使os.close() 也会刷新流,此处也再刷新一次
 23             os.flush();
 24         } catch (FileNotFoundException e) {
 25             e.printStackTrace();
 26         } catch (IOException e) {
 27             e.printStackTrace();
 28         }finally {
 29             if (os != null && is != null) {
 30                 //4.关闭资源,先打开的后关闭。注意要分别关闭
 31                 try {
 32                     is.close();
 33                 } catch (IOException e) {
 34                     e.printStackTrace();
 35                 }
 36                 try {
 37                     os.close();
 38                 } catch (IOException e) {
 39                     e.printStackTrace();
 40                 }
 41             }
 42         }
 43 
 44     }
 45 }
 46 
6.字节数组流   ByteArrayInputStream & ByteArrayOutputStream

字节数组流无需关闭,由java虚拟机gc进行回收.

7.IO工具类
  1 package wangyue;
  2 
  3 import java.io.*;
  4 
  5 /**
  6  * 1、封装拷贝
  7  * 2、封装释放资源
  8  */
  9 public class FileUtils {
 10 
 11     public static void main(String[] args) {
 12 
 13         byte[] datas = null;
 14         //文件到文件
 15         try {
 16             InputStream is = new FileInputStream("test");
 17             OutputStream os = new FileOutputStream("test-copy.txt");
 18             copy(is, os);
 19         } catch (IOException e) {
 20             e.printStackTrace();
 21         }
 22         //文件到字节数组
 23         try {
 24             InputStream is = new FileInputStream("test.png");
 25             ByteArrayOutputStream os = new ByteArrayOutputStream();
 26             copy(is, os);
 27             datas = os.toByteArray();
 28             System.out.println(datas.length);
 29         } catch (IOException e) {
 30             e.printStackTrace();
 31         }
 32         //字节数组到文件
 33         try {
 34             InputStream is = new ByteArrayInputStream(datas);
 35             OutputStream os = new FileOutputStream("test-copy.png");
 36             copy(is,os);
 37         } catch (FileNotFoundException e) {
 38             e.printStackTrace();
 39         }
 40     }
 41 
 42     /**
 43      * 对接输入输出流
 44      * @param is
 45      * @param os
 46      */
 47     public static void copy(InputStream is, OutputStream os) {
 48         try {
 49             byte[] flush = new byte[2014];//缓冲容器
 50             int len;
 51             while ((len = is.read(flush)) != -1) {
 52                 os.write(flush, 0, len);
 53             }
 54             os.flush();
 55         } catch (IOException e) {
 56             e.printStackTrace();
 57         }finally {
 58             close(is,os);
 59         }
 60     }
 61 
 62     /**
 63      * 释放资源
 64      * @param is
 65      * @param os
 66      */
 67     public static void close(InputStream is,OutputStream os) {
 68         try {
 69             if (is != null) {
 70                 is.close();
 71             }
 72         } catch (IOException e) {
 73             e.printStackTrace();
 74         }
 75 
 76         try {
 77             if (os != null) {
 78                 os.close();
 79             }
 80         } catch (IOException e) {
 81             e.printStackTrace();
 82         }
 83     }
 84 
 85     /**
 86      * 释放资源
 87      * @param ios
 88      */
 89     public static void close(Closeable... ios) {
 90         for (Closeable io : ios) {
 91             try {
 92                 if (null != io) {
 93                     io.close();
 94                 }
 95             } catch (IOException e) {
 96                 e.printStackTrace();
 97             }
 98         }
 99     }
100 
101 }
102 
  1 package wangyue;
  2 
  3 import java.io.*;
  4 
  5 public class FileUtils2 {
  6     /**
  7      * 对接输入输出流
  8      * try...with...resource
  9      * 不需要在finally中释放资源,只要try(is,os)即可,系统自动释放资源,不需要关心释放顺序
 10      * @param is
 11      * @param os
 12      */
 13     public static void copy(InputStream is, OutputStream os) {
 14         try (InputStream iss = new FileInputStream("sdf");
 15             OutputStream oss = new FileOutputStream("test")) {
 16 
 17             byte[] flush = new byte[2014];//缓冲容器
 18             int len;
 19             while ((len = is.read(flush)) != -1) {
 20                 os.write(flush, 0, len);
 21             }
 22             os.flush();
 23         } catch (IOException e) {
 24             e.printStackTrace();
 25         }
 26     }
 27 }
 28 


8.装饰器设计模式,原理剖析

image

  1 package wangyue;
  2 
  3 /**
  4  * 模拟咖啡
  5  * 1、抽象组件:需要装饰的抽象对象(接口或抽象父类)
  6  * 2、具体组件:需要装饰的对象
  7  * 3、抽象装饰类:包含了对抽象组件的引用,以及装饰者共有的方法
  8  * 4、具体装饰类:被装饰的对象
  9  */
 10 public class DecorateTest02 {
 11 
 12     public static void main(String[] args) {
 13         Drink coffee = new Coffee();
 14         Drink sugar = new Sugar(coffee);
 15         System.out.println(sugar.info() + "-->" + sugar.cost());
 16         Drink milk = new Milk(coffee);
 17         System.out.println(milk.info() + "-->" + milk.cost());
 18     }
 19 }
 20 //抽象组件
 21 interface Drink {
 22     double cost();//费用
 23     String info();//说明
 24 }
 25 
 26 //具体组件
 27 class Coffee implements Drink {
 28     private String name = "原味咖啡";
 29 
 30     @Override
 31     public double cost() {
 32         return 10;
 33     }
 34 
 35     @Override
 36     public String info() {
 37         return name;
 38     }
 39 }
 40 
 41 //抽象装饰类
 42 abstract class Decorate implements Drink {
 43 
 44     //对抽象组件的引用
 45     private Drink drink;
 46 
 47     public Decorate(Drink drink) {
 48         this.drink = drink;
 49     }
 50 
 51     @Override
 52     public double cost() {
 53         return this.drink.cost();
 54     }
 55 
 56     @Override
 57     public String info() {
 58         return this.drink.info();
 59     }
 60 }
 61 
 62 //具体的装饰类
 63 class Milk extends Decorate {
 64 
 65     public Milk(Drink drink) {
 66         super(drink);
 67     }
 68     @Override
 69     public double cost() {
 70         return super.cost() * 4;
 71     }
 72 
 73     @Override
 74     public String info() {
 75         return super.info() + "牛奶";
 76     }
 77 }
 78 //具体的装饰类
 79 class Sugar extends Decorate {
 80 
 81     public Sugar(Drink drink) {
 82         super(drink);
 83     }
 84     @Override
 85     public double cost() {
 86         return super.cost() * 2;
 87     }
 88 
 89     @Override
 90     public String info() {
 91         return super.info() + "加入优质方糖";
 92     }
 93 }
 94 
 95 
9.字节缓冲流  BufferedInputStream & BufferedOutputStream
  • 提升性能
  • 最底层一定是节点流
  • 只需要释放最外层的处理流,java自动寻找对应的字节流,并释放

使用方式,直接在字节流外面加上字节缓冲流,能够显著提升效率

  1 InputStream is = new BufferedInputStream(new FileInputStream(src));
  2 OutputStream os = new BufferedOutputStream(new FileOutputStream(dest));

释放资源只需要释放最外层的流即可

10.字符缓冲流  BufferedReader  &  BufferedWriter

仅限于纯文本操作


11.转换流    InputStreamReader  &  OutputStreamWriter

是字节流与字符流之间的桥梁,能将字节流转换为字符流,并且能够为字节流指定字符集,可处理一个个的字符

  1 package wangyue;
  2 
  3 import java.io.*;
  4 
  5 /**
  6  * 转换流:InputStreamReader   OutputStreamWriter
  7  * 1、以字符流的形式操作字节流(纯文本)
  8  * 2、指定字符集
  9  */
 10 public class ConvertTest {
 11     public static void main(String[] args) {
 12         //操作System.in和System.out
 13         try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
 14              BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out))) {
 15             //循环获取键盘的输入(exit退出),输出此内容
 16             String msg = "";
 17             while (!msg.equals("exit")) {
 18                 msg = reader.readLine();//循环读取
 19                 writer.write(msg);//循环写出
 20                 writer.newLine();
 21                 writer.flush();//强制刷新,内容太少,必须强制刷新,否则数据驻留在缓存中,只有当缓存满了,才会写一次
 22             }
 23         } catch (IOException e) {
 24             e.printStackTrace();
 25         }
 26 
 27     }
 28 }
 29 


  1 package wangyue;
  2 
  3 import java.io.*;
  4 import java.net.URL;
  5 
  6 /**
  7  * 转换流:InputStreamReader   OutputStreamWriter
  8  * 1、以字符流的形式操作字节流(纯文本)
  9  * 2、指定字符集
 10  */
 11 public class ConvertTest02 {
 12     public static void main(String[] args) {
 13         //操作网络流 下载百度源码
 14         try (BufferedReader reader = new BufferedReader(new InputStreamReader(new URL("http://www.baidu.com").openStream(), "UTF-8"));
 15              BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("baidu.html"), "UTF-8"))
 16         ) {
 17 
 18             String temp = null;
 19             while ((temp = reader.readLine()) != null) {
 20                 writer.write(temp);
 21                 writer.newLine();
 22                 writer.flush();
 23             }
 24         } catch (IOException e1) {
 25             e1.printStackTrace();
 26         }
 27     }
 28 }
 29 


12.数据流 DataInputStream  &  DataOutputStream

简单说,就是保留了数据类型的字节流,操作的是一些基本 类型和字符串

最好再怼上一个字节缓冲流,提升下性能

  1 package wangyue;
  2 
  3 import java.io.*;
  4 
  5 /**
  6  * 数据流:
  7  * 1、写出后读取
  8  * 2、读取的顺序与写出保持一致
  9  *
 10  * DataOutputStream
 11  * DataInputStream
 12  */
 13 public class DataTest {
 14 
 15     public static void main(String[] args) throws IOException {
 16         //写出
 17         ByteArrayOutputStream baos = new ByteArrayOutputStream();
 18         DataOutputStream dos = new DataOutputStream(baos);
 19         //操作数据类型+数据
 20         dos.writeUTF("嘿嘿嘿");
 21         dos.writeInt(123);
 22         dos.writeBoolean(false);
 23         byte[] datas = baos.toByteArray();
 24         //读取
 25         DataInputStream dis = new DataInputStream(new ByteArrayInputStream(datas));
 26         String UTF = dis.readUTF();
 27         int i = dis.readInt();
 28         boolean b = dis.readBoolean();
 29         System.out.println(UTF);
 30         System.out.println(i);
 31         System.out.println(b);
 32 
 33     }
 34 }
 35 


13.对象流  ObjectInputStream  &  ObjectOutputStream

操作所有对象。

对象的序列化和反序列化

对象要进行序列化或反序列化必须实现   Serializable   接口,Serializable接口是一个空接口,没有任何意义,只是给虚拟机的一个标识

image

进行数据还原时,为了避免类型转换异常,先使用  instanceof  关键字进行类型的判断

  1 if(str instanceof String){
  2 	String strObject = (String) str;
  3 }

在一个实现了序列化接口的类中,某属性属于敏感信息,不应该被序列化,可使用   transient(透明)   关键字。标识某属性不需要序列化

  1 Class Employee implements Serializable{
  2 	private transient String name;//不需要序列化
  3 	private double salary;
  4 }


14.打印流   PrintStream

image


15.随机流  RandomAccessFile

随机流加上多线程,可以实现对一个大文件的多线程分段下载

image

  1 package wangyue;
  2 
  3 import java.io.File;
  4 import java.io.IOException;
  5 import java.io.RandomAccessFile;
  6 
  7 /**
  8  * 随机读取和写入流 RandomAccessFile
  9  */
 10 public class RandTest01 {
 11     public static void main(String[] args) throws IOException {
 12         RandomAccessFile raf = new RandomAccessFile(new File("baidu.html"), "r");
 13         //起始位置
 14         int beginPos = 2;
 15         //实际大小
 16         int actualSize = 1026;
 17         //随机读取
 18         raf.seek(2);
 19         byte[] flush = new byte[1024];
 20         int len = -1;
 21         while ((len = raf.read(flush))!=-1) {
 22             if (actualSize > len) {//获取本次读取的所有内容
 23                 System.out.println(new String(flush,0,len));
 24                 actualSize -= len;
 25             } else {
 26                 System.out.println(new String(flush,0,len));
 27                 break;
 28             }
 29         }
 30         raf.close();
 31     }
 32 }
 33 


16.合并流  SequenceInputStream

image


17.Commons IO   FileUtils使用


image

依赖的jar包

image

代码演示

  1 package commons;
  2 
  3 import org.apache.commons.io.FileUtils;
  4 import org.apache.commons.io.IOUtils;
  5 import org.apache.commons.io.LineIterator;
  6 import org.apache.commons.io.filefilter.DirectoryFileFilter;
  7 import org.apache.commons.io.filefilter.EmptyFileFilter;
  8 import wangyue.FileUtil;
  9 
 10 import java.io.File;
 11 import java.io.IOException;
 12 import java.net.URL;
 13 import java.util.ArrayList;
 14 import java.util.Collection;
 15 import java.util.List;
 16 
 17 /**
 18  * 大小、列出子孙集、读取文件、写出文件
 19  * 重点:拷贝
 20  */
 21 public class CIOTest01 {
 22     public static void main(String[] args) throws IOException {
 23         //文件大小
 24         long len = FileUtils.sizeOf(new File("test.png"));
 25         System.out.println(len);
 26         //目录大小
 27         len = FileUtils.sizeOf(new File("G:/work/IOStudy"));
 28         System.out.println(len);
 29         //返回子孙集
 30         //FileUtils.listFiles(目录,过滤文件(是否为空,后缀名,支持组合(and,or)等等),过滤目录  null代表只走一层  DirectoryFileFilter.INSTANCE表示子孙集)
 31         Collection<File> files = FileUtils.listFiles(new File("G:/work/IOStudy"), EmptyFileFilter.NOT_EMPTY, DirectoryFileFilter.INSTANCE);
 32         for (File file : files) {
 33             System.out.println(file.getAbsolutePath());
 34         }
 35         //读取文件
 36         String msg = FileUtils.readFileToString(new File("test"), "UTF-8");
 37         System.out.println(msg);
 38         byte[] datas = FileUtils.readFileToByteArray(new File("test"));
 39         System.out.println(datas.length);
 40         //逐行读取
 41         List<String> msgs = FileUtils.readLines(new File("output.txt"), "UTF-8");
 42         for (String msgone : msgs) {
 43             System.out.println(msgone);
 44         }
 45         LineIterator it = FileUtils.lineIterator(new File("output.txt"));
 46         while (it.hasNext()) {
 47             System.out.println(it.nextLine());
 48         }
 49         //写出内容
 50         FileUtils.write(new File("good.wy"), "只有不断的学习,才有机会更进一步\r\n", "UTF-8",false);//最后一个参数表示是否追加,默认false
 51         FileUtils.writeStringToFile(new File("good.wy"), "只有不断的学习,才有机会更进一步\r\n", "UTF-8",true);
 52         FileUtils.writeByteArrayToFile(new File("good.wy"), "只有不断的学习,才有机会更进一步\r\n".getBytes("UTF-8"),true);
 53         //写出列表
 54         List<String> data = new ArrayList<>();
 55         data.add("马云");
 56         data.add("马华腾");
 57         data.add("马哥");
 58         FileUtils.writeLines(new File("good.wy"),data,"-----",true);
 59 
 60         //复制文件
 61 //        FileUtils.copyFile(new File("test.png"), new File("test-copy2.png"));
 62         //复制文件到目录
 63 //        FileUtils.copyFileToDirectory(new File("test.png"),new File("lib"));
 64         //复制目录到目录,是先创建lib2,然后将lib复制到lib2目录下
 65 //        FileUtils.copyDirectoryToDirectory(new File("lib"), new File("lib2"));
 66         //复制目录,直接复制lib,粘贴时修改目录名为lib3
 67 //        FileUtils.copyDirectory(new File("lib"), new File("lib3"));
 68         //拷贝URL内容
 69 //        String url = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1570559702535&di=a5b17ed682978dd64e461156092f6fa6&imgtype=jpg&src=http%3A%2F%2Ft-1.tuzhan.com%2F56215ac87b82%2Fc-1%2Fl%2F2012%2F10%2F08%2F15%2Ff955c4477ad445a184778d45f667e437.jpg";
 70 //        FileUtils.copyURLToFile(new URL(url), new File("钢铁侠.jpg"));
 71         String baiduStr = IOUtils.toString(new URL("http://www.baidu.com"), "UTF-8");
 72         System.out.println(baiduStr);
 73 
 74     }
 75 }
 76 
posted @ 2019-10-06 18:38  用代码打败魔法  阅读(203)  评论(0编辑  收藏  举报