第55节:Java当中的IO流-时间api(下)-上

标题图

Java当中的IO流(下)-上

日期和时间

日期类:java.util.Date

系统时间:

long time = System.currentTimeMillis();
public class DateDemo {
 public static void main(String[] args){

  long time = System.currentTimeMillis();
  System.out.println(time);

 }
}

currentTimeMillis

public static long currentTimeMillis()

currentTimeMillis是用来返回当前时间的,单位以毫秒,其值的粒度取决于底层操作系统.它是与在1970年1月1日UTC之间的当前时间和午夜之间的差异.

UTC世界时

阅读api,类Date

java.lang.Object
-> java.util.Date

实现的接口:

Serializable, Cloneable, Comparable<Data>

从以下版本开始 JDK1.0

public class Date extends Object
implements Serializable, Cloneable, Comparable<Data>

Date有两个附加功能,可以将日期解释为年,月,日,小时,分钟和第二个值,允许格式化和解析日期字符串。但是,从JDK 1.1开始, 要用Calendar类实现在日期和时间字段之间进行转换,并且使用DateFormat类应用于格式化和解析日期字符串, Date中的相应的方法被弃用。

Calendar
DateFormat

一天 = 24 * 60 * 60 = 86400

年,月,日期,小时,分钟,秒值

年份从整数 y - 1900 表示。 月份从 0到11 的整数表示。 0是1月,1是2月,等等; 日期从 1到31 的整数表示。

小时由0到23的整数表示。 分钟由0到59的整数表示。 一般以0到59的整数表示。 秒针由0到61的整数表示。

注意

Date构造方法:

Date()
用来分配Date对象,并且进行初始化对象,时间测量到最近的毫秒

Date(long, date)
用来分配Date对象,并且进行初始化对象,时间为标准基准时间以后指定毫秒数

使用Date,创建日期对象,封装对象,进行解析毫秒值

import java.text.DateFormat;
import java.util.Date;

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

        long time = System.currentTimeMillis();
        System.out.println(time);

        Date date = new Date(time);
        System.out.println(date.toString());

    }
}

toString()为将 Date对象转换为 String的形式 dow mon dd hh:mm:ss zzz yyyy

注意

日期格式化 DateFormat

DateFormat是日期和时间格式化子类的抽象类,常用SimpleDateFormat,格式化为日期到文本,解析为文本到日期,并且此类提供了很多类方法,(静态方法)

格式化分很多风格分别为,FULL,LONG,MEDIUM和SHORT.

java.text
类 DateFormat

java.lang.Object
-> java.text.Format
-> java.text.DateFormat

public abstract class DateFormat extends Format

DateFormat提供了很多类方法,不需要子类,只需要它提供的很多类方法,就可以进行格式化风格,DateFormat为日期格式化对象,可以通过类方法得到日期格式器.

myString = DateFormat.getDateInstance().format(myDate);

DateFormat.format(Date date) DateFormat.getDateInstance().format(myDate); 风格化:FULL、LONG、MEDIUM(默认风格)和 SHORT

long time = System.currentTimeMillis();
Date date = new Date(time);

DateFormat dateFormat = DateFormat.getDateInstance();
String myString = dateFormat.format(date);

System.out.println(myString);

风格化:

DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.FULL);
DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.FULL);
dateFormat = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL);

Class DateFormat

注意

Demo案例:

import java.text.DateFormat;
import java.util.Date;

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

        long time = System.currentTimeMillis();
        Date date = new Date(time);
        System.out.println(date.toString());

        DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.FULL);
        dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
        String mydate = dateFormat.format(date);
        System.out.println(mydate);
    }
}

IO流

Input  Output

IO流是用来处理设备之间的数据传输,在Java中数据的传输是通过流的方式进行操作的,在Java中提供了java.io包用于操作流的对象.

File

File类是将文件或者文件夹进行封装成对象的,为了方便对文件或者文件夹进行操作.

什么是递归呢?

递归就是自己调用自己,就是可以把某功能重复使用.

输入流为读,输出流为写

要输入,进行读入 要输出,进行写出

