小码笔记17:IO流

一、File类

java.io.File
文件和目录路径名的抽象表示,主要用于文件夹和目录的创建、查找和删除等操作

  • java中八电脑的文件和文件夹(目录)封装成一个File类 我们可以使用File类对文件和文件夹进行操作

  • File类是和系统无关的一个类,任何操作系统都可以使用这个类的方法

  • file 文件
    direatory文件夹
    path路径

1.构造方法
1.public File(String pathname)  
返回通过路径名字符串转换为抽象路径创建新的File实例

2.public File(String parent,String child) 
	从父路径名字符串和子路径字符串创建新的File实例 
	父路径和子路径可以单独书写,使用起来非常灵活;父路径和子路径都可以变化 
                  
3.public File(File parent ,String child) 从父抽象路径名和子路径名字符串创建新的
	父路径和子路径可以单独书写,使用起来非常灵活;父路径和子路径都可以变化
	父路径是File类型,可以使用File类的方法对路径进行一些操作再创建对象
2.常用成员变量
1.static String    pathSeparator    与系统相关的路径分隔符,被表示为一个字符串
  static char      pathSeparatorChar 与系统相关的路径分隔符
  
2.static String    separator          与系统有关的默认分隔符,被表示为一个字符串
  static char      separator          与系统相关的默认分隔符
  
3.操作路径
    1.Windows C:/develop/a/a.txt
    2.Linux   C:\develop\a\a.txt
    3.通用写法:
   		" C:"+File.separator+"develop"+File.separato+"a"+File.separato+"a.txt"
           
4.绝对路径和相对路径 
   1.绝对路径  完整路径
          以盘符开始的路径
          C:\\JAVA\\javaWorkSpace\\ecilpse\\12-1day\\src\\a.txt
   2.相对路径  简化路径
          相对指的是对于当前的根目录
          a.txt
   3.注意  1.路径不区分大小写
            2.路径中中文文件名称分隔符windows使用两个反斜杠

3.常用方法
1.获取         1.String     getAbsolutePath() 返回File的绝对路径字符串
               2.String      getPath()  将File转换成路径名字字符串
               3.String      getName()  获取File表示的文件或者目录名称
               4.long        length()   返回File表示的文件长度 //不存在返回0
               
2.判断         1. boolean    exits()    判断此File表示的文件或者目录是否实际存在
               2. boolean    isDirectory() 判断此File类表示的是否为空
               3.boolean      isFile()   判断此File类表示的是否是文件 .

3.新建删除     1. boolean    createNewFile() 当且仅当具有该名称的文件夹不存在时,创建一个新的空文件,返回是否成功
               2.boolean     delete()   删除File表示的文件或者目录 (File要存在),返回是否成功
               3.boolean     mkdir()    创建File表示的目录,返回是否成功
               4.boolean     mkdirs()   创建File表示的目录,包括任何必须但不存在的父目录 (多级文件夹),返回是否成功
               
4.遍历         1.String[]     list()    返回一个String数组,表示File类目录中所有子文件或者目录
               2.File[]      listFile()  返回一个File数组 ,表示File类目录中所有子文件或者目录
               注意事项    
          				list()listFile()遍历的是构造方法中给出的目录
                       如果构造方法中给出的目录路径不存在会报空指针异常
                       目录和构造方法中的目录不一致也会报空指针异常
4.递归
  • 递归:指在当前方法中内调自己的这种现象

  • 分类

    • 直接递归 方法自身调用自己
    • 间接递归 A方法调用B,B方法调用C,C方法调用A
  • 注意事项

    • 递归一定要有条件限制 递归要保证能够停下来 否则会发生堆栈溢出
    • 在递归中有限定条件但是也不能递归次数太多,否则也会发生堆栈溢出
    • 构造方法禁止递归
  • 使用前提
    当调用方法时,方法的主体不变,每次调用方法的参数不同,可以使用递归

