【JavaSE筆記】IO(三)IO流_字節流

本期知識點:
IO流
字節流

IO流

1.IO流

設備和設備之間的傳輸(讀和寫)

2.分類

a.按流向分爲:

輸入流---讀取數據
輸出流---寫出數據

b.按數據類型分爲:

字節流:
字節輸入流:InputStream
字節輸出流:OutputStream
字符流:
字符輸入流:Reader
字符輸出流:Writer
注意:
a:如果我們沒有明確說明按照什麼分,默認按照數據類型分。
b:除非文件用windows自帶的記事本打開我們能夠讀懂,才採用字符流,否則建議使用字節流。

字節流

1.FileOutputStream寫出數據

a.字節輸出流對象中的寫數據的方法:

public void write(int b):寫入一個字節
public void write(byte[] b):寫一個字節數組

public void write(byte[] b, int index,int len):寫一部分字節數組(常用)

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class 寫數據的方法 {
	public static void main(String[] args) throws IOException {
		//創建文件字節輸出對象
		FileOutputStream fos = new FileOutputStream("fos.txt");
//		public void write(int b):寫入一個字節
		fos.write(97);
		//打開記事本 看到寫入了 97ASCII碼對應的字符 
//		public void write(byte[] b):寫一個字節數組
		byte []a = {97,98,99,100,101};
		fos.write(a);
		//打開記事本 看到寫入了 ASCII碼對應的字符  bcdef
//		public void write(byte[] b, int index,int len):寫一部分字節數組(常用)
		fos.write(a, 2, 3);
		//cde
		fos.close();
	}
}

b.操作步驟:

i.創建字節輸出流對象
FileOutputStream裏面的具體的構造方法:
public FileOutputStream(File file)指定一個File對象
public FileOutputStream(String name) 直接指定文件名稱
ii.調用write()方法寫數據
iii.釋放資源close()

c.相關的問題?

i.創建字節輸出流對象做了幾件事情?
1)調用系統功能區創建FileOutputStream對象

2)將fos對象指向fos.txt文件


ii.爲什麼要close()?

iii.如何實現數據的換行?
現了一個給文件中寫入了一個數據,並且沒有換行,那是因爲我們沒有給for循環中增加一個換行符號:針對不同的操作系統換行符號是不一樣的:
windows:\r\n
Linux:\n

Mac:\r


iv.如何實現數據的追加寫入?
構造方法:
public FileOutputStream(File file, boolean append)

如果第二個參數爲 true,則將字節寫入文件末尾處,而不是寫入文件開始處

public class FileOutputStreamDemo3 {
	public static void main(String[] args) throws IOException {
		//創建文件字節輸出流對象
//		FileOutputStream fos = new FileOutputStream("fos3.txt") ;
		FileOutputStream fos = new FileOutputStream("fos3.txt", true) ;
		
		//寫數據
		for(int x = 0 ; x <10 ; x ++){
			fos.write(("hello"+x).getBytes());
			//需要寫一個換行符號
			fos.write("\r\n".getBytes());
		}
		
		//釋放資源
		fos.close();
	}
}

d.文件字節輸出流中加入異常處理(try...catch方式)

i.1.0分開處理

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 
 * 文件字節輸出流中加入異常處理(try...catch方式)
 * */