流可以分字节流和字符流哦~

字节流的抽象类:

InputStream ,OutputStream

子类FileInputStream
子类FileOutputStream

字符流的抽象列:

Reader , Writer

子类FileReader
子类FileWriter

IO流的操作,导入IO包,进行IO异常处理,对流进行关闭

字符流FileWriter 操作:

我们要进行创建流对象,就是建立数据存放的文件

FileWriter fw = new FileWriter("dashu.txt");

然后进行写入的方法,一定要用write()方法,将数据写入:

fw.write("简书作者: 达叔小生");

最后一定不要忘记,关闭流资源哦~

fw.close()

这样就可以在文本中写入数据了,字符流创建文件.

字符流FileReader 操作:

首先我们要指定文件数据读取的对象,建立一个流对象:

FileReader fr = new FileReader("dashucoding.txt");

然后创建一个临时存放的数据的数组对象:

// 因为是字符

char[] ch = new char[1024];

然后进行读取方法,要用到read()方法,将流中的数据进行读取到数组中:

fr.read(ch);

最后一定不要忘记,关闭流资源哦~

fr.close()

FileReader 读取:

FileReader fr = new FileReader("dashucoding.txt");

char[] ch = new char[1024];
int len = 0;
while((len=fr.read(ch)) != -1){
 System.out.println(new String(ch,0,len));
}

高效率-字符流缓冲区的帮助

有了缓冲区可以对数据的读和写的效率大大提高了.

BufferedWriter
BufferedReader
BfferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

转换流- InputStreamReader,OutputStreamWriter

转换流是字符流和字节流之间转换的桥梁,方便了字符流和字节流之间的操作 转换流的应用场景为当字节流中的数据都是字符时,可以转成字符流进行操作,更加方便快捷.

字符流体系

字符流

(Reader, Writer)
(Reader -> BufferedReader, InputStreamReader)
(Writer -> BufferedWriter, OutputStreamWriter )
FileReader, FileWriter

字节流体系

字节流

(InputStream, OutputStream)
(InputStream -> FileInputStream, FilterInputStream)
(OutputStream -> FilterOutputStream, FileOutputStream)
BufferedInputStream, BufferedOutputStream

抽象类Calendar

JDK1.1开始,使用Calendar类实现日期和时间字段之间的转换,然后使用DateFormat类来进行格式化和解析日期字符串.

java.util
类 Calendar

java.lang.Object
-> java.util.Calendar

public abstract class Calendar extends Object
implements Serializable, Cloneable, Comparable<Calendar>

Calendar提供了一些字段:

YEAR, MONTH, DAY_OF_MONTH, HOUR

Calendar.YEAR
Calendar.MONTH
Calendar.DAY_OF_MONTH
Calendar.HOUR

操作字段:set(),add()和roll(),使用这些方法可以更改日历字段,获取和设置日历字段值,可以调用set()方法,可以使用get,getTimeInMillis,getTime,add和roll进行调用.

Calendar提供了一个类方法getInstance:

Calendar rightNow = Calendar.getInstance();

// 获取日历对象

JDK1.1开始就使用这类,不使用Date类了,Calendar 案例:

import java.util.Calendar;

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

        Calendar c = Calendar.getInstance();
        // System.out.println(c);
        // 获取年
        System.out.println(c.get(Calendar.YEAR));
    }
}

搞定年月日

import java.util.Calendar;

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

        Calendar c = Calendar.getInstance();
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH)+1;
        int day = c.get(Calendar.DAY_OF_MONTH);

        System.out.println(year+"年"+month+"月"+day+"日");
    }
}

搞定星期

import java.util.Calendar;

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

        Calendar c = Calendar.getInstance();
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH)+1;
        int day = c.get(Calendar.DAY_OF_MONTH);
        String week = getWeek(c.get(Calendar.DAY_OF_WEEK));

        System.out.println(year+"年"+month+"月"+day+"日"+week);
    }

    public static String getWeek(int i) {
        if(i<0 || i>7){
            throw new RuntimeException(i+"没有对应的星期");
        }
        String[] weeks = {"","星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
        return weeks[i];
    }
}

