1. 程式人生 > >Java當中的IO流-時間api(下)-上

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 點贊