Java的I/O框架——字節流

字節流分類總覽

  • 字節流的方向分類
    • InputStream 抽象輸入類
    • OutputStream() 抽象輸出類
  • 字節節點流
    • FileInputStream
    • FileOutputStream
  • 字節過濾流
    • BufferedOutputStream
    • BufferedInputStream
    • 提供了IO效率,減少訪問磁盤的次數。數據存放在緩衝區中。flush()刷新緩衝區,提交數據
  • 序列化和反序列化
  • 對象流
    • ObjectInputStream
    • ObjectOutputStream
    • 增強讀寫8中基本數據類型和字符串功能
    • 讀寫對象,可以實現對象的持久化存儲

字節流的分類

字節流分爲兩大類

輸入字節流
  • InputStream 抽象輸入類 是輸入類字頂級抽象類
    在這裏插入圖片描述
    以上是JDK1.8文檔提供的該抽象類的方法
    其中常用的有以下幾種
void close() 
關閉此輸入流並釋放與流關聯的任何系統資源。  
abstract int read() 
從輸入流讀取下一個數據字節。  
int read(byte[] b) 
讀取一定數量的字節從輸入流並存入緩衝區陣列 b。  
int read(byte[] b, int off, int len) (不常用但是要知道) 
讀到 len字節從輸入流讀入字節數組數據。  
輸出字節流
- OutputStream()	抽象輸出類 是輸出類頂級抽象類

在這裏插入圖片描述
以上是JDK1.8文檔提供的該抽象類的方法基本都是常用的除了write(byte[] b, int off, int len)

字節節點流

FileInputStream輸入字節節點流
  • 是InputStream子類
  • 構造函數如下
public FileInputStream(String name)
                throws FileNotFoundException 
                // 系統相關的文件名稱
public FileInputStream(File file)
                throws FileNotFoundException
				// file代表傳遞一個File對象指向打開連接的地址
public FileInputStream(FileDescriptor fdObj)
				//通過使用文件描述符 fdObj創建一個 FileInputStream,它代表一個現有連接到文件系統中的一個實際的文件。 
  • 具有的方法
    在這裏插入圖片描述
  • 使用實例代碼
public class Test{
	public static void main(String[] args) throws Exception{
		InputStream is = new FileInputStream("資源路徑");//如果找不到會拋出異常
		//讀取方式一: 
		//int n = is.read(); 一次讀一個
		//讀取方式二:
		byte[] bytes = new byte[1024];
		int n;
		while((n  = is.read(bytes))!=-1){
			for(int i = 0; i < n; i++){
				System.out.print((char)bytes[i]);
			}
		}
		is.close();
	}
	
}
FileOutputStream輸出字節節點流
  • 是OutputStream子類
  • 構造函數如下
FileOutputStream(File file) 
創建一個文件輸出流寫入指定的 File對象表示的文件。  
FileOutputStream(File file, boolean append) 
創建一個文件輸出流寫入指定的 File對象表示的文件。  
FileOutputStream(FileDescriptor fdObj) 
創建一個文件輸出流,寫入指定的文件描述符,它表示在文件系統中的實際文件的現有連接。  
FileOutputStream(String name) 
創建一個文件輸出流,用指定的名稱寫入文件。  
FileOutputStream(String name, boolean append) 
創建一個文件輸出流,用指定的名稱寫入文件。  

  • 具體的方法

在這裏插入圖片描述

  • 示例
public class Test{
	public static void main(String[] args) throws IOException{
		// 方式一
		// String file = "./src/txt/target.txt";
		// 方式二
		File file = new File("./src/txt/target.txt");
		OutputStream ios = new FileOutputStream(file);  
		// 每次寫入
		ios.write('3');
		byte[] bytes = new byte[] {'1','2','3','4','5','6','7','8','9',65,66};
		ios.write(bytes);
		ios.close();
	}
}
FileInputStream 與FileOutputStream綜合案例
  • 模仿上傳文件也就是先讀後寫
public class TestFileIO {
	public static void main(String[] args) throws IOException {
		// 將指定圖片,上傳一份項目裏來
		// 文件是再存儲設備中 -> 讀到程序中來-->寫入到存儲設備中
		FileInputStream fis = new FileInputStream("1.png");
		FileOutputStream fos = new FileOutputStream("./src/txt/1.png");
		int n;
		while((n = fis.read())!=-1) {
				fos.write(n);
		}
		System.out.println("讀取結束");
		fis.close();
		fos.close();
	}
}

