11-JavaSE【字节流、字符流,IO异常处理,Properties属性集,ResourceBundle 工具类】

Lambda表达式

  • 应用:简化匿名内部的代码书写

    • 要求:只能针对函数式接口进行操作
  • 语法:

    • (参数列表) -> {
          //方法体代码
      }
      
    • //针对函数式接口:Comparator,使用匿名内部类
      Collections.sort(list, new Comparator<String,String>(){
          //重写compare方法
          public int compare(String s1, String s2){
              //....
          }
      });
      
      //针对函数式接口:Comparator,使用Lambda
      Collections.sort(list, (String s1, String s2) -> {
              //....
          }
      );
      
  • 基于标准语法,进行省略:

    • //省略:参数
      //1、省略参数列表中所有的参数类型
      //2、当参数列表中仅有一个参数时,可以省略参数类型、小括号
      
      //省略:方法体
      //当方法体中仅有一个行代码时:可以省略 大括号、return、分号
      

Stream流

  • 应用:针对集合、数组进行操作

  • Stream流:获取流、中间操作、终端操作

    • 获取流:

      • //集合
        Stream s1 = list.stream();
        Stream s2 = set.stream();
        Stream s3 = map.keySet.stream();
        Stream s4 = map.entrySet().stream();
        
        //数组
        Stream s = Stream.of(数组[]);
        
    • 中间操作(常用API方法)

      • filter()
        limit(n)
        skip(n)
        distinct()
        map()
        sorted(Comparator c)    
        
    • 终端操作(API方法)

      • forEach()
        count()
        collect( toList )    
        

File类

  • 应用:为了创建一个基于硬盘上的文件和目录的对象

    • //用户类
      public class User{
          String name;//登录名
          String passwd;//密码
          
          Date registerDate; //用户的注册时间
          File  file;   //用户肖像
      }
      
  • 构造方法:

    • public File(String path)
      public File(String parent , String child)
      public File(File parent , String child)
      
  • 常用方法:

    • 获取功能

      • //文件名
        String  getName()
            
        //文件大小
        long  length()
            
        //文件修改时间
        long  lastModified()     
        
    • 判断功能

      • //文件是否存在
        boolean exists()
        
        //是文件
        boolean isFile    
        
    • 创建删除功能

      • //创建文件
        createNewFile()
        
        //创建目录
        mkdir()   //要求:父路径必须存在
        mkdirs()  //父路径不存在时,会先创建父路径
            
        //删除目录、文件
        delete()    
        
    • 目录遍历

      • String[]  list() //获取目录下所有文件或文件夹的名称
        File[]  listFiles()  //获取当前目录下所有文件或目录的对象   
        

递归

  • 概念: 递归是应用在方法上的, 方法自己调用自己
  • 递归实现:
    • 递进
    • 边界值 (为了约束递归,不能让递归实现死循环)
    • 回归
  • 递归的弊端:递归时会调用方法入栈执行,当递归次数过多时会造成栈内存空间占满,造成内存溢出

今天内容:

  • IO:字节流 (重点)
  • IO:字符流 (重点)
  • Properties属性集
  • ResourceBundle(类似于Properties)

一、IO流

IO概念:

  • IO:计算机中设备之间数据传输使用的技术
  • Java中的IO: 都在java.io包下
    • 字节流:
      • 字节输入流
      • 字节输出流
    • 字符流:
      • 字符输入流
      • 字符输出流
  • IO流分类:
    • 字节输入流
    • 字节输出流
    • 字符输入流
    • 字符输出流
  • IO流的父类:
    • 字节输入流:java.io.InputStream
    • 字节输出流:java.io.OutputStream
    • 字符输入流:java.io.Reader
    • 字符输出流:java.io.Writer

1、IO概述

在操作计算机时,把数据存储到计算机的硬盘上,从硬盘上某个文件中读取数据,

都是需要使用IO流来实现的。

结论:IO流就是实现设备之间的数据传输。(计算机之间进行数据交互,需要借助IO流)

