Java: IO流、两种释放资源的方式Properties、commos-io类库

一:IO流

IO流概述

IO流分类

IO流是一块很大的知识体系,让我们一鼓作气学完吧。我认为要真正的学好一个知识点,清晰的框架是必不可少的。那么这里我们就先认识一下IO流体系。

总括:IO流体系

首先,我们先通过一张图片去认识IO流体系

怎么样?是不是清晰明了,循序渐进。可见IO流大体分为两种流:字节流字符流.

字节流可分为:字节输入流(InputStream)字节输出流(OutputStream)

字符流可分为:字符输入流(Reader)字符输出流(Writer)

以上的InputStream、OutputStream、Reader、Writer都是抽象类,以下的几种流:文件流(File)缓冲流(Buffered)字符转换流[(Input/Out)Stream(Reader/Writer)]对象字节流(Object)打印流(Print)都相当于它们四个的实现类

接下来我们将会依次介绍这些流:

1.1 文件流

1.1.1文件字节流

文件字节输入流

实例:

(1)读取字节:

(1)读取字节:
/*1.    创建一个 文件字节输入流管道 与 源文件 接通 */
  //InputStream is=new FileInputStream(new File(".\\Phase2\\resource\\data01.txt"));
        //简化写法:
    InputStream is=new FileInputStream(".\\Phase2\\resource\\data01.txt");
                                                   
/*2.    读取一个字节返回(读取完毕返回-1 !!!)*/
    int b1=is.read();       //read() 每次接一滴水
    System.out.println("第一个字节的编码为:"+b1);
    System.out.println("第一个字节为:"+(char)b1);

/*3.    使用循环改进,定义一个变量记录每次读取的字节
*       w   2    国
*       o   o   [ooo]     -->几个字节(UTF-8) */
    int b;
    while( ( b=is.read() ) != -1){ //一次只读取一个字节,因此遇到三个字节的汉字会报错
        System.out.print((char)b);
    }

(2)读取字节数组:

(2)读取字节数组(读取完毕返回-1):
    InputStream is=new FileInputStream(".\\Phase2\\resource\\data02.txt");
                                                        //data里有5个字节
     //定义一个字节数组,用于读取字节数组
     byte[] buffer =new byte[3];//每次读取3个字节(1个桶每次装3滴水)

     int len1=is.read(buffer);
     System.out.println("第一次读取了几个字节:"+len1);
     String rs1=new String(buffer);
     System.out.println(rs1);

     int len2=is.read(buffer);//这里只剩余2个字节了,打印出来的第3个字节是上一次读取的第3个字节
     System.out.println("第三次读取了几个字节:"+len2);
     String rs2=new String(buffer,0,len2);//但是,可以改进!!! 0的意思是从第1位开始读取,每次读 len3 个字节
     System.out.println(rs2);

      //改进使用循环,每次读取一个字符数组
      byte[] buffer2=new byte[3];
      int len;
      while( (len=is.read(buffer2)) !=-1){
          System.out.print(new String(buffer2,0,len));
       }

(3)读取全部字节:

public static void main(String[] args) throws IOException {
(3)一次性读取所有字节
/* 方式1:  自定义字节数组*/

    //1.创建一个 文件字节输入流管道 与 源文件 接通
    File f=new File(".\\Phase2\\resource\\data03.txt");
    InputStream is=new FileInputStream(f);

    //2.定义一个字节数组与文件的大小一样大
    byte[] buffer=new byte[(int) f.length()];
    int len=is.read(buffer);
    System.out.println("读取的字节为:"+len);
    System.out.println(new String(buffer));

/*方式2:  用API读取字节数组*/
    byte[] buffer2=is.readAllBytes();
    System.out.println(new String(buffer));

 }//main方法的括号
文件字节输出流

实例:

