JavasSEDemo31IO流

简介

  • 本文是2021/04/29整理的笔记
  • 赘述可能有点多,还请各位朋友耐心阅读
  • 本人的内容和答案不一定是最好最正确的,欢迎各位朋友评论区指正改进

易错练习题

练习1

byte b = 127;
System.out.println(-b);

选择程序运行结果
A、-127
B、0
C、-128
D、运行错误
答案
A

练习2

对于switch/case语句以下说法正确的有。
A、default语句是可选的,但是如果出现default则必须位于所有的case后面
B、case子句后面的值必须是常量,且不可重复
C、switch后面的表达式的值如果是数值型,则必须是可精确匹配的整数值,如int\long,而不能是浮点数
D、case后面的break是必选的,不能省略break

练习3

以下哪个是有关封装优点的正确描述?
A、 可以不用定义成员变量
B、 可以直接通过类名修改属性
C、 可以不需要改变接口来改变实现,以达到外部使用代码无需变动
D、 可以不需要改变实现来改变接口,已达到外部使用代码无需变动

练习4

当一个类的所有构造器均为私有的,以下哪个描述是正确的?
A、 不能被其他类实例化
B、 不能被其他类继承
C、 既不能被其他类实例化,也不能被其他类继承
D、 该类必须被final修饰

练习5

交易明细文件内容如下例:log.txt
#姓名 性别 帐号 发生额
刘德华|1|4155990188888888|300.00
晓龙|1|1155990199999999|500.00
黄晓明|1|4155990100000000|1000.50
张东健|1|4155990155555555|600.99
梁朝伟|0|4155990111111111|5000.00
刘德华|1|4155990188888888|200.00
张东健|1|4155990155555555|500.99
刘德华|1|4155880188888888|1200.00
PS:1)一行是一条交易明细,每行分4列,列间用|分隔。#为注释符号。
2)类TransRecord存储一条明细。
实现功能:
一个人可能消费有多笔。(当姓名和账号相同的话就认为是同一人)统计每个人的消费总额。按消费额的金额升序排序。要求显示每个人的姓名、性别、帐号、消费总额的信息

public  class TransRecord implements Comparable<TransRecord>{
    private String name;
    private int sex;
    private String number;
    private double money;

    @Override
    public String toString() {
        return "Exchange{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", number='" + number + '\'' +
                ", price=" + money +
                '}';
    }

    public TransRecord() {
    }

    public TransRecord(String name, int sex, String number, double price) {
        this.name = name;
        this.sex = sex;
        this.number = number;
        this.money = price;
    }

    public String getName() {
        return name;
    }

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

    public int getSex() {
        return sex;
    }

    public void setSex(int sex) {
        this.sex = sex;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }




    @Override
    public int compareTo(TransRecord o) {
        double d = this.getMoney() - o.getMoney();
       if(d >0){
           return 1;
       }else{
           return -1;
       }
    }
}
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.TreeSet;
public class Demo03homework {
    public static void main(String[] args) throws IOException {
        //创建TreeSet集合,存储类型为TransRecord
        TreeSet<TransRecord> treeSet = new TreeSet<>();
        TreeSet<TransRecord> treeSet1 = new TreeSet<>();
        //创建基本字符输入流
        FileReader fileReader = new FileReader("D:\\AJavaStudyTest\\homework\\log.txt");
        //创建缓冲字符输入流
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        String line;
        while((line = bufferedReader.readLine())!=null){
            if(line.contains("|")){
                String[] split = line.split("\\|");
                TransRecord transRecord = new TransRecord(split[0], Integer.parseInt(split[1]), split[2], Double.parseDouble(split[3]));
                boolean flag =false;
                for (TransRecord record : treeSet) {
                    if(record.getName().equals(transRecord.getName()) && record.getNumber().equals(transRecord.getNumber()) && record.getSex()==(transRecord.getSex())){
                        flag =true;
                        record.setMoney(record.getMoney() + transRecord.getMoney());
                    }
                }
                if(!flag){
                    treeSet.add(transRecord);
                }
            }
        }
        bufferedReader.close();
        fileReader.close();
        for (TransRecord transRecord : treeSet) {
            treeSet1.add(transRecord);
        }
        for (TransRecord transRecord : treeSet1) {
            System.out.println("transRecord = " + transRecord);
        }
    }
}

练习6

题目:
将一个文件夹中的内容复制到其它目录中。(比如:把D:\chenhao中的内容复制一份到 e:\zhangsan文件夹中)
(递归和通过字节流来进行复制FileInputStream和FileOutputStream)