字節過濾流

  • 提供了IO效率,減少訪問磁盤的次數。數據存放在緩衝區中。flush()刷新緩衝區,提交數據
  • 是一個增強節點流,需要節點流
BufferedInputStream
  • 構造方法
    在這裏插入圖片描述
  • 自帶和繼承的方法
  • 是InputStream孫子類
  • 父類是FilterInputStream
int available() 
返回一個可以從這個輸入流讀取(或跳過)的字節數的估計值,而不阻塞該輸入流的下一個方法的調用。  
void close() 
關閉此輸入流並釋放與流關聯的任何系統資源。  
void mark(int readlimit) 
看到的 InputStream的 mark方法一般合同。  
boolean markSupported() 
如果輸入流的支持 mark和 reset方法。  
int read() 
看到的 InputStream的 read方法一般合同。  
int read(byte[] b, int off, int len) 
從這個字節的輸入流讀取到指定的字節數組中的字節,從給定的偏移量開始。  
void reset() 
看到的 InputStream的 reset方法一般合同。  
long skip(long n) 
看到的 InputStream的 skip方法一般合同。  
  • 示例
public class TestBufferedInputStream{
	public static void main(String[] args){
// 有參構造需要一個字節輸出節點流
		// 先創建字節輸出節點流
		FileInputStream fis = new FileInputStream("./src/txt/target.txt");
		// 增強節點流
		BufferedInputStream bis = new BufferedInputStream(fis);
		byte[] bytes = new byte[1024];
		int n;
		while((n = bis.read(bytes))!=-1) {
			for (int i = 0; i < n; i++) {
				System.out.print((char)bytes[i]);
			}
		}
		// -----------------------------------------
	}
}

BufferedOutputStream
  • 構造方法