在这里插入图片描述

1)什么叫IO

  • I 就是Input, 表示输入,数据从硬盘(或者外部存储设备)输入 到内存 (读取文件)

  • O 就是Output,表示输出,数据从内存中输出到外部存储设备 (写入文件)

结论:IO是以内存为基准,数据流向内存时为input,数据从内存中流出时为output

2)Java中I/O操作主要是指使用java.io包下的内容,进行输入、输出操作。

输入也叫做读取数据,输出也叫做作写出数据。

java.io.File类:是用来操作文件或目录的 (不能对文件中存储的内容进行操作)

如果要对文件中存储的内容进行操作:读、写 ,需要使用java.io包下的InputStream、OutputStream

3)IO流分类

根据数据的流向分为:输入流输出流

  • 输入流 :把数据从其他设备上读取到内存中的流。 读数据
  • 输出流 :把数据从内存 中写出到其他设备上的流。 写数据

根据数据的类型分为:字节流字符流

  • 字节流 :以字节为单位,读写数据的流。(万能流:可以对任何类型的文件进行读写操作)
  • 字符流 :以字符为单位,读写数据的流。(只能针对文本文件进行读写操作)

2、字节流(一切皆字节)

一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都是一个一个的字节,那么传输时一样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据。

1)OutputStream字节输出流

java.io.OutputStream抽象类是表示字节输出流的所有类的超类将指定的字节信息写出到目的地。它定义了字节输出流的基本共性功能方法。

public void close() // 关闭此输出流并释放与此流相关联的任何系统资源。 
    
public void flush() // 刷新此输出流并强制任何缓冲的输出字节被写出。  
    
public void write(byte[] b) // 将 b.length 字节从指定的字节数组写入此输出流。
    
public void write(byte[] b, int off, int len) // 从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。  
    
public abstract void write(int b) // 指定的字节输出流。

**注意:**close() 方法,当完成流的操作时,必须调用此方法,释放系统资源。

01、FileOutputStream类

java.io.FileOutputStream类是文件输出流,用于将数据写出到文件。(是OutputStream的子类)

构造方法
public FileOutputStream(File file) // 创建文件输出流以写入由指定的[File对象]表示的文件。
    
public FileOutputStream(String name) // 创建文件输出流以指定的[名称]写入文件。 
    
// 1. 使用File对象创建流对象
File file = new File("a.txt");
FileOutputStream fos = new FileOutputStream(file);
      
// 2. 使用文件名称创建流对象
FileOutputStream fos = new FileOutputStream("b.txt");
写出字节数据

写出一个字节:write(int b)方法

写出字节数组:write(byte[] b)方法

写出指定长度字节数组write(byte[] b, int off, int len)方法

// 1. write(int b) 写数据   
// 使用文件名称创建流对象
FileOutputStream fos = new FileOutputStream("fos.txt");     
// 虽然参数为int类型四个字节,但是只会保留一个字节的信息写出。
fos.write(97); // 写出第1个字节
fos.write(98); // 写出第2个字节

// 2. write(byte[] b)方法
FileOutputStream fos = new FileOutputStream("fos.txt");     
// 字符串转换为字节数组
byte[] b = "祖国你好".getBytes();
// 写出字节数组数据
fos.write(b);

// 3. write(byte[] b, int off, int len) 方法
FileOutputStream fos = new FileOutputStream("fos.txt");     
// 字符串转换为字节数组
byte[] b = "abcde".getBytes();
// 写入在b数组中-》从索引2开始,取长度为2个字节
fos.write(b,2,2);

fos.close();
数据追加续写

每次程序运行,创建输出流对象,都会清空目标文件中的数据。如何保留目标文件中数据,还能继续添加新数据呢?

public FileOutputStream(File file, boolean append) // 创建文件输出流以写入由指定的 File对象表示的文件。  
    
public FileOutputStream(String name, boolean append) // 创建文件输出流以指定的名称写入文件。
    
// 例如:
 // 使用文件名称创建流对象