5.文件过滤器
  • 在File类中有两个和isFiles()重载的方法,方法的参数传递就是过滤器
 File[]   listFiles(FileFilter filter) 
 File[]   listFiles(FilenameFilter filter)
  • 1.过滤文件(File对象)
    java.io.FileFilter接口
    用于抽象路径名(File对象)的过滤器

    boolean     accept(File  pathname) 
    用于过滤文件的方法,测试指定抽象路径是否应该包含在某个路径名称中
    File pathname :使用ListFiles方法遍历目录得到每一个文件对象 
    
  • 2.用于过滤文件名称
    java.io.FilenameFilter接口
    实现此接口的类实例可用于过滤器文件名

    boolean    accept(File dir ,String  name)
    测试指定文件是否应该包含在某一文件列表中
    
  • 3.案例

    (FilenameFilter也可以)这里用FileFiter举例
    1.定义一个方法  参数传递File类型的目录   方法对目录进行遍历
    public  static void FileFilterImpl() implements FileFilter{
       @Override
        public boolean accept(File pathname){
           return pathname.isDirectory()||pathname.getName().toLowerCase.endWith(".java");
       }
    }
    public static void getAllFile(File dir ){
         File[]  files  =dir.listFiles(new FileFilterImpl()) ;  //传过滤器对象
         for(File f :files) {
                    if(f.isDirectory()){
                       getAllFile(f);
                    }else{
                    System.out.println(f);
                    }
         }
    } 
    2.使用匿名内部类版本 
       public static void getAllFile(File dir ){
            File[]  files  =dir.listFiles(new FileFilter(){
                  @Override
                  public boolean accept(File pathname){
                   return pathname.isDirectory()||pathname.getName().toLowerCase.endWith(".java");
                  }
            }) ;  //传过滤器对象
            for(File f :files) {
                       if(f.isDirectory()){
                          getAllFile(f);
                       }else{
                       System.out.println(f);
                       }
            }
      } 
    3. 使用Lambda表达式优化省略版本
      public static void getAllFile(File dir ){
        File[]  files =dir. listFiles(pathname->pathname.isDirectory()||pathname.getName().toLowerCase().endWith(".java"));
      } 
    

二、IO流概述

  • IO:输入/输出(Input/Output)
  • 流: 是一种抽象概念,是对数据传输的总称。也就是说数据在设备间的传输称为流,流的本质是数据传输
  • IO 流就是用来处理设备间数据传输问题的。常见的应用:文件复制;文件上传;文件下载
    在这里插入图片描述
1.分类选择
  • 按照数据的流向

    1. 输入流:读数据
    2. 输出流:写数据
  • 按照数据类型来分

    1. 字节流
      • 字节输入流
      • 字节输出流
    2. 字符流
      • 字符输入流
      • 字符输出流
  • IO流的使用场景

    • 如果操作的是纯文本文件,优先使用字符流
    • 如果操作的是图片、视频、音频等二进制文件。优先使用字节流
    • 如果不确定文件类型,优先使用字节流。字节流是万能的流
2.IO异常的处理
1.在JDK1.7之后可以增加一个(),在括号中定义流对象
  那么这个流对象的作用域就在try中有效
  try中代码制定完毕会自动把流释放,不用finally 
  
2.格式try (定义流对象){
          可能产生异常的代码
       } catch(异常类变量  变量名){
          异常处理逻辑
       } 
       
3.  
    try(FileWriter fw =new FileWriter(D:\\a.txt)){
        for(int i=0;i<10;i++){
            fw.write("你好"+"\n");
        }
   }catch(TOException e){
       System.out.println(e);
   }
3.Properties属性集

