【JAVA】编码表,字符流,对象流,其他流(二)

简介: 【JAVA】编码表,字符流,对象流,其他流

4 字符缓冲流


4.1 字符缓冲流


  • BufferedWriter:可以将数据高效的写出
  • BufferedReader:可以将数据高效的读入到内存
  • 注意 : 字符缓冲流不具备读写功能 , 只提供缓冲区 , 真正读写还是需要依赖于构造接收的基本的字符流

构造方法:

public BufferedWriter(Writer out) : 构造方法中需要接收一个基本的字符输出流

public BufferedReader(Reader in) : 构造方法中需要接收一个基本的字符输入流

package com.itheima.bufferedstream_demo;
import java.io.*;
/*
    需求 : 使用字符缓冲流复制纯文本文件
    将当日课程资料中的 ‘斗罗大陆.txt’ 复制到当前模块下 'copy.txt'
 */
public class BufferedStreamDemo1 {
    public static void main(String[] args) throws IOException {
        // 创建高效的字符输入流对象
        BufferedReader br = new BufferedReader(new FileReader("D:\\传智播客\\上海-JavaSE进阶面授\\day12【缓冲流、转换流、序列化流、装饰者模式、commons-io工具包】\\资料\\斗罗大陆.txt"));
        // 创建高效的字符输出流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("day12_demo\\copy.txt"));
        // 一次读写一个字符
//        int ch;
//        while ((ch = br.read()) != -1) {
//            bw.write(ch);
//        }
        // 一次读写一个字符数组
        char[] chs = new char[1024];
        int len;
        while ((len = br.read(chs)) != -1) {
            bw.write(chs, 0, len);
        }
        // 释放资源
        br.close();
        bw.close();
    }
}

4.2 字符缓冲流特有的功能


  • BufferedWriter类
  • void newLine():写一个行分隔符,会根据操作系统的不同,写入不同的行分隔符
  • BufferedReader类
  • public String readLine() :读取文件一行数据, 不包含换行符号 , 读到文件的末尾返回null
package com.itheima.bufferedstream_demo;
import java.io.*;
/*
    1 字符缓冲流:
        BufferedWriter:可以将数据高效的写出
        BufferedReader:可以将数据高效的读入到内存
    2 字符缓冲流特有功能
        BufferedWriter类
            void newLine​():写一个行分隔符,会根据操作系统的不同,写入不同的行分隔符
        BufferedReader类
            public String readLine​() :读取文件一行数据, 不包含换行符号 ,  读到文件的末尾返回null
        远桥之下泛莲舟
        岱岩石上松溪流
        万仞翠山梨亭在
        莫闻空谷声悠悠
 */
public class BufferedStreamDemo2 {
    public static void main(String[] args) throws IOException {
        // 创建高效的字符输出流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("day12_demo\\abc.txt"));
        // void newLine​():写一个行分隔符,会根据操作系统的不同,写入不同的行分隔符
        bw.write("远桥之下泛莲舟");
        bw.newLine();
        bw.write("岱岩石上松溪流");
        bw.newLine();
        bw.write("万仞翠山梨亭在");
        bw.newLine();
        bw.write("莫闻空谷声悠悠");
        bw.flush();
        // 创建高效的字符输入流对象
        BufferedReader br = new BufferedReader(new FileReader("day12_demo\\abc.txt"));
        // public String readLine​() :读取文件一行数据, 不包含换行符号 ,  读到文件的末尾返回null
//        String s = br.readLine();
//        System.out.println(s);
//        s = br.readLine();
//        System.out.println(s);
//        s = br.readLine();
//        System.out.println(s);
//        s = br.readLine();
//        System.out.println(s);
//        System.out.println("============");
//        s = br.readLine();
//        System.out.println(s);
//        s = br.readLine();
//        System.out.println(s);
        // 循环改进
        String line;
        while((line = br.readLine()) != null){
            System.out.println(line);
        }
        // 释放资源
        br.close();
        bw.close();
    }
}

4.3 字符缓冲流练习


package com.itheima.bufferedstream_demo;
import java.io.*;
import java.util.Arrays;
/*
    需求:读取文件中的数据 : 33 22 11 55 44
    排序后 : 11 22 33 44 55  再次写到本地文件
    步骤 :
        1 创建高效的字符输入流对象
        2 读取文件中的一行数据
        3 将数据按照空格切割
        4 把字符串数组转成int类型数组
        5 对int类型的数组进行排序
        6 创建高效的字符输出流对象
        7 遍历数组,把数组中的数据写入到文件中
        8 释放资源
 */
public class BufferedStreamDemo3 {
    public static void main(String[] args) throws IOException {
        // 1 创建高效的字符输入流对象
        BufferedReader br = new BufferedReader(new FileReader("day12_demo\\sort.txt"));
        // 2 读取文件中的一行数据
        String line = br.readLine();
        // 3 将数据按照空格切割
        String[] strs = line.split(" ");
        // 4 把字符串数组转成int类型数组
        int[] arr = new int[strs.length];
        for (int i = 0; i < strs.length; i++) {
            arr[i] = Integer.parseInt(strs[i]);
        }
        // 5 对int类型的数组进行排序
        Arrays.sort(arr);
        // 6 创建高效的字符输出流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("day12_demo\\sort.txt"));
        // 7 遍历数组,把数组写入到文件中
        for (int i = 0; i < arr.length; i++) {
            bw.write(arr[i] + " ");
            bw.flush();
        }
        // 8 释放资源
        br.close();
        bw.close();
    }
}

5 转换流


5.1 转换流介绍


  • 转换流就是来进行字节流和字符流之间转换的桥梁

5.2 转换流分类


  • InputStreamReader是从字节流到字符流的桥梁
  • public InputStreamReader(InputStream in) : 创建一个使用默认编码的 InputStreamReader。
  • public InputStreamReader(InputStream in , String charsetName) : 创建使用指定编码的 InputStreamReader。
  • OutputStreamWriter是从字符流到字节流的桥梁

public OutputStreamWriter(OutputStream out) : 创建使用默认字符编码的                                    OutputStreamWriter

public OutputStreamWriter(OutputStream out, String charsetName) : 创建使用指定编码的         OutputStreamWriter。

练习

package com.itheima.conversion_demo;
import java.io.*;
/*
    转换流就是来进行字节流和字符流之间转换的桥梁
    InputStreamReader是从字节流到字符流的桥梁
        public InputStreamReader(InputStream in) : 创建一个使用默认编码的 InputStreamReader。
        public InputStreamReader(InputStream in ,  String charsetName) : 创建使用指定编码的 InputStreamReader。
    OutputStreamWriter是从字符流到字节流的桥梁
        public OutputStreamWriter(OutputStream out) : 创建使用默认字符编码的 OutputStreamWriter
        public OutputStreamWriter(OutputStream out,  String charsetName) : 创建使用指定编码的 OutputStreamWriter。
    需求1 : 使用转换流 , 把以下数据按照GBK的编码写入文件 , 在使用GBK的编码读取数据
    数据如下 :
        远桥之下泛莲舟
        岱岩石上松溪流
        万仞翠山梨亭在
        莫闻空谷声悠悠
 */
public class ConversionDemo2 {
    public static void main(String[] args) throws IOException {
        // 创建转换输出流
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day12_demo\\conversion.txt"), "GBK");
        osw.write("远桥之下泛莲舟");
        osw.write("\r\n");
        osw.write("岱岩石上松溪流");
        osw.write("\r\n");
        osw.write("万仞翠山梨亭在");
        osw.write("\r\n");
        osw.write("莫闻空谷声悠悠");
        osw.write("\r\n");
        osw.close();
        // 创建转换输入流
        InputStreamReader isr = new InputStreamReader(new FileInputStream("day12_demo\\conversion.txt"), "GBK");
        int ch;
        while ((ch = isr.read()) != -1) {
            System.out.print((char) ch);
        }
        isr.close();
    }
}
package com.itheima.conversion_demo;
import java.io.*;
/*
    转换流就是来进行字节流和字符流之间转换的桥梁
    InputStreamReader是从字节流到字符流的桥梁
        public InputStreamReader(InputStream in) : 创建一个使用默认编码的 InputStreamReader。
        public InputStreamReader(InputStream in ,  String charsetName) : 创建使用指定编码的 InputStreamReader。
    OutputStreamWriter是从字符流到字节流的桥梁
        public OutputStreamWriter(OutputStream out) : 创建使用默认字符编码的 OutputStreamWriter
        public OutputStreamWriter(OutputStream out,  String charsetName) : 创建使用指定编码的 OutputStreamWriter。
    需求2 :  将模块根目录中GBK编码的文本文件 , 转换为UTF-8编码的文本文件
 */