FileOutputStream fos = new FileOutputStream("fos.txt"true);     
// 字符串转换为字节数组
byte[] b = "追加数据".getBytes();
// 把数组中的数据写入文件中
fos.write(b);
// 关闭资源
fos.close();

true 表示追加数据,false 表示清空原有数据。这样创建的输出流对象,就可以指定是否追加续写了。

注意:

Windows系统里,换行符号是\r\n

Unix系统里、Mac系统里\n

回车符\r和换行符\n

  • 回车符:回到一行的开头(return)
  • 换行符:下一行(newline)

写出一个换行, fos.write("\r\n".getBytes());

2)InputStream字节输入流

java.io.FileInputStream抽象类是表示字节输入流的所有类的超类,可以读取字节信息到内存中。(是OutputStream的子类)

  • public void close() :关闭此输入流并释放与此流相关联的任何系统资源。
  • public abstract int read(): 从输入流读取数据的下一个字节。
  • public int read(byte[] b): 从输入流中读取一些字节数,并将它们存储到字节数组 b中 。
01、FileInputStream类
构造方法
File file = new File("a.txt");
FileInputStream fos = new FileInputStream(file); // 使用File对象创建流对象

FileInputStream fos = new FileInputStream("b.txt"); // 使用文件名称创建流对象

tip:创建一个流对象时,必须传入一个文件路径。

该路径下,如果没有该文件,会抛出FileNotFoundException

读取字节数据

read方法,每次可以读取一个字节的数据,提升为int类型,读取到文件末尾,返回-1

read(byte[] b),每次读取b的长度个字节到数组中,返回读取到的有效字节个数,读取到末尾时,返回-1

// 1.没次读取一个字节
FileInputStream fis = new FileInputStream("read.txt"); // 文件中为abcde

int read = fis.read();
System.out.println((char) read);

// 定义变量,保存数据
int b ;
// 循环读取 --》 读取到文件末尾(循环结束)
while ((b = fis.read())!=-1) {
   System.out.println((char)b);
}


// 2. 每次读取b的长度个字节到数组中
FileInputStream fis = new FileInputStream("read.txt"); // 文件中为abcde
// 定义变量,作为有效个数
int len ;
// 定义字节数组,作为装字节数据的容器   
 byte[] b = new byte[2];
// 循环读取(可能会有错误!!)
while (( len= fis.read(b))!=-1) {
    // 每次读取后,把数组变成字符串打印
    System.out.println(new String(b));
}
----------
输出结果:
ab
cd
ed   // d 为无效字符

// 3. 避免 2 中的无效输出 字符
// 循环读取的改进
while (( len= fis.read(b))!=-1) {
    // 每次读取后,把数组的有效字节部分,变成字符串打印
    System.out.println(new String(b,0,len)); // len 每次读取的有效字节个数
}

// 关闭资源  
fis.close();  // 操作结束后一定不要忘了这句
-----------
输出结果:
ab
cd
e

tip1:错误数据d,是由于最后一次读取时,只读取一个字节e,数组中,上次读取的数据没有被完全替换,所以要通过len ,获取有效的字节。

tip2:使用数组读取,每次读取多个字节,减少了系统间的IO操作次数,从而提高了读写的效率,建议开发中使用。

3)复制图片文件(案例)
public class Copy {
    public static void main(String[] args) throws IOException {
        // 1.创建流对象
        // 1.1 指定数据源
        FileInputStream fis = new FileInputStream("D:\\test.jpg");
        // 1.2 指定目的地
        FileOutputStream fos = new FileOutputStream("./test_copy.jpg");

        // 2.读写数据
        // 2.1 定义数组
        byte[] b = new byte[1024];
        // 2.2 定义长度
        int len;
        // 2.3 循环读取
        while ((len = fis.read(b))!=-1) {
            // 2.4 写出数据
            fos.write(b, 0 , len);
        }

        // 3.关闭资源
        fos.close();
        fis.close();
    }
}

3、字符流

当使用字节流读取文本文件时,遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件

1)Reader 字符输入流