点击查看父类Hashtable
java.util.Properties集合

  • 上层父类:Hashtable
    Properties类表示了一个持久的属性集。Properties可以保存在流中或者从流中加载

  • Properties是唯一一个和IO流结合的集合
    可以使用Properties集合中的方法store()把集合中的临时数据持久化写入到硬盘中存储
    可以使用Properties集合中的犯法load(),把硬盘中的文件(键值对),读取到集合中使用

  • 使用

    1.使用Properties集合中存储取出数据
      Properties是一个双列集合,key和value默认是String
    
    2.操作字符串的方法 
            Object    setProperty(String key,String value ) 调用Hashtable中的方法put
            String    getProperty(String key) 通过key找到值相当于Map集合中的get(Key key)
            set<String>   stringPropertyNames()  返回此属性的键集,其中该键及其对应值是String
                                      相当于Map集合中的keySet()
                                      
    3.Properties遍历集合 
            Properties prop =new Properties();
            prop.setProperty("姓名","张三");
            prop.setProperty("性别","男"); 
            prop.setProperty("年龄",18); 
            Set<String > set =new prop.stringPropertyNames();
            for(String key:set){
                  String value = prop.getProperty(key);
                  System.out.println(key+"="+value);
            } 
    
  • 输出流应用store()

    1.可以使用Properties集合中的方法store 把集合中的临时数据,持久化写入硬盘
       void   store(OutStream out,String  comments)
       void   store(Writer writer,String  comments)  
       参数    OutputStream out  字节输出流,不能写中文 
              Writer writer     字符输出流, 能写中文 
              String comments   注释:用来说明保存的文件是做什么的用的(显示在目的地第一行),
                                    不能用中文写,一般用""空字符串
                                    
    2.使用步骤
              1.创建Properties集合对象,添加数据
              2. 创建字节/字符输出流,构造方法中绑定输出目的地
              3.使用Properties集合中的方法store(),把集合中的临时数据,持久化写入硬盘
              4.释放资源(关闭输出流)
              
     3.案例
            Properties prop =new Properties();
            prop.setProperty("姓名","张三");
            prop.setProperty("性别","男"); 
            prop.setProperty("年龄",18); 
            prop.store(new FileWriter("D:\\a.txt"),""); 
    
  • 输入流应用load()

    1.可以使用Properties集合中的方法load 把硬盘中保存的文件(键值对),读取到集合中使用
       void   store(InputStream inputStream)
       void   store(Reader reader)  
       参数    IutputStream inputStream 字节输入流,不能写中文 
              Reader reader     字符输入流, 能写中文 
             
                                    
    2.使用步骤
              1.创建Properties集合对象
              2.使用Properties集合中的方法load()读取保存键值对的文件
              3.遍历Properties集合
              
    3.注意事项:
               1.存储在键值对的文件中,键与值连接符号可以使用 =  空格 (其他符号)
               2.存储在键值对的文件中,可以使用#进行注释,不会再被读取
               3.存储在键值对的文件中,键值都是默认字符串,不用再加引号
    

三、字节流

一切文件数据(文本、图片、视频等)在传输时,都是以二进制数字形式保存
字节流可以传输任意数据

  • 字节流抽象类
    InputStream:表示字节输入流的所有类的超类
    OutputStream:表示字节输出流的所有类的超类
    子类名特点:子类名称都是以其父类名作为子类名的后缀
1.字节输出流(OutputStream)

java.io.OutputStream抽象类是表示字节输出流的超类 字节输出流

  • 1.常用方法

    1.void      close() 关闭此输出流并释放相关的资源 有异常要抛出
     
    2.void      flush() 刷新输出流并强制任何缓冲的输出字节被写出
    
    3.void      write(byte[] b): 将B.length字节从指定的字节数组写入输出流
     注意事项:1.如果第一个字节是正数:(0-127)  显示会查询ASCLL码表
             2.如果第一个字节是负数:第一个字节会和第二个字节组成一个中文显示,查Unicode表
                                    
      void      write(byte[] b,int  start,int len):
      从指定的字节数组写入len字节 从start开始输出到此输出流。把字节数组的一部分写入到文件中
      
    4.abstract void        write(int b) 将指定的字节输出流 
    
  • 2.文件字节输出流( FileOutputStream )
    java.io.FileOutputStream extends OutputStream
    文件字节输出流
    把内存的数据写入到硬盘的文件中

  • 构造方法

    1.FileOutputStream(String name):创建一个具有指定名称的文件写入数据的输出文件流
       FileOutputStrem(File  file) :创建一个向指定File文件对象表示的文件写入数据的文件输出流
       
    2. 参数:写入数据的目的
            String name:目的地是一个文件的路径
            File  file :目的地是一个文件
            
    3. 构造方法的作用
            1.创建一个FileOutputStrem对象
            2.会根据构造方法传递的文件/路径创建一个空文件夹 
            3.会把FileOutputStream对象指向创建好的文件夹 
    
  • 使用

    1.写入数据的原理(内存-->硬盘)
            java程序-->JVM-->OS(操作系统) -->OS调用写数据方法-->把数据写到文件中
    
    2.字节输出流的使用步骤 
            1. 创建一个FileOutputStream对象,将构造方法中传递写入目的地
            2.调用FileOutputStream对象中的方法write()将数据写入到文件中
            3.释放资源(流使用会占用一定的内存,使用完毕后要把内存清空,提高程序的效率) 
            
    3.换行   
    	写换行符号 
    	windows : \r   \n
    	linux   : /n
    	mac     :  \r
            
    4.举例:
            FileOutputStream fos =new FileOutputStream("D:\\a.text") 
            //写一个
            fos.write(48);//0
            
            //写多个
            byte[]  bts = {65,66,67,68,69}//ABCDE
            fos.write(bts,1,2);//BC
            
            //写字符串
            byte[]  bts2 ="你好".getButes();
            fos.write(bts2);
            
            fos.write()
            fos.close(); 
             
    