`在這裏插入圖片描述

  • 方法
void flush() 
刷新緩衝輸出流。  
void write(byte[] b, int off, int len) 
寫 len字節指定字節數組中的起始偏移 off這個緩衝輸出流。  
void write(int b)  
public class TestBufferedOutputStream {
	public static void main(String[] args) throws IOException {
		// 1.先構建節點流
		FileOutputStream fos = new FileOutputStream("./src/txt/target.txt");
		// 2.增強節點流,將節點流對象當參數傳入
		BufferedOutputStream bos = new BufferedOutputStream(fos);
		//------------------寫到緩衝區並提交
		bos.write('a');
		bos.write('c');
		bos.write('a');
		byte[] bytes = new byte[]{1,2,3,4,5,6,7,8,9};
		bos.write(bytes);
		bos.flush();//將數據一次性從緩衝區刷入到文件
		bos.close();// 關閉流並把緩衝區存在的數據一次性寫入到文件裏,級聯執行flush()
	}
}
  • 綜合案例

public class TestInputStream {
	public static void main(String[] args) throws IOException, ClassNotFoundException{
		String file = "./src/txt/target.txt";
		bufferedInput(file);
		bufferedOutput(file);
		bufferedInput(file);
	}
	private  static void bufferedInput(String file) throws IOException {
		FileInputStream fileInputStream = new FileInputStream(file);
		BufferedInputStream bis = new BufferedInputStream(fileInputStream);
		// 緩衝流
		byte[] bytes = new byte[1024];
		int n;
		while ((n = bis.read(bytes))!=-1) {
			for (int i = 0; i < n; i++) {
				System.out.print((char)bytes[i]);
			}
		}
		bis.close();
		fileInputStream.close();
	}
	private  static void bufferedOutput(String file) throws IOException {
		FileOutputStream fileInputStream = new FileOutputStream(file);
		BufferedOutputStream bis = new BufferedOutputStream(fileInputStream);
		// 緩衝流
		byte[] bytes = new byte[] {'a','c','d','1','2','3','4'};
		int n;
		bis.write(bytes);
		bis.close();
		fileInputStream.close();
	}
}

序列化和反序列化

序列化需要實現幾個必備條件:

  • 必須實現接口Serializable
  • 必須保證所有屬性均支持序列化
  • Transient修飾的爲臨時屬性,不參與序列化
  • 讀取到文件末尾時:java.IO.EOFException
class Student implements Serializable{
	String name;
	transient Integer age;
	String sex;
	Double score;
	// 數組:基本數據類型可以序列化
	// 引用數據類型的數組,數組類型要支持序列化
	// static 會影響序列化
	public Student(String name, Integer age, String sex, Double score) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
		this.score = score;
	}
	@Override
	public  String toString() {
		return "Student [name=" + name + ", age=" + age + ", sex=" + sex + ", score=" + score + " ]";
	}
	//public native int add();
}

對象流

  • 增強讀寫8中基本數據類型和字符串功能
  • 讀寫對象,可以實現對象的持久化存儲
  • 雖然可以跟以上BufferedInputStream/BufferedOutputStream一樣用同樣的功能而且增強了讀寫8種基本數據類型和字符串功能但常用的還是讀寫對象,對對象實現持久化存儲
  • 父類是InputStream
ObjectInputStream
  • 構造方法

在這裏插入圖片描述

  • 普通方法
int available() 
返回可以不阻塞讀取的字節數。  
void close() 
關閉輸入流。  
void defaultReadObject() 
從該流中讀取當前類的非靜態和非瞬態字段。  
protected boolean enableResolveObject(boolean enable) 
使流能夠允許從流中讀取的對象被替換。  
int read() 
讀取一個字節的數據。  
int read(byte[] buf, int off, int len) 
讀入一個字節數組。  
boolean readBoolean() 
在布爾值中讀取。  
byte readByte() 
讀取一個8位字節。  
char readChar() 
讀取一個16位字符。  
protected ObjectStreamClass readClassDescriptor() 
從序列化流中讀取類描述符。  
double readDouble() 
讀一個64位的雙。  
ObjectInputStream.GetField readFields() 
從流中讀取持久字段,並使它們可用名稱命名。  
float readFloat() 
讀取一個32位浮點。  
void readFully(byte[] buf) 
讀取字節,阻塞,直到所有的字節都讀。  
void readFully(byte[] buf, int off, int len) 
讀取字節,阻塞,直到所有的字節都讀。  
int readInt() 
讀取一個32int。  
String readLine() 
過時的。  
此方法沒有正確地將字節轉換爲字符。詳見和替代輸入流。  
long readLong() 
讀一個64位長的。  
Object readObject() 
從對象輸入流對象。  
protected Object readObjectOverride() 
這種方法被稱爲對象,通過構建保護對象使用無參數構造函數受信任的子類。  
short readShort() 
讀一個16位的短。  
protected void readStreamHeader() 
的readstreamheader方法是提供讓子類來讀取和驗證自己的流頭。  
Object readUnshared() 
讀取對象輸入流“獨享”的對象。  
int readUnsignedByte() 
讀取一個無符號的8位字節。  
int readUnsignedShort() 
讀取一個無符號的16位短。  
String readUTF() 
讀 modified UTF-8格式字符串。  
void registerValidation(ObjectInputValidation obj, int prio) 
在返回圖形之前註冊一個要驗證的對象。  
protected<?> resolveClass(ObjectStreamClass desc) 
加載指定的流類描述的本地類等價。  
protected Object resolveObject(Object obj) 
這種方法將允許受信任的子類對象輸入流用另一個來代替在反序列化期間。  
protected<?> resolveProxyClass(String[] interfaces) 
返回實現代理類描述符中命名的接口的代理類;子類可以實現此方法從流中讀取自定義數據以及動態代理類的描述符,從而允許它們使用接口和代理類的替代加載機制。  
int skipBytes(int len) 
跳過的字節。  

  • 這個對象流的方法就有很多了尤其是其對八種基本類型和字符串增強的方法
ObjectOutputStream
  • 構造方法

  • 普通方法

ObjectOutputStream和ObjectInputStream使用示例
  • 示例一:
public class TestObjectStream {
	public static void main(String[] args) throws IOException, ClassNotFoundException{
		OutputStream os = new FileOutputStream("./src/txt/target.txt");
		ObjectOutputStream oos = new ObjectOutputStream(os);
		//oos.writeInt(30);
		//oos.writeDouble(3.5);
		//oos.writeBoolean(true);
		//oos.flush();
		//______________________________--
		InputStream is = new FileInputStream("./src/txt/target.txt");
		ObjectInputStream ois = new ObjectInputStream(is);
		
		//int  result = ois.readInt();
		//System.out.println(result);
		
		Student stu = new Student("李敢敢",23,"男",150D);
		Student stu1 = new Student("趙巖巖",22,"女",150D);
		Student stu2 = new Student("李某人",10,"未知",150D);
		oos.writeObject(stu);
		oos.writeObject(stu1);
		oos.writeObject(stu2);
		oos.flush();
		oos.close();
		// 返回個異常
		
		while (true) {
			try {
				System.out.println((Student)ois.readObject());
			} catch (Exception e) {
				// 到達文件末尾
				break;
			}
			
		}
		ois.close();
	}
}
class Student implements Serializable{
	String name;
	transient Integer age;
	String sex;
	Double score;
	// 數組:基本數據類型可以序列化
	// 引用數據類型的數組,數組類型要支持序列化
	// static 會影響序列化
	public Student(String name, Integer age, String sex, Double score) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
		this.score = score;
	}
	@Override
	public  String toString() {
		return "Student [name=" + name + ", age=" + age + ", sex=" + sex + ", score=" + score + " ]";
	}
	//public native int add();
}
綜合示例:
public class TestInputStream {
	public static void main(String[] args) throws IOException, ClassNotFoundException{
		String file = "./src/txt/target.txt";
		// 輸入接口
		//____FileInputStream方式讀
		//fileInputRead(file);
		//____FileOutputStream方式取
		//fileOutputWrite(file);
		
		//fileInputRead(file);
		//____bufferedInput(file)
		//bufferedInput(file);
		//bufferedOutput(file);
		//bufferedInput(file);
		//_________________
		
		objecttOutputStream(file);
		objecttInputStream(file);
	}
	private  static void fileInputRead(String file) throws IOException {
		InputStream ios = new FileInputStream(file);  
		// 輸出接口 
		//OutputStream outStream = new FileOutputStream(file);
		// 每次讀一個字節
		//inputStream.read();
		byte[] bytes = new byte[1024];
		int n;
		while ((n = ios.read(bytes))!= -1) {
			for (int i = 0; i < n; i++) {
				System.out.print((char)bytes[i]); 
			}
		}
		ios.close();
	}
	private  static void fileOutputWrite(String file) throws IOException {
		OutputStream ios = new FileOutputStream(file);  
		// 每次寫入
		byte[] bytes = new byte[] {'1','2','3','4','5','6','7','8','9',65,66};
		ios.write(bytes);
		ios.close();
		
	}
	private  static void bufferedInput(String file) throws IOException {
		FileInputStream fileInputStream = new FileInputStream(file);
		BufferedInputStream bis = new BufferedInputStream(fileInputStream);
		// 緩衝流
		byte[] bytes = new byte[1024];
		int n;
		while ((n = bis.read(bytes))!=-1) {
			for (int i = 0; i < n; i++) {
				System.out.print((char)bytes[i]);
			}
		}
		bis.close();
		fileInputStream.close();
	}
	private  static void bufferedOutput(String file) throws IOException {
		FileOutputStream fileInputStream = new FileOutputStream(file);
		BufferedOutputStream bis = new BufferedOutputStream(fileInputStream);
		// 緩衝流
		byte[] bytes = new byte[] {'a','c','d','1','2','3','4'};
		int n;
		bis.write(bytes);
		bis.close();
		fileInputStream.close();
	}
	private  static void objecttOutputStream(String file) throws IOException{
		FileOutputStream fileInputStream = new FileOutputStream(file);
		ObjectOutputStream objectout = new ObjectOutputStream(fileInputStream);
		objectout.writeObject(new Student("李大大","33"));
		objectout.writeObject(new Student("趙巖巖","43"));
		objectout.writeObject(new Student("李敢敢","63"));
		objectout.close();
		fileInputStream.close();
	}
	private  static void objecttInputStream(String file) throws IOException, ClassNotFoundException{
		FileInputStream fileInputStream = new FileInputStream(file);
		ObjectInputStream objectout = new ObjectInputStream(fileInputStream);
		byte[] bytes = new byte[1024];
		while (true) {
			try {
				System.out.println((Student)objectout.readObject());
			} catch (Exception e) {
				// 到達文件末尾
				break;
			}
			
		}
		objectout.close();
		fileInputStream.close();
	}
}
class Student implements Serializable{
	private final static long serialVersionUID = 71282334L;
	private String name;
	private String age;
	public Student(String name, String age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getAge() {
		return age;
	}
	public void setAge(String age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
	
}
  • 歡迎交流探討
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章