public class ConversionDemo2 {
    public static void main(String[] args) throws IOException {
        // 创建转换输入流
        InputStreamReader isr = new InputStreamReader(new FileInputStream("day12_demo\\GBK编码的文件.txt"), "GBK");
        // 创建转换输出流
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day12_demo\\UTF编码的文件.txt"), "UTF-8");
        int ch;
        while ((ch = isr.read()) != -1) {// 以GBK编码进去读取
            osw.write(ch);// 以UTF-8编码进行写入
        }
        // 释放资源
        isr.close();
        osw.close();
    }
}

6 对象操作流


6.1 对象操作流介绍


  • 可以把对象以字节的形式写到本地文件,直接打开文件,是读不懂的,需要再次用对象操作流读到内存中

6.2 对象操作流的分类


  • ObjectOutputStream :
  • 对象操作输出流(对象序列化流):就是将对象写到本地文件中,或者在网络中传输对象
  • ObjectInputStream :
  • 对象操作输入流(对象反序列化流):把写到本地文件中的对象读到内存中,或者接收网络中传输的对象

6.3 对象操作流的注意事项


  • 注意 : 如果一个类对象想要被序列化 , 那么此类需要实现Serializable接口
  • Serializable接口的含义 :
  • 1 是一个标记性接口 , 里面没有任何抽象方法
  • 2 只要一个类实现了此接口 , 表示此类的对象可以被序列化
  • 用对象序列化流序列化了一个对象后,假如我们修改了对象所属的Javabean类,读取数据会不会出问题呢?
  • 会出问题,会抛出InvalidClassException异常
  • 如果出问题了,如何解决呢?
  • 给对象所属的类加一个serialVersionUID
  • private static final long serialVersionUID = 42L;
  • 如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?
  • 给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程
package com.itheima.objectstream_demo;
import java.io.Serializable;
/*
    如果此类对象想要被序列化 , 那么此类需要实现Serializable接口
    Serializable接口的含义 :
        是一个标记性接口 , 里面没有任何抽象方法
        只要一个类实现了此接口 , 表示此类的对象可以被序列化
 */
public class User implements Serializable {
    /*
        问题分析 :
            serialVersionUID : 序列号
            序列号是根据类的信息进行生成的
            如果没有自己给出序列号 , JVM会根据类的信息自动计算一个序列号
            如果改动了类的信息 , 那么JVM会重新计算一个序列号
            第一步 : 把对象序列化到本地中 , 序列号为 -4446663370728791812 也会存储到本地中
            第二步 : 我们自己修改了类 , 会重新计算一个新的序列号 2908680347500030933
            第三步 : 当把对象读到内存中时 , 本地中的序列号和类中的序列号不一致就会发生 InvalidClassException异常
        解决方案 :
            我们自己手动给出序列号, 不让虚拟机自动生成 , 并且这个值恒久不变
            private static final long serialVersionUID = 值L;
     */
    private static final long serialVersionUID = 111L;
    private String username;
    private transient String password;
    public User() {
    }
    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

6.4 对象操作流的练习


7 装饰设计模式


  • 设计模式 : 一套良好的编码风格 , 经过众多的开发人员不断的测试总结而来

目标

  • 熟悉装饰设计模式的使用

内容讲解

【1】概述

  • 装饰模式指的是在不改变原类, 不使用继承的基础上,动态地扩展一个对象的功能。
  • 不使用继承技术扩展功能, 可以降低耦合
  • 使用原则:
  • 装饰类和被装饰类需要有共同的父类型。
  • 在之前学习过的 BufferedWriter 和 FileWriter 就是装饰设计模式
  • BufferedWriter的父类为Writer
  • FileWriter的父类也是Writer
  • 我们把FileWriter的对象传递到BufferedWriter的构造中 , 那么可以理解为BufferedWriter是装饰类 , FileWriter是被装饰类
  • BufferedWriter对FileWriter的功能做了增强
  • 装饰类的构造要接收被装饰类的对象
  • FileWriter fw = new FileWriter(“路径”);
  • BufferedWriter bw = new BufferedWriter(fw);
  • 在装饰类中把要增强扩展的功能进行扩展
  • BufferedWriter和FileWriter的功能一样, 都具备Writer中写数据的功能
  • 但是BufferedWriter提供了缓冲区 , 相当于对FileWriter功能做了扩展
  • 对于不要增强的功能直接调用
  • 不需要增强的功能直接继承父类的即可

【2】代码实践

已知有接口Star和其子类型LiuDeHua。

public interface Star {
    public abstract void sing();
    public abstract void dance();
}

需求 :在不改变LiuDeHua类,及不使用继承的技术前提下,动态的扩展LiuDeHua的sing功能。

LiuDeHua就是一个被装饰类 , 需要对唱歌的功能进行扩展

思路 :

定义一个装饰类,去装饰增强 LiuDehua类。

步骤:

  • 创建LiuDeHua类并实现接口Star【被装饰类】
  • 定义一个装饰类LiuDeHuaWrapper实现Star 【装饰类】
  • 在装饰类里面定义一个成员变量类型是LiuDeHua,可以使用构造方法进行传入被装饰类对象。
  • 在装饰类中对sing方法进行功能扩展
  • 对dance不做改动
  • 测试类分别创建装饰类的对象和被装饰类的对象。将被装饰类对象刘德华对象设置给装饰类对象
package com.itheima.design_demo;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
/*
    装饰模式指的是在不改变原类, 不使用继承的基础上,动态地扩展一个对象的功能
    使用原则 :
        1. 装饰类和被装饰类需要有共同的父类型。
        2. 装饰类要传入被装饰类的对象
        3. 在装饰类中把要增强扩展的功能进行扩展
        4. 对于不要增强的功能直接调用
    需求 : 在不改变LiuDeHua类,及不使用继承的技术前提下,动态的扩展LiuDeHua的sing功能。
            LiuDeHua就是一个被装饰类 , 需要对唱歌的功能进行扩展
    步骤:
        1. 创建LiuDeHua类并实现接口Star【被装饰类】
        2. 定义一个装饰类LiuDeHuaWrapper实现Star 【装饰类】
        3. 在装饰类里面定义一个成员变量类型是LiuDeHua,可以使用构造方法进行传入被装饰类对象。
        4. 在装饰类中对sing方法进行功能扩展
        5. 对dance不做改动
        6. 测试类分别创建装饰类的对象和被装饰类的对象。将被装饰类对象刘德华对象设置给装饰类对象
 */
public class Test {
    public static void main(String[] args) throws IOException {
        // 被装饰类对象
        LiuDeHua huaZai = new LiuDeHua();// 0x001
        // 装饰类对象
        LiuDeHuaWrapper liuDeHuaWrapper = new LiuDeHuaWrapper(huaZai);
        liuDeHuaWrapper.sing();
        liuDeHuaWrapper.dance();
//        // 被装饰类对象
//        FileWriter fw = new FileWriter("路径");
//        // 装饰类对象
//        BufferedWriter bw = new BufferedWriter(fw);
    }
}
// 1. 创建LiuDeHua类并实现接口Star【被装饰类】
class LiuDeHua implements Star {
    @Override
    public void sing() {
        System.out.println("唱忘情水...");
    }
    @Override
    public void dance() {
        System.out.println("华仔在跳老年迪斯高..");
    }
}
// 2. 定义一个装饰类LiuDeHuaWrapper实现Star 【装饰类】
class LiuDeHuaWrapper implements Star {
    // 3. 在装饰类里面定义一个成员变量类型是LiuDeHua,可以使用构造方法进行传入被装饰类对象。
    private LiuDeHua huaZai;// 0x001
    public LiuDeHuaWrapper(LiuDeHua huaZai) {// 0x001
        this.huaZai = huaZai;
    }
    @Override
    public void sing() {
        // 4. 在装饰类中对sing方法进行功能扩展
        System.out.print("华仔深情");
        huaZai.sing();
    }
    @Override
    public void dance() {
        // 5. 对dance不做改动
        huaZai.dance();
    }
}
// 明星接口 , 装饰类和被装饰类的父类型
interface Star {
    public abstract void sing(); // 唱歌
    public abstract void dance();// 跳舞
}

内容小结

  1. 装饰类和被装饰类需要有共同的父类型。
  2. 装饰类要传入被装饰类的对象
  3. 在装饰类中把要增强扩展的功能进行扩展
  4. 对于不要增强的功能直接调用

8 commons-io工具包(对文件的拷贝做优化)


学习目标

  • 能够熟悉导入commons-io工具包,并使用

内容讲解

【1】三方库的导入

下载commons-io相关jar包;http://commons.apache.org/proper/commons-io/

把commons-io-2.6.jar包复制到指定的Module的lib目录中

将commons-io-2.6.jar加入到项目中

在这里插入图片描述

【2】API

1)org.apache.commons.io.IOUtils类