2.字节输入流(InputStream)

java.io.InputStream抽象类
表示字节输入流的超类 字节输入流

  • 常用方法

    1.int      read() 从输入流中读取数据的写一个字节并返回,读取完毕返回-1
    
    2.int      read(byte[]  b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中
    
    3.void     close()   关闭此输入流并释放相关的资源 有异常要抛出
    
  • 文件字节输入流( FileInputStream )
    java.io.FileInputStream extends InputStream 文件字节输入流
    把硬盘中的文件数据读取到内存中使用

    • 使用

      1.写入数据的原理(内存-->硬盘)
              java程序-->JVM-->OS(操作系统) -->OS调用读取数据方法-->读取数据文件
      
      2.字节输出流的使用步骤 
              1. 创建一个FileIutputStream对象,将构造方法中传递读取目的地
              2.调用FileIutputStream对象中的方法read()将数据读取文件
              3.释放资源
              
      3.字节流读取文本时,如果遇到中文字符可能不会显示完整的字符,
      因为中文字符可能占用多个字节存储,导致乱码
         此时建议用字符流读取
         GBK :占用两个字节
         UTF-8:占用三个字节
         
      4.举例:
         FileIutputStream fis =new FileIutputStream("D:\\a.text")
          //读一个 
          int len =fis.read();//a-->97
          System.out.print(char(len));//a
          
        //读多个
         int len =fis.read();
         while((len=fis.read())!=-1){//abc
           System.out.print(char(len));//abc
         }
         
         //自定义长度读取  1K
         byte[] byts =new byte[1024]
         int len =fis.read();
         while((len=fis.read(byts))!=-1){//abc
           System.out.print(char(len));//abc
         }
         fis.close(); 
      
      • 文件复制练习
        public  static void main(String[] args) throws IOException{
              //创建流
              FileIutputStream fos =new FileIutputStream("D:\\a.text") 
              FileOutputStream fis =new FileOutputStream("E:\\a.text") 
              
              //读取
              int  len =0;
              byte[]  bytes =new byte[1024];
              while ((len=fis.read(bytes))!=-1) {
                    fis.write(len);
              }
              //释放资源
              fis.close();
              fos.close();
        }
        

四、字符流(和字节流用法基本一样)

以字符问单位进行读写数据,专门用于处理文本文件

  • 字节流抽象类
    • Reader:表示字符输入流的所有类的超类
    • Writer:表示字符输出流的所有类的超类
    • 子类名特点:子类名称都是以其父类名作为子类名的后缀
1.字符输入流(Reader)

java.io.Reader抽象类时表示用于输入字符流的所有类的超类 字符输入流
基本用法和方法跟字节流一样,不写了

  • 文件字符输入流( FileReader )
    java.io.FileReader extends InputStreamReader extends Reader
    把硬盘中的文件数据以字符的方式读取到内存中使用
    用法同文件字节输入流
2.字符输出流(Writer)

java.io.Writer抽象类时表示用于读取字符流的所有类的超类 字符输出流
基本用法和方法跟字节流一样,不写了

  • 文件字符输出流( FileWriter )
    java.io.FileWriter extends InputStreamWriter extends Writer
    把内存的数据写入到硬盘的文件中
    用法同文件字节输出流

五、其他流

1.缓冲流/高效流

缓冲流,也叫高效流,是对四个基本FileXX流的增强

  • 分类
    • 字节缓冲流
      BufferedIuputStream
      BufferedOutputStream
    • 字符缓冲流
      BUfferedReader
      BufferedWriter

用法类似详细了解请查看wqg_code的博客IO—转换流和缓冲流总结

2.转换流
  • OutputStreamWriter
    创建一个新的缓冲输出流,以数据写入指定的底层输出流
  • IutputStreamReader
    创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流

用法类似详细了解请查看wqg_code的博客IO—转换流和缓冲流总结

3.打印流

java.io.PrintStream
extends OutputStream
打印流
PrintStream为其他输出流添加了功能,使他们能方便的打印各种数据表示形式

  • 打印流特点

    • 只负责输出,不负责读取
    • 与其他输出流不同,PrintStream永远不会抛出IOException
    • 特有方法print,println
      void print(任意类型的值)
      void println(任意类型的值并换行)
      
  • 构造方法

       PrintStream(File file):输出的目的地是一个文件
         PrintStream(OutputStream out )输出的目的地是一个文件字节流
         PrintStream(String fileName):输出的目的地是一个文件路径
    
  • 注意事项:
    如果使用继承自父类的方法写数据 那么查看数据的时候会查询编码表 97->a
    如果使用自己特有的print/println方法会原样输出 97->97

六、字符编码

1.ASCLL码表

美国信息交换标准代码,是基于拉丁字母的一套电脑编码系统,用于显示现代英语,主要控制字符(回车、退格、换行)
等可显示字符(英文大小写字符、阿拉伯数字和西文符号)

基本ASCLL码字符集使用7(bit)表示一个字符,共128个字符。ASCLL扩展字符集使用8(bit)表示一个字符,共256字符方便支持欧洲常用字符

2.ISO-8859-1字符集

拉丁码表,别名Latin-1,用于显示欧洲常用的语言,比如荷兰、丹麦、德语、意大利语、西班牙语等
ISO-8859-1使用单字节编码,兼容ASCLL码表

3.GBK

GBXXX系列,国标,用于显示中文而设计的一套字符集
GBK:最常用的中文码表。实在GB2312基础上扩展规范使用了双字节编码放啊,共收录了21003个汉字。同时支持繁体中文、日文、韩文

4.Unicode字符集

Unicode编码自用是为了表达任意语言设计的业界标准的,统一码,万国码
它最多使用四个字节来表达每个字母、符号、或者问题。有三种编码方案,UTF-8、UTF-16、UTF-32。UTF-8最常用

七、序列化和反序列化

1.Java序列化的机制
  • 序列化:用一个字节表示一个对象,该序列包含的对象的数据、对象的类型、对象存储的属性等信息
    字节序列化写到文件后,相当于文件中持久保存了一个对象的信息

  • 反序列化,从文件重构对象,反序列化。将对象的数据、对象的类型、对象存储的属性等信息用来在内存中创建对象

  • 序列化和反序列化的时候会抛出NotSerializableException 没有序列化异常
    需要序列化的对象所在的类需要实现java.io.Serizlizable接口以启动其序列化功能

2.Serializable接口

标记型接口
要进行序列化和反序列化的类必须实现Serializable接口,就会给类加一个序列化标记
当继续进行序列化或者反序列化时,就是检测类上是否有这个标记

  • 有,可以序列化和反序列化
  • 没有,抛出没有序列化异常
    在这里插入图片描述
3.ObjectOutputStream

java.io.ObjectOutputStream extends OutputStream 对象的序列化流
把对象以流的方式写入到文件中保存

1. 构造方法
 	ObjectOutputStream (OutputStream out):创建一个写入执行OutputStream的ObjectOutputStream
    OutputStream out:字节输出流
4. 成员方法: 
       void writerObject(Object obj)  将指定的对象写入ObjectOutputStream
  • 使用
1. 字节输出流的使用步骤 
       1.创建ObjectOutputStream,构造方法中将OutputStream作为参数传递进去
       2.调用ObjectOutputStream对象中的方法writeObject()将数据写入到文件中
       3.释放资源,默认先调用flush()                   
2. 举例:
        FileOutputStream fos =new FileOutputStream("D:\\a.text") 
        ObjectOutputStream oos =new ObjectOutputStream(fos);
        bos.writeObject(new Person("张三","18","男"));
        //Person类必须实现Serializable接口,否则报没有序列化
        bos.close();
3.ObjectInputStream

java.io.ObjectInputStream extends InputStream 对象的反序列化流
把文件中保存的对象以流的形式读取

成员方法: 
void    readObject()  将指定的对象写入ObjectOutputStream 

其他地方用法一样,就这个方法不同。一个序列化方法,一个是反序列化方法

  • 注意事项
1.readerObject方法中抛出了ClassNotFountException(文件找不到异常)
  当不存在对象时抛出异常
       反序列化前提:1.类必须实现Serializable接口
                   2.类必须存在类对应的class文件
                       
2.当JVM反序列化时,能找到class文件但是序列化对象之后发生了修改,
   反序列化失败抛出InvalidClassException
       如何解决:手动添加序列号
       
3.手动写序列号
       格式在Serializable接口规定:
            可序列化类通过声明seriaIVersionUID的字段(必须 static final long修饰)显示声明其自己的序列号
             static final long seriaIVersionUID=42L //常量  不能改变      
4.transient关键字
  • static 关键字:静态关键字
    静态优先于非静态加载到内存中(静态优先于对象进入到内存中)
    被static 修饰的成员变量不能被序列化,序列化的都是对象

  • transient关键字 瞬态关键字
    被transient修饰的成员变量不能被序列化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码为海

你的支持是我更新最大得动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值