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();
}
}
執行結果: