1. 程式人生 > >Java基礎之File類與IO流(三)

Java基礎之File類與IO流(三)

一、記憶體流

使用記憶體流的需求:

        把一個網路上的圖片儲存到陣列中,但是圖片的大小不能確定,怎樣解決?

記憶體流主要用來操作記憶體

ByteArrayInputStream和ByteArrayOutputStream

        輸入和輸出可以把檔案作為資料來源,也可以把記憶體作為資料來源;

        ByteArrayInputStream主要完成將內容從記憶體中讀入程式中,而ByteArrayOutputStream的主要功能是將資料寫入到記憶體中。

注意:因為這兩個流沒有使用系統資源,所以不用關閉,也不需要丟擲異常。

記憶體流操作示意圖:


ByteArrayOutputStream獲取資料的方式

1、public byte[] toByteArray()

           建立一個新分配的位元組陣列。它的大小是這個輸出流的當前大小和緩衝區的有效內容的副本。

2、public String toString()

           使用該平臺的預設字符集將緩衝區的內容轉換為字串。

二、列印流

列印流提供了列印方法,可以將各種資料型別原樣列印,可以操作輸出流和檔案。

PrintStream

     1、提供了操作位元組的功能;

     2、如果包裝的是緩衝流可設定自動flush

     3、可設定字符集

PrintWriter

      1、沒有操作位元組功能

      2、內部有緩衝區,即使將自動重新整理設定為true

      3、可設定字符集

列印流的構造方法

PrintStream的構造方法:

public PrintStream(File file)

public PrintStream(OutputStream out)

PrintWriter 的構造方法

public PrintWriter(File file)

public PrintWriter(Writer out)

public Print(OutputStream out)

三、物件流、序列化與反序列化

相關類

    1、ObjectOutputStream(用於序列化)

    2、ObjectInputStream(用於反序列化)

使用物件流可以實現物件的序列化與反序列化操作

使用序列化的原因:

1、易於儲存

2、易於傳輸

序列化與反序列化

序列化與反序列化的過程


序列化:將物件的狀態儲存到特定儲存介質中的過程(將物件轉換成位元組序列(二進位制)的過程)

反序列化:從特定儲存介質中的資料重新構建物件的過程(將物件的二進位制形式轉換成物件)

                  序列化步驟                                                                   反序列化步驟

                              

實現了Serializable介面的類都應該生成一個private static final long serialVersionUID序列化版本ID作為標識

原因:我們剛開始寫完一個類,這個類沒有生成序列化版本ID,將內容序列化以後,可以反序列化,但當我們將這個類稍微改動之後,就不能在反序列化了

注意:

序列化不能儲存靜態成員和transient修飾的成員

四、RandomAccessFile

直接繼承Object。

主要功能是完成隨機讀寫功能,可以讀取指定位置的內容。

構造方法:

public RandomAccessFile(File file,String mode)

public RandomAccessFile(String name,String mode)

      只能操作檔案

檔案的開啟模式(mode):

       “r”以只讀方式開啟。呼叫結果物件的任何write方法都將導致丟擲IOException。

       “rw”開啟以便讀取和寫入。如果該檔案尚不存在,則嘗試建立給檔案。

RandomAccessFile常用方法


五、裝飾者模式

背景:

       當需要對已有的物件進行功能增強時,可以定義類(裝飾類),將已有的物件傳入,基於已有的功能,並提供加強功能,那麼自定義的類為裝飾類。

裝飾者設計模式的特點:

1、裝飾物件和真實物件有相同的介面或抽象類

2、裝飾物件包含一個真實物件的引用

3、裝飾物件接收所有的來自客戶端的請求,它把這些請求轉發給真實的物件

4、裝飾物件可以在轉發這些請求之前或之後增加一些附加的功能

裝飾者設計模式的結構:

1、抽象構建角色(Component):

          給出一個抽象的介面,以規範準備接受附加責任的物件。相當於IO流裡的InputStream/OutputStream。

2、具體的構建角色(ConcreteComponent):

         定義一個將要接受附加責任的類。相當於IO裡面的FileInputStream/FileOutputStream。

3、抽象裝飾角色(Decorator):

         持有一個抽象構建角色(也就是Component)的引用,並實現這個抽象構建介面。相當於FilterInputStream/FilterOutputStream。

4、具體的裝飾角色(ConcreteDecorator):

         負責給構建物件“貼上”附加的責任。相當於BufferedInputStream/BufferedOutputStream。

ByteArrayInputStream例項:

package memory;

import java.io.ByteArrayInputStream;
import java.io.IOException;

public class ByteArrayInputStreamDemo {