public static void main(String[] args) throws IOException {
/*1.    创建一个 文件字节输出流管道 与 目标文件 接通*/
                                 //加true,不覆盖管道(也就是每次运行不清除之前的数据)
//OutputStream os=new FileOutputStream(".\\Phase2\\resource\\out01.txt",true);
OutputStream os=new FileOutputStream(".\\Phase2\\resource\\out01.txt");

/*2.    写数据出去*/
  //2.1   写一个字节出去
    os.write('x');
    os.write("\r\n".getBytes());(Charset编码API)
    //1.回车换行(换行) 2.兼容性更强 3.这里需要把"/r/n"字符串转换成字节数组再输出
   
   //2.2   写一个字节数组出去
     byte[] buffer1={101,102,103};
     os.write(buffer1);

     byte[] buffer2="我是中国人".getBytes();
   //byte[] buffer2="我是中国人".getBytes("GBK"); 用GBK进行编码
     os.write(buffer2);

     byte[] buffer3={'a','b',99,100};
     os.write(buffer3,0,3);//写一个数组的一部分出去

/*3.    刷新/关闭 流*/
   //os.flush();  写数据,必须刷新数据,可以继续使用流
     os.close();//可以释放资源,包含了刷新!!!关闭了流后不可以继续使用

1.1.2 文件字符流

文件字符输入流

实例:

public static void main(String[] args) throws IOException {
(1)一次读取一个字符
/*1.    创建一个 字符输入流管道 与 源文件 接通*/
    Reader fr=new FileReader(".\\Phase2\\resource\\data04.txt");

/*2.    读取一个字符返回,没有可读的字符则返回-1*/
    int code1=fr.read();
    System.out.println((char)code1);
    
/*3.    定义循环读取字符*/
    int code;
    while ( ( code=fr.read() ) !=-1 ) {
        System.out.print((char)code);//不换行
    }

(2)一次读取一个字符数组
    char[] buffer=new char[1024];//1k字符
    int len;
    while ( (len=fr.read(buffer) ) !=-1 ){
        String rs=new String(buffer,0,len);
        System.out.println(rs);
    }
}
文件字符输出流

实例:

public static void main(String[] args) throws IOException {
/*1.    创建一个 字符输出流管道 与 目标文件 接通*/
  //Writer fw=new FileWriter(".\\Phase2\\resource\\out02.txt");·//覆盖管道,每次启动都会清空之前的数据
    Writer fw=new FileWriter(".\\Phase2\\resource\\out02.txt",true);//继续写

//2.写一个字符出去
    fw.write(98);
    fw.write('a');
    fw.write('赵');//汉字不会出问题了
    fw.write("\r\n");   //换行

//3.写一个字符串出去
    fw.write("abc清澈的爱为中国");
    fw.write("abc清澈的爱为中国",3,7);//从第3个字节开始,写7个字节

//4.写一个字符数组出去
    char[] chars="abc清澈的爱为中国".toCharArray();
    fw.write(chars);
    fw.write(chars,3,7);

//5.
  //fw.flush();       //刷新流后,还可以继续使用
    fw.close();         //关闭流后,不能再继续使用
}

补充:try-catch-finally和try-catch-resource

try-catch-finally:

try-catch-resource:

1.2 缓冲流

1.2.1 文件字节缓冲流

文件字节缓冲输入/输出流

实例:

public static void main(String[] args) {
//1.    创建一个文件输入流管道 与 原图片 相通
    try(        /*try() (括号里面只能放资源对象)无视异常,强行关闭资源*/
    InputStream is = new FileInputStream("D:\\JavaPoint\\Fighting.jpg");//必须有后缀
    InputStream bis= new BufferedInputStream(is);
    /*把原始的 字节输入流 包装成 高级的缓冲字节输入流*/

//2.    创建一个字节输出流管道 与 目标文件接通
    OutputStream os = new FileOutputStream("D:\\JavaPoint\\BufferedFighting.jpg");
    OutputStream bos=new BufferedOutputStream(os);/*把原始的 字节输出流 包装成 高级的缓冲字节输出流*/
){
//3.    定义一个 字节数组 转移数据
    byte[] buffer = new byte[1024];
    int len;    //记录每次读取的字节数
    while ((len = bis.read(buffer)) != -1) {
        bos.write(buffer, 0, len);
    }
    System.out.println("图片复制完成了");
    
    //try-catch-resorce已经关闭流了,不用再释放资源了
} catch (Exception e) {
    e.printStackTrace();
    }
}

1.2.2 文件字符缓冲流

文件字符缓冲输入流

实例:

try {
    Reader fr=new FileReader("D:\\idea\\HM\\Phase2\\resource\\data05.txt");
    
    BufferedReader br=new BufferedReader(fr);//这里要使用BufferedReader的特有功能
    br.readLine();//读一行字符,空行也读,直到读完返回null
    
    String line;
    while( (line = br.readLine()) !=null ){ 
        System.out.println(line);
    }
} catch (Exception e) {
    e.printStackTrace();
}
文件字符缓冲输出流

实例:

 public static void main(String[] args) throws IOException {
/*1.    创建一个 字符输出流管道 与 目标文件 接通*/
Writer fw=new FileWriter(".\\Phase2\\resource\\out02.txt",true);//不覆盖管道

//2.写一个字符出去
    fw.write(98);
    fw.write('a');
    fw.write('赵');//汉字不会出问题了
    fw.write("\r\n");   //换行

//3.写一个字符串出去
    fw.write("abc清澈的爱为中国");
    fw.write("\r\n");
    fw.write("abc清澈的爱为中国",3,7);//部分

//4.写一个字符数组出去
    char[] chars="abc清澈的爱为中国".toCharArray();
    fw.write(chars);
    fw.write(chars,3,7);

//5.
       //fw.flush();       //刷新流后,还可以继续使用
        fw.close();         //关闭流后,不能再继续使用
}

小结:字符缓冲流

1.3 字符转换流

转换流其实就是把字符流转换成字节流。字节流因为是一个字节一个字节读取的,不会出bug,也就没有字节转换流

1.3.1字符转换输入流

为什么要使用字符转换输入流

实例:

代码UFF-8 文件 GBK("D:\idea\HM\Phase2\resource\GBK_data.txt")

public static void main(String[] args) throws Exception {
/*1.    提取GBK文件的原始文件字节流*/
    InputStream is=new FileInputStream(".\\Phase2\\resource\\GBK_data.txt");

/*2.    把 原始文件字节流 转换成 字符输入流 */
    Reader isr=new InputStreamReader(is,"GBK");//以指定的GBK编码转换成字符输入流,完美的的解决了乱码问题
    BufferedReader br=new BufferedReader(isr);
    String line;
    while( (line=br.readLine()) !=null ){
        System.out.println(line);
    }
}

1.3.2 字符转换输出流

为什么要使用字符转换输出流

实例:

public static void main(String[] args) throws IOException {
/*1.    定义一个字节输出流*/
    OutputStream os=new FileOutputStream(".\\Phase2\\resource\\out04.txt");

/*2.    把原始的字节输出流 转换成 字符输出流*/
    Writer osw=new OutputStreamWriter(os);
   //以默认的UTF-8写字符出去,直接写跟FileWriter一样
 
/*3.    把低级的字符输出流 包装成 高级的缓冲字符串输出流 */
    BufferedWriter bw=new BufferedWriter(osw);
    bw.write("我爱中国1");
    bw.write("我爱中国2");
}

1.4 对象字节流

对象序列化与反系列化

序列化是指把对象数据存储到文件中。

反序列化:

实例:序劣化的三个重点

1.对象要序列化,必须实现Serializable接口

2.申明序列化的版本号码(序列化与反序列化的版本号必须一致才不会报错!!!)

3.transient 修饰的成员变量不参与序列化

public class serializable {         //序列化
    public static void main(String[] args) throws Exception {
/*1.    创建学生对象*/
    Student s1=new Student("山姆","sam","123",34);

/*2.    对象序列化:使用 对象字节输出流管道 包装 低级的文件字节输出流管道*/
    ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(".\\Phase2\\resource\\obj.txt"));

/*3.直接调用序列化方法*/
    oos.writeObject(s1);

    oos.close();//关闭资源

//=================反序列化================(序列化和反序列化操作路径一致)
/*1.    创建 对象字节输入流管道 包装 低级的文件字节输入流*/
    ObjectInputStream ois =new ObjectInputStream(new FileInputStream(".\\Phase2\\resource\\obj.txt"));

/*2.    调用对象字节输入流的反序列方法*/
    Student s2=(Student) ois.readObject();
    System.out.println(s2);
    }
}
       
class Student implements Serializable {    
    //1.对象要序列化,必须实现Serializable接口

    private static final  long serialVersionUID=1;
    //2.申明序列化的版本号码(序列化与反序列化的版本号必须一致才不会报错!!!)

    private String name;
    private String loginName;
    private transient String password;//3.transient 修饰的成员变量不参与序列化
    private int age;

            @Override
            public String toString() {
                return "Student{" +
                        "name='" + name + '\'' +
                        ", loginName='" + loginName + '\'' +
                        ", password='" + password + '\'' +
                        ", age=" + age +
                        '}';
            }

            public Student() {
    }

    public Student(String name, String loginName, String password, int age) {
        this.name = name;
        this.loginName = loginName;
        this.password = password;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getLoginName() {
        return loginName;
    }

    public void setLoginName(String loginName) {
        this.loginName = loginName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

1.5 打印流

实例:

一个路径只能创建一个打印流对象。

public static void main(String[] args) throws Exception {
/*  创建一个打印流对象  */
    PrintStream ps1=new PrintStream(new FileOutputStream(".\\Phase2\\resource\\ps1.txt"));
    //使用PrintWriter也行

    ps1.println("我是打印流,可以打印任何类型的数据");
    ps1.close();
}

补充:重定向

//改变输入语句的位置(重定向)
    PrintStream ps3=new PrintStream(".\\Phase2\\resource\\ps3.txt");
    System.out.println("我在重定向前面,还是会打印到控制台");
    
    System.setOut(ps3);//把系统的打印流改成我们自己的打印流

    System.out.println("我是我们自己的打印流,不会打印到控制台,而是会打印到文件中");

二:Properties

2.1 Properties的归属及作用

2.2 Properties与IO流结合

这便是为什么我们要在IO流这里讲Properties的原因。其中load和store方法是我们着重要掌握的。

实例:

public static void main(String[] args) throws IOException {
    Properties properties=new Properties();//1.实质上就是一个Map集合,但是可以与IO流结合
    System.out.println(properties);
    properties.setProperty("jack","1314");
    properties.setProperty("rose","520");
    System.out.println(properties);

//2.    把键值文件存到属性文件中
    properties.store(new FileWriter("./Phase2/resource/user.properties"),
                "我是注释:看到了v我50");
    //参数一:保存管道(文件路径) 参数二:文件保存注释   
       
//3.加载属性文件中的键值对信息数据到属性对象properties中去
    properties.load(new FileReader("./Phase2/resource/user.properties"));
    System.out.println(properties);
    String rs=properties.getProperty("jack");//4.获取键的值
    System.out.println(rs);
}

三:commons-io类库

3.1 导入commons-io jar包

3.2 commons-io概述

3.3 commons-io API

实例:

以下所有 " " 中应填的东西是路径,这里省略。

public static void main(String[] args) throws IOException {
(1)IOUtils类
    //完成 文件复制
    IOUtils.copy(new FileInputStream(""),new FileOutputStream(""));

(2)FileUtils类
//1.完成 文件 复制到 文件夹 下
    FileUtils.copyFileToDirectory(new File(""),new File(""));

//2.完成 文件夹 复制到 文件夹下
    FileUtils.copyDirectoryToDirectory(new File(""),new File(""));

//3..删除文件夹(!!!)
    FileUtils.deleteDirectory(new File(""));

(3)java 自己提供的完成代码复制的操作(New IO的技术):
        Files.copy(Path.of(""),Path.of(""));
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值