描述

文本和日期对象

// 从time转到date
Date date = new Date(time)

// 格式化 日期对象转换为日期字符串
DateFormat format = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);

// 文本字符串
String time = format.format(date);
// 日期对象转换为日期字符串

文本转换为日期对象,进行解析,即"2018-10-10"转日期对象 参数是字符串:"2018-10-10"转日期对象 日期对象 Date date 凡是字符串转换为其它,都是解析

public class DateTest {
    public static void main(String[] args) throws ParseException {

        String mydate = "2018-10-10";
        DateFormat dateFormat = DateFormat.getDateInstance();
        Date date = dateFormat.parse(mydate);
        System.out.println(date);
    }
}

这里不同日期风格的文本要对应不同的格式器

String mydate = "2018-10-10";
DateFormat dateFormat = DateFormat.getDateInstance();

String mydate = "2018年-10月-10日";
DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.LONG);

如果给出的文本超出提供的风格,那么可以自己定义,进行解析,在Java中知道了这种情况,类DateFormat的子类为SimpleDateFormat对象.

java.text
类 SimpleDateFormat

java.lang.Object
-> java.text.Format
-> java.text.DateFormat
-> java.text.SimpleDateFormat

public class SimpleDateFormat extends DateFormat 

文本可能给出"2018/10/10",使用SimpleDateFormat

public SimpleDateFormat(String pattern)
参数为:pattern
是用来描述日期和数据格式的模式

抛出:
NullPointerException为给定的模式为null
IllegalArgumentException为给定的模式无效

SimpleDateFormat自己定义相关模式:

mydate = "2018/10/10 15:14:13";

// 自定义
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");

// 解析
Date date = dateFormat.parse(mydate);

System.out.println(date);

Class SimpleDateFormat

SimpleDateFormat是一个具体的类,可以格式化,日期转文本,也可以解析,文本转日期和归一化.

描述

描述

练习获取天数

import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;

public class DateDemo {
    public static void main(String[] args) throws ParseException {

        /*
         * 思路:
         * 1,从2018-10-2到2018年10月8日有多少天?相减
         * 2,字符串不能相减,毫秒值可以相减。
         * 3,获取毫秒值  毫秒值 -> 日期对象, 日期对象 -> 毫秒值。
         * 4,获取日期对象  需要将 字符串文本 -> 解析 -> 日期对象。
         */

        // 两者相差多少天,给定日期模式
        String date1 = "2018-10-2";
        String date2 = "2018年10月8日";

        // 进行模式解析
        int style_1 = DateFormat.MEDIUM;
        int style_2 = DateFormat.LONG;

        // 定义方法, 获取天数 参数文本日期, 模式
        int days = getDays(date1,date2, style_1,style_2);

        // 获取天数
        System.out.println("days="+days);

    }

    private static int getDays(String date1, String date2,
            int style_1, int style_2) throws ParseException {

        // 进行模式
        DateFormat format_1 = DateFormat.getDateInstance(style_1);
        DateFormat format_2 = DateFormat.getDateInstance(style_2);

        // 进行模式解析, 日期对象 解析 -> 日期对象。
        Date date_1 = format_1.parse(date1);
        Date date_2 = format_2.parse(date2);

        // 获取毫秒数 日期对象 -> 毫秒值。
        long time_1 = date_1.getTime();
        long time_2 = date_2.getTime();

        long time = Math.abs(time_1 - time_2);
        int day = (int)(time/1000/60/60/24);

        return day;
    }
}

解决2月份的天数问题?

使用方法:

add(int field, int amount)
返回为abstract void 

为给定的日历字符安添加或者减去指定的时间量
import java.util.Calendar;

public class DateTest {
    public static void main(String[] args) {
            show(year);
    }

    public static void show(int year) {
        Calendar c = Calendar.getInstance();

        // 2+1 = 3;
        c.set(year, 2, 1);
        // 知道3月1日的前一天就是2月的最后一天,就知道2月份的天数。
        c.add(Calendar.DAY_OF_MONTH, -1);

        int year1 = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH) + 1;
        int day = c.get(Calendar.DAY_OF_MONTH);
        String week = getWeek(c.get(Calendar.DAY_OF_WEEK));