public static int copy(InputStream in, OutputStream out):
  把input输入流中的内容拷贝到output输出流中,返回拷贝的字节个数(适合文件大小为2GB以下)
public static long copyLarge(InputStream in, OutputStream out):
  把input输入流中的内容拷贝到output输出流中,返回拷贝的字节个数(适合文件大小为2GB以上)
package com.itheima.commons_io;
import org.apache.commons.io.IOUtils;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
    org.apache.commons.io.IOUtils类
    public static int copy(InputStream in, OutputStream out):
  把input输入流中的内容拷贝到output输出流中,返回拷贝的字节个数(适合文件大小为2GB以下)
    public static long copyLarge(InputStream in, OutputStream out):
  把input输入流中的内容拷贝到output输出流中,返回拷贝的字节个数(适合文件大小为2GB以上)
 */
public class Test1 {
    public static void main(String[] args) throws IOException {
        IOUtils.copy(new FileInputStream("D:\\传智播客\\安装包\\好看的图片\\liqin.jpg") , new FileOutputStream("day12_demo\\copy.jpg"));
    }
}

2)org.apache.commons.io.FileUtils

public static void copyFileToDirectory(final File srcFile, final File destFile): 
  复制文件到另外一个目录下。
public static void copyDirectoryToDirectory(File src , File dest ):
  复制src目录到dest位置。

代码实践:

package com.itheima.commons_io;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
/*
    org.apache.commons.io.FileUtils
    public static void copyFileToDirectory(final File srcFile, final File destFile):
  复制文件到另外一个目录下。
    public static void copyDirectoryToDirectory(File src , File dest ):
  复制src目录到dest目录中。
 */
public class Test2 {
    public static void main(String[] args) throws IOException {
        FileUtils.copyDirectoryToDirectory(new File("D:\\传智播客\\安装包\\好看的图片") , new File("D:\\"));
    }
}

内容小结

commons-io可以简化IO复制文件的操作。

相关文章
|
2月前
|
Java
Java开发实现图片URL地址检验,如何编码?
【10月更文挑战第14天】Java开发实现图片URL地址检验,如何编码?
91 4
|
2月前
|
Java
Java实现随机生成某个省某个市的身份证号?如何编码?
【10月更文挑战第18天】Java实现随机生成某个省某个市的身份证号?如何编码?
153 5
|
2月前
|
Java
Java开发实现图片地址检验,如果无法找到资源则使用默认图片,如何编码?
【10月更文挑战第14天】Java开发实现图片地址检验,如果无法找到资源则使用默认图片,如何编码?
65 2
|
2月前
|
存储 缓存 Java
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
这篇文章详细介绍了Java中的IO流,包括字符与字节的概念、编码格式、File类的使用、IO流的分类和原理,以及通过代码示例展示了各种流的应用,如节点流、处理流、缓存流、转换流、对象流和随机访问文件流。同时,还探讨了IDEA中设置项目编码格式的方法,以及如何处理序列化和反序列化问题。
88 1
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
|
2月前
|
Java 数据处理 开发者
揭秘Java IO流:字节流与字符流的神秘面纱!
揭秘Java IO流:字节流与字符流的神秘面纱!
39 1
|
2月前
|
自然语言处理 Java 数据处理
Java IO流全解析:字节流和字符流的区别与联系!
Java IO流全解析:字节流和字符流的区别与联系!
96 1
|
3月前
|
存储 移动开发 Java
java核心之字符串与编码
java核心之字符串与编码
26 2
|
4月前
|
Java PHP 开发者
PHP中的异常处理:Java常见的编码方式
在PHP开发中,掌握异常处理至关重要,它有助于预见并管理运行时错误,避免用户体验受损或数据丢失。本文介绍PHP异常处理的基本概念与实践,包括try-catch语句的使用,以及如何通过抛出和捕获异常来增强代码的健壮性和可靠性。通过示例展示如何避免常见错误,如除数为零的情况,并探讨多catch块和finally语句的高级用法,帮助开发者提升程序稳定性与可维护性。[总字符数:238]
32 0
|
移动开发 Java 数据处理
|
3天前
|
安全 Java API
java如何请求接口然后终止某个线程
通过本文的介绍,您应该能够理解如何在Java中请求接口并根据返回结果终止某个线程。合理使用标志位或 `interrupt`方法可以确保线程的安全终止,而处理好网络请求中的各种异常情况,可以提高程序的稳定性和可靠性。
28 6