Java学习笔记day21-字符流及其它流

字符流
字符串中的编码解码问题

编码

  • byte[] getBytes():使用平台的默认字符集将该String编码为一系列字节,将结果存储到新的字节数组中;
  • byte[] getBytes(String charsetName):使用指定的字符集将该String编码为一系列字节,将结果存储到新的字节数组中;

解码

  • String(byte[] bytes):通过使用平台的默认字符集解码指定的字节数组来构造新的String;
  • String(byte[] bytes,String charsetName):通过指定的字符集解码指定的字节数组来构造新的String;
字符流写数据
方法名说明
void write(int c)写一个字符
void write(char[] cbuf)写一个字符数组
void write(char[] cbuf,int off,int len)写出字符数组的一部分
void write(String str)写一个字符串
void write(String str,int off,int len)写一个字符串的一部分
import java.io.FileWriter;
import java.io.IOException;

public class CharStreamTest {
    public static void main(String[] args) throws IOException {
       //创建字符输出流对象
        //FileWriter fw = new FileWriter(new File("day21\\src\\a.txt"));
        FileWriter fw = new FileWriter("day21\\src\\a.txt");
        //一次写一个字符
        fw.write(97);
        fw.write(98);
        fw.write(99);
        //一次写一个字符数组
        char[] arr = {97,98,99,100,101};
        fw.write(arr);
        //一次写一个字符数组的一部分
        fw.write(arr,1,3);
        //一次写一个字符串
        String s = "一次写一个字符串";
        fw.write(s);
        //一次写一个字符串的一部分
        fw.write(s,5,3);
        fw.close();
    }
}

注意

  • 如果文件不存在,就创建,但是要保证父级路径存在;如果文件存在就清空;
  • 写出int类型的整数,实际写出的是整数在码表上的对应的字母;
  • 写出字符串数据,是把字符串本身原样写出;
flush和close方法
方法名说明
flush()刷新流,还可以继续写数据
close()关闭流,释放资源,但是在关闭之前会先刷新流,一旦关闭,就不能再写数据
字符流读数据
import java.io.FileReader;
import java.io.IOException;

public class ReaderTest {
    public static void main(String[] args) throws IOException {
        //创建字符输入流对象
        FileReader fr = new FileReader("day21\\src\\a.txt");
        //读数据
        //一次读一个字符
        int ch;
        while((ch = fr.read()) != -1){
            System.out.println((char)ch);
        }
        
        //一次读一个字符数组
        //创建一个数组
        char[] chars = new char[1024];
        int len;
        //read方法还是读取,但是一次读取多个字符
        //他把读到的字符都存入到chars数组
        //返回值:表示本次读到了多少个字符
        while ((len = fr.read(chars))!=-1){
            System.out.println(new String(chars,0,len));
        }
        //释放资源
        fr.close();
    }
}
案例:保存键盘录入的数据

​ 将用户键盘录入的用户名和密码保存到本地实现永久化存储;要求用户名和密码各自独占一行。

import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;

public class Anli {
    public static void main(String[] args) throws IOException {
        //实现键盘录入,把用户名和密码录入进来
        Scanner sc = new Scanner(System.in);
        System.out.println("请录入用户名:");
        String username = sc.next();
        System.out.println("请录入密码:");
        String password = sc.next();
        //分别把用户名和密码写到本地文件
        FileWriter fw = new FileWriter("day21\\src\\a.txt");
        //将用户名和密码写到文件中
        fw.write(username);
        fw.write("\r\n");
        fw.write(password);
        //刷新流
        fw.flush();
        //释放资源
        fw.close();
    }
}

字符缓冲流:

  • BufferedWriter:可以将数据高效的写出;
  • BufferedReader:可以将数据高效的读取到内存;

​ 构造方法:

  • BufferedWriter(Writer out)
  • BufferedReader(Reader in)
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderTest {
    public static void main(String[] args) throws IOException {
        //字符缓冲输入流
        BufferedReader br = new BufferedReader(new FileReader("day21\\src\\a.txt"));
        //读取数据
        char[] chars = new char[1024];
        int len;
        while ((len = br.read(chars)) != -1){
            System.out.println(new String(chars,0,len));
        }
        br.close();
    }
}
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedWriterTest {
    public static void main(String[] args) throws IOException {
        //字符缓冲输出流
        BufferedWriter bw = new BufferedWriter(new FileWriter("day21\\src\\a.txt"));
        //写数据
        bw.write(97);
        bw.write("\r\n");
        char[] chars = {97,98,99,100,101};
        bw.write(chars);
        bw.write("\r\n");
        bw.write(chars,1,3);
        bw.write("\r\n");
        String s = "字符缓冲输出流";
        bw.write(s);
        bw.write("\r\n");
        bw.write(s,2,5);
        bw.close();
    }
}
字符缓冲流特有功能