java.io.Reader抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。

  • public void close() :关闭此流并释放与此流相关联的任何系统资源。
  • public int read(): 每次可以读取一个字符的数据,提升为int类型,读取到文件末尾,返回-1
  • public int read(char[] cbuf): 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中
FileReader类

java.io.FileReader类是读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。

tips:

  1. 字符编码:字节与字符的对应规则。Windows系统的中文编码默认是GBK编码表。

    idea中UTF-8

  2. 字节缓冲区:一个字节数组,用来临时存储字节数据。

  3. 当创建一个流对象时,必须传入一个文件路径。类似于FileInputStream 。该路径下,如果没有该文件,会抛出FileNotFoundException

构造方法

// 使用File对象创建流对象
File file = new File("a.txt");
FileReader fr = new FileReader(file);

// 使用文件名称创建流对象
FileReader fr = new FileReader("b.txt");
// 使用文件名称创建流对象
FileReader fr = new FileReader("read.txt");
// 定义变量,保存有效字符个数
int len ;
    // 定义字符数组,作为装字符数据的容器
    char[] cbuf = new char[2];
// 循环读取
while ((len = fr.read(cbuf))!=-1) {
    System.out.println(new String(cbuf,0,len));
}
// 关闭资源
fr.close();
2)Writer字符输出流

java.io.Writer抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地。

  • public abstract void close() :关闭此输出流并释放与此流相关联的任何系统资源。
  • public abstract void flush() :刷新此输出流并强制任何缓冲的输出字符被写出。
  • public void write(int c) :写出一个字符。
  • public void write(char[] cbuf):将 b.length字符从指定的字符数组写出此输出流。
  • public abstract void write(char[] b, int off, int len) :从指定的字符数组写出 len字符,从偏移量 off开始输出到此输出流。
  • public void write(String str) :写出一个字符串。
FileWriter类

java.io.FileWriter类是写出字符到文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。

tip:当你创建一个流对象时,必须传入一个文件路径,类似于FileOutputStream。

构造方法

// 使用File对象创建流对象
File file = new File("a.txt");
FileWriter fw = new FileWriter(file);

// 使用文件名称创建流对象
FileWriter fw = new FileWriter("b.txt");

写出字符write(int b) 方法,每次可以写出一个字符数据

tips:

  1. 虽然参数为int类型四个字节,但是只会保留一个字符的信息写出。
  2. 未调用close方法,数据只是保存到了缓冲区,并未写出到文件中。
  • flush :刷新缓冲区,流对象可以继续使用。
  • close :关闭流,释放系统资源。关闭前会刷新缓冲区。

tip:即便是flush方法写出了数据,操作的最后还是要调用close方法,释放系统资源。

write(char[] cbuf)

write(char[] cbuf, int off, int len)

每次可以写出字符数组中的数据,用法类似FileOutputStream

tip:字符流,只能操作文本文件,不能操作图片,视频等非文本文件。

当我们单纯读或者写文本文件时 使用字符流 其他情况使用字节流


二、IO资源处理

JDK7以前异常处理方式
try{
	IO资源的访问代码
}catch(IOException e){
	处理异常
}finally{
  	释放IO资源(调用close)
}
JDK7版本开始

对于IO资源的处理有种新的方式:try-with-resource

这种方式最大的好处是,不用程序员自己调用close方法释放资源了,会自动释放资源

格式:

try(资源1;资源2;资源3){
  //操作资源
}catch(IOException e){
  //处理异常
}
//注:创建资源如果有多个,使用分号进行分割

如果一个资源的类型是AutoCloseable接口的实现类,就可以去使用try-with-resource方式处理

在这里插入图片描述

结论:字节流、字符流都可以使用try-with-resource方式进行释放资源

tip:流对象必须有实现AutoCloseable接口,才可以激活使用:try…with…resource


三、Properties属性集

  • java.uitl.Properties 类表示了一个持久的属性集(属性列表)

  • Properties 中的数据以K-V形式存储

  • Properties 可保存在流中或从流中加载