	public static void main(String[] args) {
		String data = "你好,記憶體流";
		ByteArrayInputStream bais = new ByteArrayInputStream(data.getBytes());//構造方法中傳入的位元組陣列就是要讀取的位元組陣列
		byte[] b = new byte[1024];//自定義緩衝區
		try {
			int len = bais.read(b);
			System.out.println("讀取到的內容是:" + new String(b,0,len));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
執行結果:

ByteArrayOutputStream例項:

package memory;

import java.io.*;

public class ByteArrayOutputStreamDemo {

	public static void main(String[] args) {
		File srcFile = new File("f:" + File.separator + "18.jpg");
		File destFile = new File("f:" + File.separator + "18.txt");
		InputStream input = null;
		OutputStream out = null;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();//寫入記憶體中的記憶體輸出流
		try {
			input = new FileInputStream(srcFile);//讀取原始檔的輸入流
			out = new FileOutputStream(destFile);//寫入目標檔案的輸出流
			byte[] b = new byte[1024];
			int len = 0;
			while((len = input.read(b)) != -1) {
				baos.write(b,0,len);//不斷地寫入記憶體
			}
			byte[] data = baos.toByteArray();//建立一個新分配的位元組陣列。它的大小是當前這個輸出流的當前大小和緩衝區的有效內容的副本
			out.write(data);//將圖片檔案一次性的寫入目標檔案
			System.out.println("寫入成功!");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				out.close();
				input.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

}
執行結果:

序列化與反序列化例項:

package serial;

import java.io.Serializable;

public class Person implements Serializable {

	/**
	 * 新增一個控制序列化與反序列化版本一致性的serialVersionUID屬性
	 */
	private static final long serialVersionUID = 1L;
	private String name;
	private int age;
	private transient String sex;//由transient修飾的屬性不能被序列化儲存
	static String job;//靜態屬性也不能被序列化儲存
	
	public Person() {
	}

	public Person(String name, int age, String sex) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]" + job;
	}
	
	
}
package serial;

import java.io.*;
/**
 * 序列化
 * @author lenovo
 *
 */
public class SerialDemo {

	public static void main(String[] args) {
		File file = new File("f:" + File.separator + "test.txt");
		Person per = new Person("胡漢三",28,"男 ");
		OutputStream out = null;
		ObjectOutputStream oos = null;
		try {
			out = new FileOutputStream(file);
			oos = new ObjectOutputStream(out);
			Person.job = "混世魔王";
			oos.writeObject(per);//序列化
			System.out.println("序列化成功!");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				oos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}

}
package serial;

import java.io.*;

/**
 * 反序列化
 * @author lenovo
 *
 */
public class DeSerialDemo {

	public static void main(String[] args) {
		File file = new File("f:" + File.separator + "test.txt");
		InputStream input = null;
		ObjectInputStream ois = null;
		try {
			input = new FileInputStream(file);
			ois = new ObjectInputStream(input);
			Person per = (Person)ois.readObject();//反序列化
			System.out.println(per);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				ois.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

}
執行結果:

序列化:

反序列化:


RandomAccessFile例項:

package raf;

import java.io.*;

public class RandomAccessFileDemo {

	public static void main(String[] args) {
		File file = new File("f:" + File.separator + "teest.txt");
		RandomAccessFile raf = null;
		try {
			raf = new RandomAccessFile(file,"rw");
			raf.writeBoolean(false);
			raf.writeChars("hello");
			raf.writeChar('中');
			System.out.println("寫入成功!");
			
			raf.seek(9);
			System.out.println("當前檔案指標位置:" + raf.getFilePointer());
			System.out.println(raf.readChar());
			raf.seek(3);
			System.out.println("當前檔案指標位置:" + raf.getFilePointer());
			System.out.println(raf.readChar());
			raf.seek(11);
			System.out.println("當前檔案指標位置:" + raf.getFilePointer());
			System.out.println(raf.readChar());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
執行結果:

裝飾者模式例項:

package decorator;

/**
 * 抽象構建角色
 * @author lenovo
 *
 */
public interface Learn {
	public void learn();
}
package decorator;

/**
 * 具體的構建角色
 * @author lenovo
 *
 */
public class Student implements Learn {

	@Override
	public void learn() {
		System.out.println("聚精會神的看書...");
	}

}
package decorator;

/**
 * 抽象裝飾角色
 * @author lenovo
 *
 */
public class Decorator implements Learn {
	private Learn learn;//持有抽象構建角色的引用
	
	
	public Decorator(Learn learn) {
		super();
		this.learn = learn;
	}


	@Override
	public void learn() {
		this.learn.learn();
	}

}
package decorator;

/**
 * 具體的裝飾角色
 * @author lenovo
 *
 */
public class ConcreteDecorator extends Decorator{

	public ConcreteDecorator(Learn learn) {
		super(learn);
	}

	public void hardLearn() {
		System.out.println("找書...");
		super.learn();
		System.out.println("記筆記...");
	}
}
package decorator;

public class TestDecorator {

	public static void main(String[] args) {
		Learn learn = new Student();
		ConcreteDecorator cd = new ConcreteDecorator(learn);
		cd.hardLearn();
	}

}

執行結果: