java中文本I/O、日期与时间API

一、文本I/O

1、字符流

字符流是以字符(char)为单位读写数据的:一次处理一个Unicode

  • 字符流的底层仍然是基本的字节流
  • 字符流封装了字符的编码解码算法

字符输出流:

/**
 * @document: 文件字符输出流
 * @Author:SmallG
 * @CreateTime:2023/8/3+15:05
 */

public class Demo01 {
    public static void main(String[] args) {
        FileWriter writer = null;
        try {
            writer = new FileWriter("F:/hello.txt");
            //往文件中写入内容
            writer.write("SmallG大帅锅\n");
            writer.write("SmallY大美铝\n");
        } catch (IOException e) {
            System.out.println(e.getMessage());
        } finally {
            //再finally中关闭流 关闭前提:write不为空
            //try语句块执行后,如果在执行try出错了,writer对象没创建成功,所以不用关
            if (writer != null){
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

字符输入流:

/**
 * @document: 字符文件输入流:读取文件内容
 * @Author:SmallG
 * @CreateTime:2023/8/3+15:15
 */

public class Demo02 {
    public static void main(String[] args) {
        FileReader reader = null;
        try {
            reader = new FileReader("F:/hello.txt");
            //定义读取字符的容器  一次读5个字符
            char[] data = new char[5];
            int len = -1;
            while ((len = reader.read(data)) != -1) {
                //转换为字符串
                String str = new String(data, 0, len);
                System.out.print(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

try-with-resources语法

  • 目的是为了简化try-catch-finally语句块
  • finally语句块不能范围try语句中声明的变量,这样有了try-with-resources语句
  • try后面的()称为资源说明头,用于创建语句块中使用的资源对象
  • 资源说明头中创建的对象必须实现java.lang.AutoCloseable接口,该接口只有一个方法-close()
/**
 * @document: try-with-resources语法
 * @Author:SmallG
 * @CreateTime:2023/8/3+15:31
 */

public class Demo03 {
    public static void main(String[] args) {
        try (
                MyStream1 stream1 = new MyStream1();
                MyStream2 stream2 = new MyStream2()
        ) {
            System.out.println("try with resources");
            System.out.println(stream1);
            System.out.println(stream2);
        } catch (Exception e) {

        }
    }
}

class MyStream1 implements Closeable {

    @Override
    public void close() throws IOException {
        System.out.println("MyStream1流关闭了");
    }
}

class MyStream2 implements Closeable {

    @Override
    public void close() throws IOException {
        System.out.println("MyStream2流关闭了");
    }
}

2、字符缓冲流

  • BufferedReader---------->字符输入缓冲流,缓冲区大小为8192个字符
  • BufferedWriter----------->字符输出缓冲流,缓冲区大小为8192个字符
  • BufferedReader,提供了readLine:读取一行内容,以'\n','\r'来识别,返回的内容不包括换行符。skip:跳过指定数量的字符。
  • BufferedWriter中没有提供相似的writeLine方法,但提供了newLine方法,达到换行效果。
字符输出缓冲流
/**
 * @document: 字符输出缓冲流
 * @Author:SmallG
 * @CreateTime:2023/8/3+15:47
 */

public class Demo04 {
    public static void main(String[] args) {
        try (
                FileWriter writer = new FileWriter("F:/hello.txt");
                BufferedWriter bw = new BufferedWriter(writer)
        ) {
            bw.write("第一行内容:SmallG大帅锅\n");
            bw.newLine();
            bw.write("第二行内容:Hello BufferedWriter");
            bw.newLine();
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }
}
字符输入缓冲流
/**
 * @document: 字符输入缓冲流
 * @Author:SmallG
 * @CreateTime:2023/8/3+15:52
 */
public class Demo05 {
    public static void main(String[] args) {
        try (
                FileReader reader = new FileReader("F:/hello.txt");
                BufferedReader br = new BufferedReader(reader);
        ) {
            String line = br.readLine();
            while (line!=null){
                System.out.println(line);
                line = br.readLine();

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

3、转换流

用于字节流和字符流之间的转换

  • InputStreamReader:字节输入流------->字符输入流
  • OutputStreamWrite:字符输出流------->字节输出流
/**
 * @document: 转换流:字节文件------>字符文件
 * @Author:SmallG
 * @CreateTime:2023/8/3+16:22
 */

public class Demo06 {
    public static void main(String[] args) throws IOException {
        // 字节流转换为字符流后效率会高一些
        FileOutputStream fos = new FileOutputStream("F:/hello.txt");
        //创建转换流 转换为字符流  增加读取速度
        OutputStreamWriter osw = new OutputStreamWriter(fos);
        //创建缓冲流进一步提高读取效率
        BufferedWriter bw = new BufferedWriter(osw);
        bw.write("第一行数据:大帅锅");
        bw.newLine();
        bw.write("第二行数据:is SmallG");
        bw.newLine();
        bw.close();
        osw.close();
        fos.close();
    }
}
/**
 * @document: 字符转换输入流:字节流------>字符流
 * @Author:SmallG
 * @CreateTime:2023/8/3+16:36
 */

public class Demo07 {
    public static void main(String[] args) throws IOException {
        //定义一个字节文件输入流 加载字符文件
        FileInputStream fis = new FileInputStream("F:/hello.txt");
        //定义转换流
        InputStreamReader isr = new InputStreamReader(fis,"utf-8");
        //定义字符输入缓冲流进一步提高效率
        BufferedReader bfr = new BufferedReader(isr);

        String line = bfr.readLine();
        while (line!=null){
            System.out.println(line);
            line = bfr.readLine(); //继续读取
        }
        bfr.close();
        isr.close();
        fis.close();
    }
}

IO流总结

4、数据统计实例

/**
 * @document: 统计每个站点6月份最高温的平均值
 * @Author:SmallG
 * @CreateTime:2023/8/4+9:07
 */

public class DataAvgDemo {
    public static void main(String[] args) {
        try (
                //加载数据文件
                FileReader reader = new FileReader("F:/data1.csv");
                //创建缓冲流提高效率
                BufferedReader br = new BufferedReader(reader);
                //创建输出文件
                FileWriter writer = new FileWriter("F:/data2.csv");
                //创建缓冲流
                BufferedWriter bw = new BufferedWriter(writer);
        ) {
            //写入第一行表中信息
            bw.write("STATION,AVG");
            //统计数据 共五个站点 分组求平均值 分五组
            //去除除六月份的数据
            //定义一个保持所有站点的数组
            String[] stations = new String[]{"99727199999", "72505394728", "72055399999", "99774399999", "72503014732"};
            //定义一个保存所有站点6月最高温度平均值的数组
            BigDecimal[] tempDatas = new BigDecimal[5];

            for (int i = 0; i < tempDatas.length; i++) {
                tempDatas[i] = new BigDecimal(0);
            }
            //统计每个站点六月份共统计了几天
            int[] dataCount = new int[5];

            // 读取数据
            String line = br.readLine(); // 第一行是表头要忽略
            line = br.readLine(); // 从第二行数据开始读取
            while (line != null) {
                //处理数据
                String[] dataArray = line.split(",");
                //去除非6月份的数据
                if (!dataArray[1].startsWith("2019/6")) {
                    line = br.readLine();
                    continue; //当前数据不处理
                }
                //取出温度
                BigDecimal temp = new BigDecimal(dataArray[2]);
                //判断当前是那个站点
                if (dataArray[0].equals(stations[0])) {
                    tempDatas[0] = tempDatas[0].add(temp);
                    dataCount[0]++;
                } else if (dataArray[0].equals(stations[1])) {
                    tempDatas[1] = tempDatas[1].add(temp);
                    dataCount[1]++;
                } else if (dataArray[0].equals(stations[2])) {
                    tempDatas[2] = tempDatas[2].add(temp);
                    dataCount[2]++;
                } else if (dataArray[0].equals(stations[3])) {
                    tempDatas[3] = tempDatas[3].add(temp);
                    dataCount[3]++;
                } else if (dataArray[0].equals(stations[4])) {
                    tempDatas[4] = tempDatas[4].add(temp);
                    dataCount[4]++;
                }


                System.out.println(dataArray[1]);
                //继续读取下一行
                line = br.readLine();
            }
            for (int i = 0; i < tempDatas.length; i++) {
                //保留两位小数  四舍五入
                BigDecimal avg = tempDatas[i].divide(new BigDecimal(dataCount[i]), 2, RoundingMode.HALF_UP);
                StringBuilder builder = new StringBuilder();
                builder.append(stations[i]).append(",").append(avg);
                //写入一行数据
                bw.newLine(); // 换行
                bw.write(builder.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

二、日期与时间API

1、Date类

Date类的每一个实例表示一个时间,内部维护一个long值:自标准基准时间以来的毫秒数

/**
 * @document: Date类 能够表示日期和时间
 * @Author:SmallG
 * @CreateTime:2023/8/4+10:27
 */

public class Demo08 {
    public static void main(String[] args) {
        //创建date对象
        Date now = new Date();
        System.out.println(now); //Fri Aug 04 10:29:15 CST 2023

        //Date中大部分方法都已经过时了
        long time = now.getTime();
        System.out.println(time);

        now.setTime(0); //1970年1月1日 08:00:00

    }
}

2、SimpleDateFormat类

对输出的Date对象进行格式化,会自动调用Date类中的toString方法。

构造方法:

  • SimpleDateFormat()
  • SimpleDateFormat(String patter)

常用方法:

  • String format(Date date):将Date对象代表的时间格式化为字符串
  • Date parse(String source):将字符串解析为Date对象
/**
 * @document: 日期时间格式化:SimpleDateFormat
 * @Author:SmallG
 * @CreateTime:2023/8/4+10:47
 */

public class Demo09 {
    public static void main(String[] args) {
        //创建日期对象
        Date now = new Date();
        // 创建日期时间格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss a E");
        //把当前的系统时间 转换为固定格式的日期时间
        String format = sdf.format(now);

        System.out.println(format);
    }
}

3、新日期时间类概述

本地化的日期时间

  • LocalDate:表示日期
  • LocalTime:表示时间
  • LocalDateTime:两者组合
/**
 * @document: 本地化的时间日期
 * @Author:SmallG
 * @CreateTime:2023/8/4+11:11
 */

public class Demo10 {
    public static void main(String[] args) {
        //创建当前的时间对象
        LocalDateTime ldt1 = LocalDateTime.now();
        System.out.println(ldt1);

        //获取年月日信息
        System.out.print(ldt1.getYear() + "年");
        System.out.print(ldt1.getMonthValue() + "月");
        System.out.print(ldt1.getDayOfMonth() + "日");

        //获取时分秒信息
        System.out.print(ldt1.getHour() + "时");
        System.out.print(ldt1.getMinute() + "分");
        System.out.print(ldt1.getSecond() + "秒");
        System.out.println();

        //指定一个时间
        LocalDateTime ldt2 = LocalDateTime.of(2023, 10, 1, 10, 10, 0);
        System.out.println(ldt2);

        // 计算时间 当前时间加上6小时
        LocalDateTime ldt3 = ldt1.plus(6, ChronoUnit.HOURS)
                .plusMinutes(10); //再加十分钟;
        System.out.println(ldt3);
        //当前时间减去1小时
        LocalDateTime ldt4 = ldt1.minus(1, ChronoUnit.HOURS)
                .minusMinutes(10); //再减去10分钟
        
        System.out.println(ldt4);
    }
}

时区操作

now():方法可以获取当前时区的时间,在now中添加参数ZoneId.of("时区名"),可以获取相应时区的时间。

/**
 * @document: ZoneDateTime
 * @Author:SmallG
 * @CreateTime:2023/8/4+11:29
 */

public class Demo11 {
    public static void main(String[] args) {
        //创建时区对象
        ZonedDateTime zdt1 = ZonedDateTime.now();
        System.out.println(zdt1); //默认时区中国东八区时间

        //指定时区的时间
        ZonedDateTime zdt2 = ZonedDateTime.now(ZoneId.of("America/Los_Angeles"));  //美国西部时间(洛杉矶)
        System.out.println(zdt2);

        //通过LocalDateTime转换为ZoneDateTime
        LocalDateTime ldt = LocalDateTime.of(2023, 10, 1, 10, 10, 10);
        ZonedDateTime zdt3 = ldt.atZone(ZoneId.systemDefault()); //默认时区
        System.out.println(zdt3);

        ZonedDateTime zdt4 = ldt.atZone(ZoneId.of("America/New_York")); //美国东部时间
        System.out.println(zdt4);

        ZonedDateTime zdt5 = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
        //转换为巴黎时间
        ZonedDateTime zdt6 = zdt5.withZoneSameInstant(ZoneId.of("Europe/Paris"));
        System.out.println(zdt5);
        System.out.println(zdt6);
    }
}

日期时间格式化

DateTimeFormatter方法:

ofPattern():用于格式化时间

format():用于输出

/**
 * @document: DateTimeFormatter
 * @Author:SmallG
 * @CreateTime:2023/8/4+11:47
 */

public class Demo12 {
    public static void main(String[] args) {
        //创建当前时间
        ZonedDateTime zdt = ZonedDateTime.now();
        //创建日期格式
        DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        //输出日期
        System.out.println(formatter1.format(zdt));

        //换一种方式得到时间
        DateTimeFormatter formatter2 = DateTimeFormatter
                .ofPattern("yyyy MM dd EE HH:mm:ss", Locale.CHINA);
        System.out.println(formatter2.format(zdt));

        //获得英国的时间
        DateTimeFormatter formatter3 = DateTimeFormatter
                .ofPattern("E, MM/dd/yyyy HH:mm:ss", Locale.UK);
        System.out.println(formatter3.format(zdt));

        //指定时间
        DateTimeFormatter formatter4 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String time = "2023-10-01 10:10:10";
        LocalDateTime ldt = LocalDateTime.parse(time, formatter4);
        System.out.println(ldt);
    }
}

三、练习

1 读取文本文件中的每一行数据信息,求其和再存入最后一行

文本文件pw.txt的内容如下所示:

练习1

操作完毕之后的文本文件pw.txt的内容如下所示:

练习2

提示:基于字符流缓冲流实现。

/**
 * @document: 读取文本文件中的每一行数据信息,求其和再存入最后一行 字符流
 * @Author:SmallG
 * @CreateTime:2023/8/3+18:08
 */

public class ReadFile {
    public static void main(String[] args) {
        try (
                FileReader reader = new FileReader("src/day04/homework/pw.txt");
                FileWriter writer = new FileWriter("src/day04/homework/pw.txt", true)
        ) {
            char[] data = new char[5];
            int len = -1;
            StringBuilder builder = new StringBuilder();
            while ((len = reader.read(data)) != -1) {
                String str = new String(data,0,len);
                builder.append(str.replace("\n","").replace("\r",""));
            }
            writer.write(builder.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2 日期计算练习

程序启动后,要求用户在控制台输入自己的生日,格式为:yyyy-MM-dd。然后经过程序计算,输出:

1、用户到今天为止一共活了多少天

2、输出其出生10000天的纪念日,格式为yyyy-MM-dd

提示:请基于Java 8提供的新日期时间API实现

程序运行效果如下所示:

练习3

/**
 * @document:日期计算
 * @Author:SmallG
 * @CreateTime:2023/8/4+18:10
 */

public class Birthday {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入您的生日:");
        String birthday = scanner.next();
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate now = LocalDate.now();
        LocalDate birth = LocalDate.parse(birthday, dtf);
        //相减
        long days = birth.until(now, ChronoUnit.DAYS);
        System.out.println("恭喜您,一共活了" + days + "天!请继续保持!");

        LocalDate res = birth.plus(10000, ChronoUnit.DAYS);
        System.out.println("您出生10000天的纪念日为:" + res);
    }
}
最后修改:2023 年 08 月 14 日
如果觉得我的文章对你有用,请随意赞赏