继承体系:

在这里插入图片描述

结论:Properties就是一个Map的实现类,维护的数据也是键值对信息。键和值都是String类型

Properties类中方法

构造方法:

Properties()    //创建一个无默认值的空属性列表

常用方法: (和流无关的方法)

 Object setProperty(String key, String value)   //存储K-V数据    相当于Map中的put方法

 String getProperty(String key)   //根据给定的key,获取对应的Value元素    相当于Map中get方法
   
 Set<String> stringPropertyNames() //获取所有Key元素的集合   //相当于Map中keySet方法

案例代码

public class PropertiesDemo1 {
    //案例:使用Properties类存储的数据并遍历
    public static void main(String[] args) {
        //创建Properties对象
        Properties pro = new Properties();

        //添加KV元素
        pro.setProperty("name","com.Student");
        pro.setProperty("method","study");
        pro.setProperty("paramter","java.lang.String");

        //获取所有的Key元素
        Set<String> set = pro.stringPropertyNames();
        //遍历Set集合
        for(String key : set){
            //通过key元素,获取Value元素
            String value = pro.getProperty(key);
            System.out.println(key+"="+value);
        }

        //set.stream().forEach((String s) -> System.out.println(s));

    }
}
Properties的流方法

Properties类可以去借助输入流输出流去保存(写)或者加载(读)属性集文件信息

属性集文件,就是由键值对格式形成的文件。 如:mysql.properties

username=root
password=1234

和流有关的方法:

 void load(InputStream inStream)   
          //从输入流中读取属性列表(键值对)
 void load(Reader reader) 
          //按简单的面向行的格式从字符输入流中读取属性列表(键值对)

 //扩展方法:    
 void store(OutputStream out, String comments) 
          //将Properties中的属性列表(键值对)写入输出流  
 void store(Writer writer, String comments) 
          //将Properties中的属性列表(键值对)写入输出流
//说明:
out/writer: 输出流,关联保存数据的文件
comments:  注释

案例代码

需求:加载属性集文件

public class PropertiesDemo2 {
    public static void main(String[] args) {
        try {
            method();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void method() throws IOException {
        //创建Properties对象
        Properties pro = new Properties();

        //使用load方法,加载pro.properties文件
        //相对路径:相对当前项目工程 
        pro.load(new FileInputStream("javase_day12/src/pro.properties"));

        //从Properties对象中获取属性
        String location = pro.getProperty("location");
        String fileName = pro.getProperty("filename");
        String length = pro.getProperty("length");

        System.out.println(location);
        System.out.println(fileName);
        System.out.println(length);

    }
}

tip:文本中的数据,必须是键值对形式,可以使用空格、等号、冒号等符号分隔


四、 ResourceBundle工具类

Properties工具类,它能够读取资源文件,当资源文件是以.properties结尾的文件时,

我们可以使用JDK提供的另外一个工具类ResourceBundle来对文件进行读取,使得操作更加简单。

java.util.ResourceBundle它是一个抽象类,我们可以使用它的子类PropertyResourceBundle来读取以.properties结尾的配置文件。

  1. 获取ResourceBundle对象

    ResourceBundle bundle = ResourceBundle.getBundle("属性文件名称")//名称不能包含后缀名
    //属性集文件必须存放在src目录下    
    
  2. 使用ResourceBundle对象中的getString()方法,获取属性的值(key对应的value)

    String value = bundle.getString("属性名");
    
//第一种方式:多态
//ResourceBundle rb =  new PropertyResourceBundle();

static ResourceBundle getBundle(String baseName) //根据名字直接获取属性资源
//参数说明:baseName 
  //1. 属性集名称不含扩展名 //例:mysql.properties文件    baseName取:mysql
  //2. 属性集文件是在src目录中的
  
//示例:src中存在一个文件 mysql.properties
ResourceBundle bundle = ResourceBundle.getBundle("mysql");

常用方法:

 String getString(String key)  //通过键,获取对应的值
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

编程小栈

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值