        System.out.println(year1 + "年" + month + "月" + day + "日  " + week);
        System.out.println(day+"天");
    }

    public static String getWeek(int i) {
        if (i < 0 || i > 7) {
            throw new RuntimeException(i + "没有对应的星期");
        }

        String[] weeks = { "", "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
        return weeks[i];
    }
}

打印流,基本类型数据流,流对象,RandomAccessFile

IO包中的打印流

PrintWriter与PrintStream可以用来操作输入流和文件

操作基本数据类型

DataInputStream与DataOutputStream
// 操作字节数组

ByteArrayInputStream与ByteArrayOutputStream
// 操作字符数据

CharArrayReader与CharArrayWriter
// 操作字符串

StringReader 与 StringWriter

操作对象

ObjectInputStream与ObjectOutputStream

RandomAccessFile

随机访问文件,自身具备读写的方法。

打印流

PrintStream 和 PrintWriter

FileOutputStream fos = new FileOutputStream("dashu.txt");
fos.write(Integer.toString(108).getBytes();
fos.close();
java.io
类 FilterOutputStream

java.lang.Object
-> java.io.OutputStream
-> java.io.FilterOutputStream

public class FilterOutputStream extends OutputStream

已知子类:
BufferedOutputStream
PrintStream

PrintStream

java.io
类 PrintStream

java.lang.Object
-> java.io.OutputStream
-> java.io.FilterOutputStream
-> java.io.PrintStream

public class PrintStream extends FilterOutputStream
implements Appendable, Closeable

方法

说明

PrintStream(File file)

用于创建指定文件且不带自动刷新的新打印流

PrintStream(File file, String csn)

用于创建指定文件名称和字符集且不带自动行刷新的新打印流

PrintStream(OutputStream out)

用于创建新的打印流

PrintStream(OutputStream out, boolean autoFlush)

用于创建新的打印流

PrintStream(OutputStream out, boolean autoFlush, String encoding)

用于创建新的打印流

PrintStream(String fileName)

用于创建指定文件名称且不带自动行刷新的新打印流

PrintStream(String fileName, String csn)

用于创建指定文件名称和字符集且不带自动行刷新的新打印流

文件字节输出流

FilterOutputStream,写东西到文件

FileOutputStream fos = new FileOutputStream("dashu.txt");
fos.write(Integer.toString(108).getBytes();
fos.close();

// 进行比较可以用PrintStream

FileOutputStream fos = new FileOutputStream("dashu.txt");

// 添加额外功能PrintStream
PrintStream ps = new PrintStream(fos);

// 如果用
// ps.write(97);
// 那么就会在 dashu.txt 该文件中显示一字节 为 a
// 使用 print() 方法

ps.print(97);
// 在 dashu.txt 文件中显示 为 97

ps.close();

点击源码 print() 方法:

public void print(int i){
 write(String.valueOf(i));
}

还可以升级 PrintStream :

PrintStream ps = new PrintStream("dashu.txt");
ps.print(97);
ps.close();

Class PrintStream

从以下版本开始: JDK1.0

描述

PrintWriter

键盘录入

BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

从以下版本开始: JDK1.1

java.lang Object
-> java.io.Writer
-> java.io.PrintWriter

public class PrintWriter extends Writer

描述

描述

PrintWriterDemo 案例:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;

public class PrintWriterDemo {
    public static void main(String[] args) throws IOException {

        BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter out = new PrintWriter(System.out,true);
        
        String line = null;
        while((line=bufr.readLine())!=null){
            if("over".equals(line)){
                break;
            }
            out.println(line.toUpperCase());
        }
        out.close();
    }
}

基本类型数据流

DataOutputStream
DataInputStream
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class DataStreamDemo {
    public static void main(String[] args) throws IOException {
        readData();
    }

    public static void readData() throws IOException {
        FileInputStream fis = new FileInputStream("dashu.txt");
        DataInputStream dis = new DataInputStream(fis);
        
        int num = dis.readInt();
        System.out.println("num="+num);
        dis.close();
        
    }

    public static void writeData() throws IOException {
        FileOutputStream fos = new FileOutputStream("dashucoding.txt");
        DataOutputStream dos = new DataOutputStream(fos);
        dos.writeInt(97);
        dos.close();
    }
}

描述

描述

操作数组和字符串的流对象

专门操作字节数组的流对象为 ByteArrayOutputStream

java.lang.Object
-> java.io.OutputStream
-> java..io.ByteArrayOutputStream
public class ByteArrayOutputStream
extends OutputStream

ByteArrayOutputStream 把数组直接封装起来,并提供流的读写方法来操作数组,此类实现了一个输出流,数据被写入到一个byte数组,获取数据的方法为 toByteArray()toString(). 其缓冲区会随着数据的增长而增加. 关闭 ByteArrayOutputStream 没有任何效果,所以不用关闭.

ByteArrayStreamDemo 案例:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

public class ByteArrayStreamDemo {
    public static void main(String[] args) {
        // 源
        ByteArrayInputStream bis = new ByteArrayInputStream("dashucoding".getBytes());
        
        // byte[] buff = "dashucoding".getBytes();
        // for(byte b : buff){
        //  bos.write(b);
        // }
        
        // 目的
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        
        int ch = 0;
        while((ch=bis.read())!=-1){
            bos.write(ch);
        }
        // 因为不用调用底层资源,所以不用关闭, 不会抛出IOException.
        System.out.println(bos.toString());
    }
}

描述

描述

IO流中的 RandomAccessFile

需求分析: 要对文件进行 读 或者 写 的操作

java.io
类 RandomAccessFile

java.lang.Object
-> java.io.RandomAccessFile

public class RandomAccessFile extends Object
implements DataOutput, DataInput, Closeable

RandomAccessFile 对文件进行随机访问, 进行 读 和 写.(随机访问,操作文件,封装了读取和写入的流, 字节输入流和字节输出流, 提供了文件指针)

描述

IO包中工具类对象 RandomAccessFile 案例:

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

public class RandomAccessFileDemo {
    public static void main(String[] args) throws IOException {

         // 内部是用byte数组进行存储数据
         // 提供了一个对数组操作的文件指针
         // 通过 getFilePointer 方法读取,并通过 seek 方法设置
         //  writeFile();
        readFile();
    }

    public static void readFile() throws IOException {
        // r 为都
        RandomAccessFile raf = new RandomAccessFile("dashu.txt", "r");
        // 改变指针的位置,想读谁就读谁
        raf.seek(8*3);
        
        byte[] buff = new byte[4];
        raf.read(buff);
        String name = new String(buff);
        System.out.println("name="+name);
        
        int age = raf.readInt();
        System.out.println("age="+age);
        
        raf.close();
    }

    public static void writeFile() throws IOException {
        // rw 为进行读写操作
        RandomAccessFile raf = new RandomAccessFile("dashu.txt", "rw");
        
        // 存储 姓名 和 年龄。
        // raf.write("张三".getBytes());
        // raf.writeInt(27);
        // raf.write("李四".getBytes());
        // raf.writeInt(38);
        // 通过seek()方法进行在哪里写入
        raf.seek(4);
        
        raf.write("简书作者: 达叔小生".getBytes());
        raf.writeInt(12);

        // 文件指针可以通过读取getFilePointer方法和由设置seek方法
        System.out.println(raf.getFilePointer());
        raf.close();
    }
}

RandomAccessFile 中是通过数组进行存储的,RandomAccessFile 不会进行覆盖,如果之前保留了数据,然后会在文件中继续保留,当导入的数据与之前的数据都在同一位置,则数据会进行覆盖.

往后余生,唯独有你 简书作者:达叔小生 90后帅气小伙,良好的开发习惯;独立思考的能力;主动并且善于沟通 简书博客: https://www.jianshu.com/u/c785ece603d1

结语

  • 下面我将继续对 其他知识 深入讲解 ,有兴趣可以继续关注
  • 小礼物走一走 or 点赞

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券