编码和解码的方法

编码是将字符(如Unicode字符)转换成字节的过程,而解码则是将字节转换回字符的过程。
String构造函数可以接受字节数组和字符数组。使用字节数组时,可以指定字符编码

        //编码
            //默认字符集UTF-8
        String s = "黑马程序员";
        byte[] bytes = s.getBytes();
        System.out.println(Arrays.toString(bytes));
            //指定字符集
        byte[] bytes1 = s.getBytes("GBK");
        System.out.println(Arrays.toString(bytes1));
        //解码
        byte[] utf8Bytes = {-23, -69, -111, -23, -87, -84, -25, -88, -117, -27, -70, -113, -27, -111, -104};
        byte[] gbkBytes = {-70, -38, -62, -19, -77, -52, -48, -14, -44, -79};
            //用默认字符集UTF-8解码
        String s1 = new String(utf8Bytes);
        System.out.println(s1);
            //用GBK字符集解码
        String s2 = new String(gbkBytes, "GBK");
        System.out.println(s2);

字符流写数据

方法名说明
public void write(int c)写入单个字符
public void write(char[] cbuf)写入字符数组
public void write(char[] cbuf, int off, int len)写入字符数组的一部分
public void write(String str)写入字符串
public void write(String str, int off, int len)写入字符串的一部分。
//代码演示
        //字符流-写出数据的构造方法
        FileWriter fw1 = new FileWriter(new File("a.txt"));//方法1
        FileWriter fw = new FileWriter("a.txt");//方法二

        //写一个字符
        fw.write(97);
        //写一个字符数组
        char[] chars = {97, 98, 99, 100, 101, 102};
        fw.write(chars);
        //写出字符数组的一部分
        fw.write(chars, 0 , 3);
        //写一个字符串
        String s = "黑马程序员";
        fw.write(s);
        //写字符串的一部分
        fw.write(s, 0, 3);

        //释放资源
        fw.close();

字符流读数据

一次只读取一个字符
字符在Java底层实际上是一个无符号的 16 位整数。
这意味着它的值范围从 0 到 65535(即 0xFFFF),用来表示 Unicode 字符集中的字符。
强制转换 (char) 实际上是将整数的 16 位二进制表示解释为一个字符的 Unicode 代码单元。

一次只读一个字符

//单次读一个数据
    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("a.txt");
        int b;
        while ((b = fr.read()) != -1){
            System.out.println((char) b);
        }
    }

一次读1024个字符

    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("a.txt");
        int length;
        char[] c = new char[1024];
        while ((length = fr.read(c)) != -1){
            System.out.println(new String(c, 0, length));
        }
    }

字符缓冲流(和字节缓冲流基本上一模一样)

字符缓冲输入流

//复制
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("a.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("honglou.txt"));
        char[] chars = new char[1024];
        int len;
        while ((len = br.read(chars)) != -1){
            bw.write(chars, 0, len);
        }
        br.close();
        bw.close();
    }

//字符缓冲输出流

void write(char[] cbuf, int off, int len) //写入字符数组的一部分
void write(int c) //写入单个字符
void write(String s, int off, int len) //写入字符串的一部分

字符缓冲流当中的两个特有方法


void newLine() :写入行分隔符(所有操作系统通用)
String readLine() :读取一行文本。

转换流

在Java11以前只能使用这种方法在字符流中指定字符集

InputStreamReader(InputStream in, String charsetName)//创建一个使用指定字符集的 InputStreamReader。
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"), "UTF-8");
OutputStreamWriter(OutputStream out, String charsetName)//创建一个使用指定字符集的 OutputStreamWriter。

Java11以后字符流推出了一个新的构造用来指定编码表

FileReader(String fileName, Charset charset) //创建一个新的 FileReader ,给定要读取的文件的名称和 charset 
FileReader fr = new FileReader("a.txt", Charset.forName("GBK"));

对象操作输出流(序列化)

序列化是将对象的状态转换为字节流的过程,以便可以将对象保存到文件或通过网络传输

//对象操作流序列化代码展示
        User user = new User("zhangsan", "qwertyop");
        
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
        oos.writeObject(user);
        oos.close();

对象操作输入流(反格式化)

Student student =(Student) ois.readObject();

序列号

把对象所属的类的序列号设置成一个常量:
给对象所属的类加一个serialVersionUlD

private static final long serialVersionUlD = 42L;

如果一个对象中的某个成员变量的值不想被序列化: 给该成员变量加transient关键字修饰, 这样用了该关键字标记的成员变量就不会参与序列化过程了

private transient int age;


转换流和对象流的构造方法里都用的是 FileInputStream

Properties

Properties概述:

  • 是一个Map体系的集合类
  • Properties中有和IO相关的方法
  • 只存String

Properties基本使用:

    public static void main(String[] args) {
        //构造:Properties虽然是Map的实现类但不需要指定泛型 但一般只会在里面添加String类型
        Properties prop = new Properties();
        //增
        prop.put("黄乘明", "刘慧");
        prop.put("小龙女", "杨过");
        prop.put("孤独时代", "陈一发儿");

        //删
        prop.remove("黄乘明");
        prop.clear();

        //改
        prop.put("黄乘明", "尹志平");
        System.out.println(prop);

        //查
        prop.containsKey("黄乘明");
        prop.containsValue("尹志平");

        //遍历
        Set<Object> key = prop.keySet();
        for (Object o : key) {
            System.out.println(o + "----" + prop.get(o));
        }

        Set<Map.Entry<Object, Object>> entries = prop.entrySet();
        for (Map.Entry<Object, Object> entry : entries) {
            System.out.println(entry.getKey() + "----" + entry.getValue());
        }
    }

Properties作为Map集合的实现类三个特有的方法

方法名说明
setProperty(String key, String value)居调用 Hashtable 方法 put
getProperty(String key)在此属性列表中搜索具有指定键的属性。
stringPropertyNames()从此属性列表返回一组不可修改的键
    public static void main(String[] args) {
        Properties prop = new Properties();
        prop.put("黄乘明", "刘慧");
        prop.put("小龙女", "杨过");
        prop.put("孤独时代", "陈一发儿");

        prop.setProperty("吃屎", "喝尿");//相当于put方法
        String s = prop.getProperty("吃屎");//相当于get方法
        System.out.println(s);
        Set<String> keysset = prop.stringPropertyNames();//相当于keySet方法
        for (String key : keysset) {
            System.out.println(key + "=" + prop.getProperty(key));
        }

    }

load properties文件

        FileReader fr = new FileReader("D:\\JavaWorkSpace\\characterstream\\properties\\prop.properties");
        Properties prop = new Properties();
        prop.load(fr);
        System.out.println(prop);

store properties文件

        Properties prop = new Properties();
        prop.put("zhanghsan", "123");
        prop.put("lisi", "4556");
        FileWriter fw = new FileWriter("D:\\JavaWorkSpace\\characterstream\\properties\\prop.properties");
        prop.store(fw,"??");
        fw.close();

转换流, 对象流的构造方式都是需要字节流
但Properties需要字符流