BufferedWriter:

  • void newLine():写一行行分隔符,行分隔符字符串由系统属性定义;

BufferedReader:

  • public String readLine():读一行文字。结果包含行的内容的字符串,不包括任何行终止符,如果留的结尾已经到达,则为null;
案例:读取文件中的数据排序后再次写到本地

​ 读取文件中的数据,排序后再次写到本地文件;

import java.io.*;
import java.util.Arrays;

public class Anli {
    public static void main(String[] args) throws IOException {
        //把文件中的数据读取近来
        BufferedReader br =new BufferedReader(new FileReader("day21\\src\\a.txt"));
        //输出流一定不能写在这里,因为会清空文件里的数据
        String s = br.readLine();
        System.out.println("读到的数据为:"+s);
        br.close();
        //将读到的数据进行切割
        String[] arr = s.split(" ");
        //把字符串数组转换为int数组
        int[] arr1 = new int[arr.length];
        //遍历数组进行类型转换
        for (int i = 0; i < arr.length; i++) {
            arr1[i] = Integer.parseInt(arr[i]);
        }
        //排序
        Arrays.sort(arr1);
        System.out.println(Arrays.toString(arr1));
        //把排序后的结果写回到本地
        BufferedWriter bw = new BufferedWriter(new FileWriter("day21\\src\\a.txt",true));
        bw.write("\r\n");
        for (int i = 0; i < arr1.length; i++) {
            bw.write(arr1[i]+" ");
            //bw.flush();
        }
        bw.close();
    }
}
其它流
转换流
  • 输入流:InputStreamReader
  • 输出流:OutputStreamWriter

1645696624281

对象操作流

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

  • 对象操作输入流:ObjectInputStream
  • 对象操作输出流:ObjectOutputStream

对象操作流分为两类:对象操作输入流和对象操作输出流

对象操作输出流(对象序列化流):就是将对象写到本地文件中,或者在网络中传输对象

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

对象序列化流:
import java.io.Serializable;

//如果想要这个类的对象能被序列化,那么这个类必须要实现一个接口Serializable
//Serializable接口的意义
//称之为是一个标记性接口,里面没有任何的抽象方法
//只要一个类实现了这个Serializable接口,那么就表示这个类的对象可以被序列化
public class User implements Serializable {
    private String username;
    private 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 + '\'' +
                '}';
    }
}
测试类:
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class ObjectStreamTest {
    public static void main(String[] args) throws IOException {
        User user = new User("xiaohua","123456");
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day21\\src\\a.txt"));
        oos.writeObject(user);
        oos.close();
    }
}
对象反序列化流
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class ObjectStreamTest1 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day21\\src\\a.txt"));
        User user = (User) ois.readObject();
        System.out.println(user);
        ois.close();
    }
}

案例:用对象操作流读写多个对象

创建多个Javabean类对象写到文件中,再次读取到内存;

import java.io.Serializable;

public class Student implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private int age;

    public Student() {
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
import java.io.*;
import java.util.ArrayList;

public class StudentTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Student st1 = new Student("小花",15);
        Student st2 = new Student("小澜",17);
        Student st3 = new Student("小雅",16);
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day21\\src\\a.txt"));
        oos.writeObject(st1);
        oos.writeObject(st2);
        oos.writeObject(st3);

        //可以将对象存入集合,再将集合写到本地
//        ArrayList<Student> list = new ArrayList<>();
//        list.add(st1);
//        list.add(st2);
//        list.add(st3);
//        oos.writeObject(list);

        oos.close();

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day21\\src\\a.txt"));
        while (true){
            try {
                Object o = ois.readObject();
                System.out.println(o);
            } catch (EOFException e) {
                break;
            }
        }

        //读取集合
//        ArrayList<Student> list1 = (ArrayList<Student>) ois.readObject();
//        for (Student student : list1) {
//            System.out.println(student);
//        }
        ois.close();
    }
}
Properties

概述:

  • 是一个Map体系的集合类
  • Properties中有跟IO相关的方法
  • 只存字符串
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class PropertiesTest {
    public static void main(String[] args) {
        Properties prop = new Properties();
        //增
        prop.put("河南","郑州");
        prop.put("河北","石家庄");
        prop.put("山西","太原");
        prop.put("山东","济南");
        System.out.println(prop);
        //删
        prop.remove("山东");
        System.out.println(prop);
        //改
        //put 如果键不存在,那么就添加,如果键存在,那么就覆盖
        prop.put("河南","豫州");
        System.out.println(prop);
        //查
        Object value = prop.get("河北");
        System.out.println(value);
        //遍历
        Set<Object> keys = prop.keySet();
        for (Object key : keys) {
            Object value1 = prop.get(key);
            System.out.println(key+"="+value1);
        }
        System.out.println("------------");
        Set<Map.Entry<Object, Object>> entries = prop.entrySet();
        for (Map.Entry<Object, Object> entry : entries) {
            System.out.println(entry.getKey()+"="+entry.getValue());
        }
    }
}
Properties作为集合的特有方法
方法名说明
Object setProperty(String key,String value)设置集合的键和值,都是String类型,底层调用Hashtable方法put
String getProperty(String key)使用此列表中指定的键搜索属性
Set stringPropertyName()从该属性列表中返回一个可修改的健集,其中键及其对应的值是字符串

