java代码-------IO2(尚马day23) week5(13)

13 篇文章 0 订阅

(1)数据流

//注册用户:  id-name-pass-age   每次拿,需要读一行,然后分割,再转类型
//如何直接拿,不需要转型  用数据流(也是字节流,但一般的字节流操作汉字会出现乱码)
@Data
class User {
    private Integer id;
    private String name;
    private double balance;
    private byte age;
}

public class DataDemo {
    public static void main(String[] args) {

        //注册用户:  id-name-pass-age    FileWriter.write(String str)
        //读取一个用户信息:  BufferedReader.readLine()  split()  Integer.parseInt()

        try {
            testRead();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    //对于数据流  最常用的场景:  writeUTF/readUTF   (写一个汉字,读一个汉字)
    //何时用它?  网络数据传输: 传输的都是字节内容  使用writeUTF/readUTF避免出现乱码的问题

    private static void testWrite() throws FileNotFoundException {
        //1.创建数据输出流对象    将数据从任意类型转为一系列字节,并写入二进制流   这是写给dataInputStream看的
        DataOutputStream dataOutput = new DataOutputStream(new FileOutputStream("src/b.txt"));
        try (dataOutput) {
            dataOutput.writeInt(1001);
            dataOutput.writeUTF("张三");
            dataOutput.writeDouble(89999.567);
            dataOutput.writeByte(20);
            dataOutput.writeBoolean(true);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void testRead() throws FileNotFoundException {
        //1.创建数据输入流对象
        DataInputStream dataInputStream = new DataInputStream(new FileInputStream("src/b.txt"));

        User user = new User();
        //可以读,但前提要先写出来,才能读   人工写的它不认识    从二进制流里读数据
        try (dataInputStream) {
            user.setId(dataInputStream.readInt());     //每次读4个字节
            user.setName(dataInputStream.readUTF());
            user.setBalance(dataInputStream.readDouble());
            user.setAge(dataInputStream.readByte());
            System.out.println(dataInputStream.readBoolean());
            System.out.println(user);
            //未先写就读,报此异常 java.io.EOFException  end of file   读到文件末尾也没发现这些东西
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void testRead1() throws FileNotFoundException {
        //用以前的方法做
        //弊端: 每读一个数据  都要进行类型的强制转换
        BufferedReader reader = new BufferedReader(new FileReader("src/user.txt"));
        User user = new User();
        try (reader) {
            String id = reader.readLine();
            String name = reader.readLine();
            String balance = reader.readLine();
            String age = reader.readLine();
            user.setId(Integer.parseInt(id));
            user.setName(name);
            user.setAge(Byte.parseByte(age));
            user.setBalance(Double.parseDouble(balance));

            System.out.println(user);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

(2)对象流

//Serializable是一个标记接口  jvm可以将这个类型的对象写入文件中
//修改java文件都需要重新编译新的class,产生新的class文件的版本号serialVersionUID,版本号唯一的,通过它可找到class文件
//在正常开发中: 记住一点  封装数据类(用户类,商品类等)上面 一定要实现 Serializable  并提供版本id
//类实现 Serializable接口在开发中 肯定是没有问题的(后期的Redis缓存/远程接口访问RMI)
//不实现Serializable  程序就有可能出现问题。
@Setter
@Getter
@ToString
public class Student implements Serializable {
    private static final long serialVersionUID = -1775089732470255694L;
    //版本号的id是自动生成的    编译工作是IDEA调javac做的,想生成id,告诉IDEA(让idea提醒我们自动生成id值)
    //setting--Editor--inspections--java--serialization issues--serializable class without ‘serialVersionUID’--选中

    private Integer id;
    private String name;
    private double balance;
    private int age;
    private int num;

    public Student() {
        System.out.println("无参构造.....");
    }


}

//对象流也要求先写才能读
public class ObjectDemo {
    public static void main(String[] args) {
        demo2();
    }

    private static void demo2() {
        //读取文件里面的对象
        try {
            ObjectInput objectInput = new ObjectInputStream(new FileInputStream("src/a.ini"));
            Student student = (Student) objectInput.readObject();
            System.out.println("读取到的文件对象:" + student);
            //读取到的文件对象:com.lisa.io.Student@7d9d1a19
            objectInput.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            //ClassNotFoundException 找不到字节码文件,也就是jvm里面找不到这个类型的class文件
            //出现该异常有两种原因:
            //1.1 java文件没有被编译(类没有被编译)
            //1.2 可能没有引入第三方的类库(架包)
            e.printStackTrace();
        }
    }

    private static void demo1() {
        //对于数据流    弊端:  读取多次 获得每个属性的信息  赋值多次
        //对象流:直接读写一个完整的对象信息
        //对象流也是在数据流基础之上丰富了一些功能。除了可以操作字面量类型 还可以操作对象类型。
        try {
            ObjectOutput objectOutput = new ObjectOutputStream(new FileOutputStream("src/a.ini"));
            //无参构造.....
            //写入的对象:com.lisa.io.Student@38082d64
            Student student = new Student();
            System.out.println("写入的对象:"+student);
            student.setId(1);
            student.setName("张三");
            //student.setAge((byte) 20);
            student.setBalance(100000.123);
            objectOutput.writeObject(student);
            objectOutput.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //只写完运行会报 NotSerializableException 没有支持序列化异常
        //这里做的事情:将对象写入磁盘文件中。     对于jvm,若操作对象 这个对象类型必须支持序列化(序列化跟writeObject有关)
        //之前学的克隆: 克隆一个对象   也是jvm底层做的  要克隆的前提: 实现Cloneable接口
        //类似的,想序列化student,必须让它支持序列化,告诉jvm,student可以被序列化,故student要实现Serializable接口
        //序列化流就是ObjectOutputStream,将对象写入文件
        //反序列化流就是ObjectinputStream,读取文件里的对象
    }
}

(3)转换流

字节转字符----将网络上的小说章节内容,下载到本地

字符转字节----打印输出

/**
 * @author: sunshine
 * @description:
 * @data: 2022/3/12  23:16
 * @version: 0.1
 * @since: jdk11
 */
public class NovelDemo {
    public static void main(String[] args) {
        try {
            demo1();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    private static void demo1() throws FileNotFoundException {
        //需求:读取指定文件的数据,在控制台打印输出(将数据写在控制台)
        //读取是read  输入流  字节输入流   字符输入流  比较合适的是字符输入流,从中选BufferedReader
        //打印是write  输出流  对应的用Bufferedwriter

        BufferedReader reader = new BufferedReader(new FileReader("src/novel.txt"));
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));   //写到控制台上去,之前是new FileWriter
        //OutputStreamWriter字符转字节

        //System.out.println("fasf") 为何调此命令可将内容打印到控制台,是字符串的println做的
        //out是printStream,继承FilterOutputStream字节输出流  关键还是在out
        //底层实现: 将数据打印在控制台---->System.out  字节输出流
        try (reader;writer) {
            String line;
            while ((line = reader.readLine()) != null) {    //循环去读
                writer.write(line);      //字符输出流写,但其实底层是转成字节输出流    一次写一行   因为想输出到控制台得结合打印流完成
                writer.newLine();        //换行
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private static void downloadNovel() throws IOException {
        //字节转字符场景:拿取网络资源,且和转换流相关的一般用BufferedReader和BufferedWriter   已成模板

        String novelPath = "https://read.qidian.com/chapter/WS49qjrNDI7v7_WH3wfEdQ2/uNA4HnHXD0P6ItTi_ILQ7A2/";  //小说章节路径(肯定加密了)
        novelPath = "https://read.qidian.com/chapter/OD1kAAaaLgMKgXB091LLaA2/eGiW7wfkoWTM5j8_3RRvhw2/";
        //novelPath = "http://book.zongheng.com/chapter/1099697/64049078.html";   //全加密,这个就没法下载

        //网络上的所有的数据都是字节流。
        //想获得万维网的资源指针。条件:1.有网。2.获得万维网资源指针URL(统一资源定位符),拿到该指针就能拿到网络上的数据
        //URL url = new URL(novelPath);      //url也是个类,在java.net  读取网络资源,用InputStream
        //InputStream inputStream = url.openStream();   //此时网络的数据都在inputStream
        //在读取的功能里面: 程序本应该使用字节流进行读取   但是我们想使用字符流进行高效读取
        //转换: 字节流读取转换成字符流读取

        //高效字符流实现读写功能
        //BufferedReader reader = new BufferedReader(new FileReader(novelPath) FileReader是找磁盘文件,故不能这样写
        BufferedReader reader = new BufferedReader(new InputStreamReader(new URL(novelPath).openStream(), StandardCharsets.UTF_8));
        //new URL(novelPath).openStream()是字节流,需转字符流,同时指定编码格式(不能随便给,看人家编码格式给的什么)
        BufferedWriter writer = new BufferedWriter(new FileWriter("src/novel1.txt"));
        try (reader; writer) {
            //循环读写
            String line;
            while ((line = reader.readLine()) != null) {    //每次读一行
                //System.out.println(line);
                if (line.contains("class="read-content j_readContent"")) {   //这是看着下载的模板进项修改,去除没用部分
                    reader.readLine();
                    reader.readLine();
                    line = reader.readLine();
                    writer.write(line.replaceAll("<p>", "
"));
                    break;
                }
            }
        }
        System.out.println("下载成功");
    }
}

(4)Properties 一个能和IO结合使用的类,是hashTable的一个子类,称为属性集

一般存 属性名=属性值

和map方法一样,但一般不用

/**
 * @author: sunshine
 * @description:
 * @data: 2022/3/13  0:06
 * @version: 0.1
 * @since: jdk11
 */
public class PropertiesDemo {

    public static void main(String[] args) {

        demo6();

    }

    private static void demo6() {
        Properties properties = new Properties();
        properties.setProperty("id", "1001");
        properties.setProperty("score", "90");
        properties.setProperty("studentName", "李雷");

        //将properties里面的数据写入文件中
        try {
            properties.store(new FileOutputStream("src/student.properties"),"哈哈哈哈哈");  //第二个参数是注释
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void demo5() {
        Properties properties = new Properties();
        try {
            //加载文件的数据
            properties.load(new FileInputStream("src/user.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        //加载properties文件,出现汉字也会乱码,此时改idea配置,改后不再乱
        //setting--搜encoding--File Encodings--全改成utf-8
        System.out.println(properties);
    }


    //配置文件后缀:  properties  xml  yml/yaml
    private static void demo4() {

        //用properties读取demo3()的文件数据
        Properties properties = new Properties();
        try {
            //加载文件的数据
            properties.load(new FileInputStream("src/user.txt"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println(properties);
        String name = properties.getProperty("name");   //想要value,直接给key
        System.out.println(name);
        //将jim改成中文的李四,结果乱码了,此时要解码      手动解码,用String     properties底层默认ISO_8859_1编码格式
        String decodeName = new String(name.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);  //转成UTF-8
        System.out.println(decodeName);

    }

    private static void demo3() throws FileNotFoundException {
        //Properties:体现在读取核心配置文件的数据
        //要求文件里面数据格式是固定的:key=value,且一行中只有一组数据

        //假设一个配置文件里的内容如下:
        //id=1001
        //name=jim
        //age=20

        //如何获得id  name  age的数据
        //读: 字节/字符输入流  Reader  FileReader(一次读一个字符或字符数组,不合适)  BufferedReader(读一行)

        BufferedReader reader = new BufferedReader(new FileReader("src/user.txt"));

        try (reader) {
            String line;
            while ((line = reader.readLine()) != null) {
                String[] array = line.split("=");
                System.out.println(array[0] + "---" + array[1]);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private static void demo2() {

        Properties properties = new Properties();
        //一般推荐使用以下的方法
        properties.setProperty("id", "1001");      //一般参数是String类型
        properties.setProperty("name", "张三");
        properties.setProperty("age", "20");

        System.out.println(properties.getProperty("id"));
        System.out.println(properties.getProperty("name"));
        System.out.println(properties.getProperty("age"));

        //相比map集合方法: 类型转换的次数少一些
        //但仍不是最重要的方法,要结合IO用
    }

    private static void demo1() {

        //针对于Properties: 以下方法 都不用
        //回顾以下map集合的方法
        Properties properties = new Properties();
        //存储数据
        properties.put("id", 1001);
        properties.put("name", "张三");
        properties.put("age", 20);

        //获得数据
        /*int id = (int) properties.get("id");
        String name = (String) properties.get("name");
        int age = (int) properties.get("age");

        System.out.println(id);
        System.out.println(name);
        System.out.println(age);*/

        //遍历Properties里面所有的数据
        //properties.forEach((k,v)-> System.out.println(k+"----"+v));
        /*Set<Map.Entry<Object, Object>> entrySet = properties.entrySet();
        for (Map.Entry<Object, Object> entry : entrySet) {
            System.out.println(entry.getKey() + "---" + entry.getValue());
        }*/
    }
}

(5)单例模式问题

/**
 * @author: sunshine
 * @description:
 * @data: 2022/3/13  0:32
 * @version: 0.1
 * @since: jdk11
 */
//单例模式是保证单实例的
public class Admin implements Cloneable, Serializable {
    private static final long serialVersionUID = 1486187929375171608L;

    private Admin() {    //1.构造方法私有化
    }

    private static final Admin admin = new Admin();   //饿汉,一上来就new

    public static Admin getInstance() {   //提供对外访问的入口
        return admin;
    }

    public Object readResolve() {
        return admin;
    }

    @Override
    public Admin clone() {
        /*Admin admin = null;
        try {
            admin = (Admin) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return admin;*/
        return this;
    }
}

public class Demo {

    public static void main(String[] args) {

        //目的:保证admin的单例
        Admin admin = Admin.getInstance();   //获得一个实例
        System.out.println("原对象:" + admin);

        /*Admin cloneAdmin = admin.clone();    //克隆一个对象,此时Admin要实现Cloneable接口,且重写clone方法
        System.out.println("克隆的对象:" + cloneAdmin);*/   //产生了新的对象

        //序列化----> ObjectOutputStream   写
        String path = "src/aa.txt";
        try {
            ObjectOutput objectOutput = new ObjectOutputStream(new FileOutputStream(path));
            objectOutput.writeObject(admin);
            objectOutput.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //反序列化: ObjectInputStream    读
        try {
            ObjectInputStream objectInput = new ObjectInputStream(new FileInputStream(path));
            Admin readAdmin = (Admin) objectInput.readObject();
            System.out.println("读取的对象:" + readAdmin);      //又产生了新的对象
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }


        //维护单例的最佳实现方案:  枚举类

        //获得对象方式:
        //1. new
        //2. 克隆: 可以打破单例     为避免打破单例,在重写的克隆方法里写: return this/Admin; 就这一句话
        //3. 序列化: 可以打破单例      为避免打破单例,需在单例模式里提供readResolve()方法,这个只能返Admin,不能用this
        //4. 反射,也能打破单例
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值