import org.junit.Test;
import java.io.*;

/**
 * 将一个文件夹中的内容复制到其它目录中。(比如:把D:\\chenhao中的内容复制一份到 e:\\zhangsan文件夹中)
 * (递归和通过字节流来进行复制FileInputStream和FileOutputStream)
 */
public class Demo03 {
    @Test
    public void test() throws IOException {
        diGui(new File("D:\\A国创"),new File("D:\\B国创"));
    }
    private void diGui(File source,File dest) throws IOException {
        //source存在
        if(source.exists()){
            if(source.isDirectory()){
                //在目标文件夹创建这个文件夹
                File dir = new File(dest + "/" + source.getName());
                //创建子文件夹
                dir.mkdirs();
                //遍历原文件夹的每一项
                File[] files = source.listFiles();
                if (files!=null && files.length >0) {
                    for (File file : files) {
                        //file.exists()
                            diGui(file, dir);
                }
            }
        }else {
                copy(source, dest);
                return;
            }
            }
    }

    public  void copy(File source, File dest) throws IOException {
        BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(source));
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(dest + "/" + source.getName()));
        byte[] bytes = new byte[1024];
        int length;
        while((length = bufferedInputStream.read(bytes))!=-1){
            bufferedOutputStream.write(bytes,0,length);
        }
        bufferedOutputStream.close();
        bufferedInputStream.close();
    }


}


注意:Win10系统在复制文件夹之前,需要将文件夹权限改为完全访问。

练习7

题目
获取一个文件夹下所有指定后缀名(.java)的文件(包括子文件夹中的内容),并将这些文件的绝对路径写入到一个文本文件中

import org.junit.Test;

import java.io.*;

public class Demo08 {
    private PrintWriter printWriter= new PrintWriter(new FileWriter("result.txt"));

    public Demo08() throws IOException {
    }

    @Test
    public void test(){
        diGui(new File("D:\\王力宏"));
        printWriter.close();
    }

    private void diGui(File file){
        if(file.isDirectory()){
            File[] files = file.listFiles();
            for (File file1 : files) {
                if(file1.isFile()){
                    save(file1);
                }else {
                    diGui(file1);
                }
            }
        }else {
            save(file);
        }
    }

    private void save(File file){
        if(file.getName().endsWith(".java")){
            //向文件写
            printWriter.println(file.getAbsolutePath());
        }
    }
}

练习8

题目
题目:实现一个方法日志记录器,将每次方法的调用信息存放在单一的文本日志文件中,并能够分析日志文件中包含的数据:调用次数最多的方法,调用总耗时最长的方法
考点:输入输出流
难度:中
思路:

  1. 日志文件
  2. 写内容:类#方法名#开始时间#结束时间#本次耗时
  3. 什么时候写日志:方法里开头写:类#方法名#开始时间 方法结尾写:#结束时间#本次耗时
  4. 分析日志文件:读取日志文件逐行解析
    (1)调用次数最多的方法:map: key:类+方法名组合 value:调用次数
    (2)调用总耗时最长的方法:map key:类+方法名组合 value:耗时
import java.io.FileNotFoundException;
import java.io.PrintWriter;

public class Logger {
    private PrintWriter printWriter;
    {
        try {
            printWriter = new PrintWriter("log.txt");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
    public void log(String string){
        printWriter.print(string);
        printWriter.flush();
    }
    public void logLn(String string){
        printWriter.println(string);
        printWriter.flush();
    }
}

import java.text.SimpleDateFormat;
import java.util.Date;

public class MyClass {
    private Logger logger = new Logger();
    public void eat(){
        logger.log(this.getClass().getName() + "#eat()#" +getTime()+"#");
        long start  = System.currentTimeMillis();
        System.out.println("MyClass.eat([])方法");
        try {
            Thread.sleep(1200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        //方法结尾写:#结束时间#本次耗时
        logger.logLn(getTime()+"#"+(end-start));
    }
    public String getTime(){
        return  new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(new Date());
    }
    public void study(){
        logger.log(this.getClass().getName() + "#study()#" +getTime()+"#");
        long start  = System.currentTimeMillis();
        System.out.println("MyClass.study([])方法");
        try {
            Thread.sleep(2200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        //方法结尾写:#结束时间#本次耗时
        logger.logLn(getTime()+"#"+(end-start));
    }

    public void drink(){
        logger.log(this.getClass().getName() + "#drink()#" +getTime()+"#");
        long start  = System.currentTimeMillis();
        System.out.println("MyClass.drink([])方法");
        try {
            Thread.sleep(5200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        //方法结尾写:#结束时间#本次耗时
        logger.logLn(getTime()+"#"+(end-start));
    }
    public void play(){
        logger.log(this.getClass().getName() + "#play()#" +getTime()+"#");
        long start  = System.currentTimeMillis();
        System.out.println("MyClass.play([])方法");
        try {
            Thread.sleep(1200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        //方法结尾写:#结束时间#本次耗时
        logger.logLn(getTime()+"#"+(end-start));
    }
}

public class TestMyClass {
    public static void main(String[] args) {
        MyClass myClass = new MyClass();
        myClass.eat();
        myClass.eat();
        myClass.eat();
        myClass.drink();
        myClass.drink();
        myClass.study();
        myClass.study();
        myClass.play();
    }
}

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class TestLogAnalysis {
    public static void main(String[] args) throws IOException {
        //分析日志文件:读取日志文件逐行解析
        BufferedReader bufferedReader = new BufferedReader(new FileReader("log.txt"));
        String line;
        Map<String, Integer> map1 = new HashMap<>();
        Map<String, Integer> map2 = new HashMap<>();
        while((line = bufferedReader.readLine())!=null){
            String[] split = line.split("#");
            String key = split[0] + "-" + split[1];
                //解决数量问题
                Integer count = map1.get(key);
                if(count != null){
                    map1.put(key,count+1);
                    //原来没有,就放1
                }else {
                    map1.put(key,1);
                }

                //耗时
                Integer time = map2.get(key);
                if(time !=null){
                    map2.put(key,time + Integer.parseInt(split[4]));
                }else {
                    map2.put(key,Integer.parseInt(split[4]));
                }

        }

       //调用次数最多的方法
        int maxCount = 0;
        String maxKey = null;
        for (Map.Entry<String, Integer> entry : map1.entrySet()) {
            if(entry.getValue() > maxCount){
                maxCount = entry.getValue();
                maxKey = entry.getKey();
            }
        }
        System.out.println("调用方法最多的是"+maxKey + ",调用方法次数是:"+maxCount);


        //调用时间最长的方法
        int maxTime = 0;
        for (Map.Entry<String, Integer> entry : map2.entrySet()) {
            if(entry.getValue() > maxCount){
                maxTime = entry.getValue();
                maxKey = entry.getKey();
            }
        }
        System.out.println("调用方法最多的是"+maxKey + ",调用方法次数是:"+maxTime);


        bufferedReader.close();
    }
}

序列化与反序列化

什么是序列化

  • 将对象的状态信息保存到流中的操作,称为序列化。

什么是反序列化

  • 将流中读取对象状态信息的操作称为反序列化。

怎么实现序列化

  1. 让实体类实现Serializable 接口 生成serialVersionUID
  2. 创建ObjectOutputStream(new FileOutputStream(文件名称))
  3. 调用writeObject(new 对象)

怎么实现反序列化

  1. new ObjectInputStream(new FileInputStream(文件名称))
  2. 调用readObject()返回Object,向下转型,将其强转为对应的对象。
  3. 打印输出

自定义序列化1

  1. 在实现了Serializable接口的类中写两个方法
  2. private void writeObject(ObjectOutputStream out){
    out.defaultWriteObject();
    out.writeUTF(address+“小贝贝”);
    }
  3. private void readObject(ObjectInputStream in){
    in.defaultReadObject();
    address = in.readUTF();
    }

自定义序列化2

  1. 在实现了Serializable接口的类中写两个方法
  2. private void writeObject(ObjectOutputStream out){
    out.writeUTF(name+“小贝贝”);
    out.writeInt(age);
    out.writeUTF(addres+“小贝贝”)
    }
  3. private void readObject(ObjectInputStream in){
    name = in.readUTF();
    age = in.readInt();
    address = in.readUTF();
    }

自定义序列化3

  1. 让类实现Externalizable接口。重写2个方法
 @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeUTF(name+"小贝贝");
        out.writeInt(age);
        out.writeUTF("天安门"+address);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        name = in.readUTF();
        age = in.readInt();
        address = in.readUTF();
    }

在字段前加transient关键字,该字段就不会被默认序列化

在字段前加static关键字,该字段页不会被默认序列化

serialVersionUID推荐加上,如果不加:会根据类名 属性名 方法名 接口名 生成;如果修改了其中的任何一项,都会引起serialVersionUID的改变,反序列化会引发InvalidClassException异常

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

香鱼嫩虾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值