示例:

import java.util.Properties;
import java.util.Set;

public class PropertiesTest2 {
    public static void main(String[] args) {
        Properties prop = new Properties();
        prop.setProperty("河南","郑州");
        prop.setProperty("陕西","西安");
        prop.setProperty("海南","海口");
        prop.setProperty("台湾","台北");
        System.out.println(prop);
        String value = prop.getProperty("海南");
        System.out.println(value);
        Set<String> keys = prop.stringPropertyNames();
        for (String key : keys) {
            String value1 = prop.getProperty(key);
            System.out.println(key+"="+value1);
        }
    }
}
Properties和IO流结合的方法:
方法名说明
void load(InputStream inStream)从输入字节流读取属性列表(键和元素对)
void load(Reader reader)从输入字符流读取属性列表(键和元素对)
void store(OutputStream out,String comments)将此属性列表(键和元素对)写入此Properties表中,以适合于使用load(InoutStream)方法的格式写入输出字节流
void store(Writer writer,String comments)将此属性列表(键和元素对)写入此Properties表中,以适合使用load(Reader)方法的格式写入输出字符流
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;

public class PropertiesTest3 {
    public static void main(String[] args) throws IOException {
        //读取
        Properties prop = new Properties();
        FileReader fr = new FileReader("day21\\prop.properties");
        //调用完了load方法之后,文件中的键值对数据已经在集合中了
        prop.load(fr);
        fr.close();
        System.out.println(prop);

        prop.put("sansan","123");
        prop.put("sisi","456");
        prop.put("wuwu","789");
        FileWriter fw = new FileWriter("day21\\prop.properties");
        prop.store(fw,null);
        fw.close();
    }
}
练习1

请使用“便捷字符流”配合数组将指定文件(笔者用的是“大地之灯.txt”)的内容打印到控制台,并统计出读文本共使用的时间;

public class Test1 {
    public static void main(String[] args) throws IOException {
        //获取当前时间
        long t1 = System.currentTimeMillis();
        //创建字符输入流对象
        FileReader fr = new FileReader("day21\\src\\大地之灯.txt", Charset.forName("gbk"));
        char[] arr = new char[1024];
        int len = 0;
        //read方法还是读取,但是一次读取多个字符
        //他把读到的字符都存入到arr数组
        //返回值:表示本次读到了多少个字符
        while ((len=fr.read(arr))!=-1){
            String s = new String(arr,0,len);
            System.out.print(s);
        }
        fr.close();
        long t2 = System.currentTimeMillis();
        System.out.println();
        System.out.println(">>>>>>>>>>>>>>>>>>>>");
        System.out.println("读取文件共使用了:"+(t2-t1)+"毫秒");
    }
}

结果:

image-20220225010037333

练习2

将下列文件中的学生信息按照年龄升序排序后重新写回原文件;要求:使用字符缓冲流完成;每次循环读取一行信息;写数据的时候换行使用newLine方法。

TXT文件内容:

凯亚,18
白山,19
可莉,17
阿七,22
public class Test2 {
    public static void main(String[] args) throws IOException {
        //创建文件对象和字符缓冲流对象,准备读数据
        File f = new File("day21\\src\\1.txt");
        BufferedReader br = new BufferedReader(new FileReader(f));
        //准备TreeSet集合,用于保存读到的学生对象并排序
        TreeSet<Student> set = new TreeSet<Student>((s1,s2)->s1.getAge()-s2.getAge()==0?s1.getName().compareTo(s2.getName()):s1.getAge()-s2.getAge());
        String s = null;
        while ((s=br.readLine())!=null){
            String[] split1 = s.split(",");
            //把切分出来的数组的第一个值作为name,第二个值作为age,创建学生对象,并按照年龄排序
            Student stu = new Student(split1[0],Integer.parseInt(split1[1]));
            set.add(stu);
        }
        //创建输出流,并把set集合中的学生信息重新写入1.txt文件中;
        BufferedWriter bw = new BufferedWriter(new FileWriter("day21\\src\\1.txt"));
        for(Student stu : set) {
            bw.write(stu.toString());
            bw.newLine();//换行,不用考虑系统问题,比写\r\n更通用
        }
        br.close();
        bw.close();
        System.out.println("排序已完成");
    }
}



public class Student {
    private String name;
    private int age;

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

    @Override
    public String toString() {
        return name + "," + age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o;

        if (age != student.age) return false;
        return name != null ? name.equals(student.name) : student.name == null;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值