public class 異常處理1 {
	public static void main(String[] args) {
		//分開處理
		
		FileOutputStream fos = null ;
		
		try {
			//創建文件字節輸出流對象
			fos = new FileOutputStream("fos4.txt") ;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		
		//寫數據
		try {
			fos.write("java".getBytes());
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		//關閉資源
		try {
			fos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}


ii.2.0一起處理

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class 異常處理2 {
	public static void main(String[] args) {
//		方式2:一起處理
		try {
			FileOutputStream fos1 = new FileOutputStream("fos4.txt") ;
			//寫數據
			fos1.write("java".getBytes());
			//釋放資源
			fos1.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}


iii.3.0 最終版本

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class 異常處理3 {
	public static void main(String[] args) {
		FileOutputStream fos  = null ;
		try {
			fos = new FileOutputStream("fos4.txt") ;
			//寫數據
			fos.write("java".getBytes());
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			//關閉資源,但是資源之前,首先判斷資源對象是否爲空
			if(fos !=null){
				//開始關閉資源
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				} 
			}
		}
	}
}


2.FileInputStream讀取數據

a.操作步驟:

i.創建字節輸入流對象
ii.調用read()方法
iii.釋放資源

b.字節輸入流對象中的讀數據的方法:

public int read():一次讀取一個字節
public int read(byte[] b):一次讀取一個字節數組

i.

import java.io.FileInputStream;
import java.io.IOException;

public class 讀取Demo01 {
	public static void main(String[] args) throws IOException {
		//創建字節輸入流對象
		FileInputStream fis = new FileInputStream("讀取Demo.txt") ;
		
		//public int read(byte[] b):一次讀取一個字節數組
		//定義數組
		byte[] bys = new byte[5] ;
		//第一次讀取
		int len = fis.read(bys) ;
		System.out.println(len);
		System.out.println(new String(bys));
		System.out.println(new String(bys,0,len));
		
		//第二次讀取
		len = fis.read(bys) ;
		System.out.println(len);
		System.out.println(new String(bys));
		System.out.println(new String(bys,0,len));
		
		//第三次讀取
		len = fis.read(bys) ;
		System.out.println(len);
		System.out.println(new String(bys));
		System.out.println(new String(bys,0,len));
		
		//第四次
		len = fis.read(bys) ;
		System.out.println(len);
		System.out.println(new String(bys));
		System.out.println(new String(bys,0,len));
		

	}
}	

ii.
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class 讀取Demo02 {
	public static void main(String[] args) throws IOException {
		//創建字節輸入流對象
		FileInputStream fis = new FileInputStream("讀取Demo.txt") ;
		/*
		跟一次讀取一個字節是一樣的,讀到末尾返回-1
		這作爲他的一個結束條件
		*/
//		定義字節數組
		byte[] bys = new byte[115] ; //自己定義的長度
		int len = 0 ;
//		一次讀取一個字節數組,然後賦值,判斷
		while((len = fis.read(bys))!=-1){
//			System.out.println(new String(bys));
			//輸出的話:不能直接輸出(new String(bys)
			//正確的輸出:new String(bys,0,len)
			System.out.println(new String(bys,0,len));
		}
	}
}

iii.終極版本!!!
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class 讀取Demo03 {
	public static void main(String[] args) throws IOException {
		//創建字節輸入流對象
		FileInputStream fis = new FileInputStream("讀取Demo.txt") ;
		//讀取數據:給定字節數組的長度是1024或者1024的倍數
		//最終版代碼
		byte[] bys = new byte[1024] ;
		//定義長度
		int len = 0;
		while((len=fis.read(bys)) !=-1){
			System.out.println(new String(bys,0,len));
		}
	}
}

3.字節流的複製

需求:在當前項目有一個a.txt文件,然後我要將a.txt文件的內容複製到當前文件下的b.txt文件
分析:
源文件:當前項目下的a.txt--->讀數據--->FileInputStream
目的文件:當前項目下的b.txt文件--->寫數據--->FileOutputStream
代碼:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyDemo1 {
	public static void main(String[] args) throws IOException {
		//封裝源文件
		FileInputStream fi = new FileInputStream("src\\IO\\a.txt");
		//封裝目標文件
		FileOutputStream fo = new FileOutputStream("src\\IO\\b.txt");
		//一次讀取一個字節
		int x = 0;
		while((x=fi.read())!=-1){
			//每次讀一個字節,就寫一個字節。
			fo.write(x);
		}
		//釋放資源
		fi.close();
		fo.close();
	}
}
問題:在實際操作中我們發現使用FileInputStream一次讀取一個字節,會出現中文亂碼,現在卻沒有,爲什麼?
解答:在以前寫法中存在強制類型轉換,把字節轉換成了字符,而一個字符對應2個字節,出現中文亂碼;在新的寫法中每次都一個字節,寫一個字節,並沒有強制類型轉換,不會有亂碼。

4.關於漢字

計算機計算機是何如識別中文這樣的字符的?
一箇中文對應兩個字節。
兩個兩個進行拼接在一塊
第一個字節:確定是否是負數
第二個字節:可以是負數,也可以是整數,對實際是沒有影響的
import java.util.Arrays;

public class 關於漢字 {
	public static void main(String[] args) {
		String s = "abcde";
		byte[] a = s.getBytes();
		System.out.println(Arrays.toString(a));//[97, 98, 99, 100, 101]
		
		String ss = "是你就好";
		byte[] b = ss.getBytes();
		System.out.println(Arrays.toString(b));//[-54, -57, -60, -29, -66, -51, -70, -61]
	}
} 


字節緩存流

1.概述

字節流一次讀寫一個數組的速度明顯比一次讀寫一個字節的速度快很多,這是加入了數組這樣的緩衝區效果,java本身在設計的時候,也考慮到了這樣的設計思想(裝飾設計模式後面講解),所以提供了字節緩衝區流

2.緩存流(高效流)

BufferedInputStream
BufferedOutputStream

3.BufferOutputStream的構造方法

public BufferedOutputStream(OutputStream out):推薦使用第一種
public BufferedOutputStream(OutputStream out, int size):指定一個緩衝區大小(第二種構造方法不常用,因爲第一種構造方法默認的緩衝區大小足夠存儲數據!)

4.問題:

字節緩衝輸出流中爲什麼不直接將文件的路徑或者文件夾的路徑作爲參數,爲什麼是OutputSteram?

緩衝流只是爲了高效而設計的,只是構建了一個緩衝區,要進行讀寫操作還需要使用基本的流對象

OutputStream是抽象類,不能直接實例化
BufferOutputStream(new FileOutputStream("路徑抽象表現形式"))
屬於java的一種設計模式:裝飾者設計模式

5.讀取數據

在字節緩衝輸入流中,在同一個對象中,讀取數據只能是一種方式,不能同時使用。
a.一次讀取一個字節

b.一次讀取一個字節數組

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;

/*
在字節緩衝輸入流中,在同一個對象中:讀數據只能是一種方式:要麼一次讀取一個字節,要麼就是一次讀取一個字節數組
不要同時使用
*/
public class BufferedInputStream類 {
	public static void main(String[] args) throws IOException {
		//創建字節緩衝輸入流對象
		//public BufferedInputStream(InputStream in)
		BufferedInputStream bi = new BufferedInputStream
				(new FileInputStream("BufferedInputStream類.txt"));
		//讀取數據:一次讀取一個字節
		int x = 0;
		while((x=bi.read())!=-1){
			System.out.print((char)x);
		}
		bi.close();
	}
}
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class BufferedOutputStream類 {
	public static void main(String[] args) throws IOException {
		//public BufferedOutputStream(OutputStream out):推薦使用第一種
		BufferedOutputStream bos = new BufferedOutputStream
				(new FileOutputStream("box.txt")) ;
		//寫數據
		bos.write("hello".getBytes());
		
		//釋放資源
		bos.close();
	}
}

6.效率問的比較

需求:把桌面的一個視頻複製到當前項目下
代碼:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/*
基本的字節輸入流一次讀取一個字節:
基本的字節輸入流一次讀取一個字節數組:
高效流的字節緩衝輸入流一次讀取一個字節:
高效流的字節緩衝輸入流一次讀取一個字節數組: 
*/

public class 對比 {
	public static void main(String[] args) throws IOException  {
//		基本的字節輸入流一次讀取一個字節:
		
		long star = System.currentTimeMillis();
		
//		fun1("C:\\Users\\Administrator\\Desktop\\AAA.mp4","bbb.mp4");//耗時:79183毫秒
//		fun2("C:\\Users\\Administrator\\Desktop\\AAA.mp4","bbb.mp4");//耗時:116毫秒
//		fun3("C:\\Users\\Administrator\\Desktop\\AAA.mp4","bbb.mp4");//耗時:676毫秒
//		fun4("C:\\Users\\Administrator\\Desktop\\AAA.mp4","bbb.mp4");//耗時:44毫秒
		
		long end = System.currentTimeMillis();
		System.out.println("耗時:"+(end-star)+"毫秒");
	}
	
	public static void fun4(String star, String end) throws IOException {
		System.out.println("高效流的字節緩衝輸入流一次讀取一個字節數組: ");	
		BufferedInputStream bi = new BufferedInputStream(new FileInputStream(star));
		BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream(end));
		byte[] a = new byte[1024];
		int len = 0;
		while((len=bi.read(a))!=-1){
			bo.write(a, 0, len);
		}
		bi.close();
		bo.close();
	}
	
	public static void fun3(String star, String end) throws IOException {
		System.out.println("高效流的字節緩衝輸入流一次讀取一個字節:");	
		BufferedInputStream bi = new BufferedInputStream(new FileInputStream(star));
		BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream(end));
		int x =0 ;
		while((x=bi.read())!=-1){
			bo.write(x);
		}
		bi.close();
		bo.close();
	}
	
	public static void fun2(String star, String end) throws IOException {
		System.out.println("基本的字節輸入流一次讀取一個字節數組:");	
		FileInputStream fi = new FileInputStream(star);
		FileOutputStream fo = new FileOutputStream(end);
		byte []x=new byte[1024];
		int len =0;
		while((len=fi.read(x))!=-1){
			fo.write(x, 0, len);
		}
		fi.close();
		fo.close();
	}

	public static void fun1(String star,String end) throws IOException{
		System.out.println("基本的字節輸入流一次讀取一個字節:");
		FileInputStream fi = new FileInputStream(star);
		FileOutputStream fo = new FileOutputStream(end);
		int x = 0;
		while((x=fi.read())!=-1){
			fo.write(x);
		}
		fi.close();
		fo.close();
	}
}


結論:
基本的字節輸入流一次讀取一個字節:耗時:79183毫秒
基本的字節輸入流一次讀取一個字節數組:耗時:116毫秒
高效流的字節緩衝輸入流一次讀取一個字節:耗時:676毫秒
高效流的字節緩衝輸入流一次讀取一個字節數組:耗時:44毫秒
發佈了51 篇原創文章 · 獲贊 15 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章