流的分類
按操作資料機關不同分為:位元組流(8bit)二進制檔案,字元流(按字元)
按資料流的流向不同分為:輸入流、輸出流
按流的角色不同分為:節點流,處理流/包裝流
抽象基類 | 位元組流 | 字元流 |
---|---|---|
輸入流 | InputStream | Reader |
輸出流 | OutputStream | Writer |
位元組輸入流(InputStream )
相關子類
FileInputStream:檔案輸入流
BufferedInputStream:緩沖位元組輸入流
ObjectInputStream:對象位元組輸入流
FileInputStream檔案輸入流
以位元組形式處理流,主要是處理二進制檔案。
@Test
public void reader01() throws IOException {
String url = "C:\\Users\\lenovo\\Desktop\\hello.txt"; //檔案位址
int readData = 0;
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(url); //建立流
while ((readData = fileInputStream.read()) != -1) { // 數為-1時則表示讀取完
System.out.print((char) readData);
}
} catch (IOException e) {
log.error(e.getMessage());
} finally {
fileInputStream.close(); // 關閉流
}
}
上述代碼是進行單位元組進行讀取是以速度相對較慢,也可以指定一次讀取的位元組數量。
fileInputStream = new FileInputStream(url); //建立流
byte[] bytes = new byte[15]; //一次讀取的位元組數量
// 數為-1時則表示讀取完
// 如果讀取正常readData值為讀取字元數量
while ((readData = fileInputStream.read(bytes)) != -1) {
System.out.print(new String(bytes, 0, readData));
}
位元組輸出流(OutputStream)
相關子類:FileOutputStream位元組輸入流
@Test
public void write01() throws IOException {
FileOutputStream fileOutputStream = null;
String url = "C:\\Users\\lenovo\\Desktop\\a.txt"; //檔案位址
String text = "123456789"; //需要寫入的資料
try {
// new FileOutputStream(url)這種方式寫入檔案是覆寫的方式
// new FileOutputStream(url, true);這種方式寫入檔案是追加的方式
fileOutputStream = new FileOutputStream(url, true);
// write(byte b[], int off, int len)
// write(byte b[])
fileOutputStream.write(text.getBytes(), 1, 4); //将檔案寫入
} catch (FileNotFoundException e) {
log.error(e.getMessage());
} finally {
fileOutputStream.close(); //關閉連接配接
}
}
字元輸入流(FileWriter)
FileWriter常用方法
1、 new FileWriter(File/String):覆寫模式,相當于流的指針在首端
2、new FileWriter(File/String,trule):追加模式,相當于流的指針在尾端’
3、 write(int):寫入單個字元
4、write(char[]):寫入指定數組
5、write(char[],off,len):寫入指定數組的指定部分
6、write (string) :寫入整個字元串
7、write(string,off, len):寫入字元串的指定部分
注意!!!FileWriter使用後,必須要關閉(close)或重新整理(flush),否則寫入不到指定的檔案!
@Test
public void write() throws IOException {
FileWriter fileWriter = null;
String url = "C:\\Users\\lenovo\\Desktop\\note.txt"; //檔案位址
try {
String text = "風雨過後,能見彩虹。";//寫入檔案内容
fileWriter = new FileWriter(url);//開啟流
//表示寫入位置0-5的字元
fileWriter.write(text,0,5);
System.out.println("程式結束");
} catch (FileNotFoundException e) {
log.error(e.getMessage());
} finally {
//關閉流
if (fileWriter != null) {
fileWriter.close();
}
}
}
字元輸入流(FileReader)
@Test
public void read01() throws Exception {
FileReader fileReader = null;
String Url = "C:\\Users\\lenovo\\Desktop\\hello.txt";//檔案位址
int readData = 0;
try {
fileReader = new FileReader(Url); //啟動流
char[] chars = new char[24]; //流每次讀取檔案大小
//fileReader.read(chars)等于-1表示檔案讀取完成
//readData的值為讀取的檔案大小
//fileReader.read如果寫入讀取大小則每次讀取一個字元
while ((readData = fileReader.read(chars)) != -1) {
System.out.print(new String(chars, 0, readData));
}
} catch (FileNotFoundException e) {
log.error(e.Message);
} finally {
//關閉流
if (fileReader!= null) {
fileReader.close();
}
}
}
緩沖流
緩沖流的作用就是對位元組、字元流更高效的讀寫。字元緩沖流(BufferedWriter、BufferedReader)和位元組緩沖流(BufferedInputStream、BufferedOutputStream)
緩沖流中使用了修飾模式。修飾模式大緻思想如下。
建立抽象類Reader_
public abstract class Reader_ {
public void fileReader(){}
public void stringReader(){}
}
分别建立FileReader_、StringReader_繼承Reader_并實作方法
public class StringReader_ extends Reader_{
public void stringReader() {
System.out.println("stringReader");
}
}
public class FileReader_ extends Reader_{
public void fileReader() {
System.out.println("fileReader");
}
}
在BufferedReader_中定義屬性Reader_,通過構造器傳入的reader屬性對FileReader、StringReader_中的方法調用
public class BufferedReader_ {
private Reader_ reader;
public BufferedReader_(Reader_ reader) {
this.reader = reader;
}
public void fileReader() {
reader.fileReader();
}
public void stringReader() {
reader.stringReader();
}
}
測試
public class demo {
public static void main(String[] args) {
BufferedReader_ bufferedReader_ = new BufferedReader_(new FileReader_());
BufferedReader_ bufferedReader_1 = new BufferedReader_(new StringReader_());
bufferedReader_.fileReader();
bufferedReader_1.stringReader();
}
}
字元緩沖流
注意:
1、BufferedWriter和BufferedReader是按照字元操作的
2、不要去操作二進制檔案(視訊、錄音等),不然可能造成檔案損壞
字元緩沖輸出流BufferedWriter
//檔案輸出流
@Test
public void write() throws IOException {
// 檔案位址
String url = "C:\\Users\\lenovo\\Desktop\\note.txt";
// 将FileWriter轉換成BufferedWriter
// new FileWriter(url, true)中的true表示以追加形式寫入,沒有true則為清空寫入
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(url, true));
String text = "風雨過後";
//寫入
bufferedWriter.write(text);
// 關閉流
System.out.println("寫入成功");
bufferedWriter.close();
}
字元緩沖輸入流BufferedReader
//檔案輸入流
public static void main(String[] args) throws Exception {
String url = "C:\\Users\\lenovo\\Desktop\\note.txt";
// 建立BufferedReader
BufferedReader br = new BufferedReader(new FileReader(url));
String s; //按行讀取
// s為null則表示讀取完
while ((s = br.readLine()) != null) {
System.out.println(s);
}
// 關閉流
br.close();
}
位元組緩沖流
想要操作二進制檔案則使用BufferedInputStream和BufferedOutputStream來操作。他們既可以操作二進制檔案也可以操作文本檔案。因為二進制是根本。
public class BufferedCopy02 {
public static void main(String[] args) throws IOException {
String url = "C:\\Users\\lenovo\\Desktop\\1527.wav";
String newUrl = "C:\\Users\\lenovo\\Desktop\\海賊王.wav";
//位元組緩沖輸入流
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(url));
//位元組緩沖輸出流
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(newUrl));
//每次讀取位元組大小
byte[] buffer = new byte[1024];
int len;
while ((len = bufferedInputStream.read(buffer))!= -1) { //讀取并寫入 -1讀取完成
bufferedOutputStream.write(buffer, 0, len);
}
// 關閉流
bufferedOutputStream.flush();
bufferedInputStream.close();
}
}
節點流/處理流
通過序列化和反序列化的方式将資料和資料類型儲存到檔案中。ObjectOutputStream輸出流和ObjectInputStream輸入流
注意事項和細節說明
1)讀寫順序要一緻
2)要求實作序列化或反序列化對象,需要實作 Serializable
3)序列化的類中建議添加SerialVersionUID,為了提高版本的相容性
4)序列化對象時,預設将裡面所有屬性都進行序列化,但除了static或transient修飾的成員
5)序列化對象時,要求裡面屬性的類型也需要實作序列化接口
6)序列化具備可繼承性,也就是如果某類已經實作了序列化,則它的所有子類也已經預設實作了序列化
ObjectOutputStream輸出流
public class ObjectOutputStream_ {
public static void main(String[] args) throws IOException {
String url = "C:\\Users\\lenovo\\Desktop\\data.dat"; //檔案位址
ObjectOutputStream oos = null;
try {
// 建立流
oos = new ObjectOutputStream(new FileOutputStream(url));
//根據對應的類型寫入資料
oos.writeChar(1);
oos.writeDouble(1.1);
oos.writeUTF("username");
oos.writeObject(new Dog());
} catch (IOException e) {
System.out.println(e.getMessage());
} finally {
// 關閉流
oos.close();
}
}
}
// Serializable序列化
class Dog implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
}
ObjectInputStream輸入流
@Slf4j
public class ObjectInputStream_ {
public static void main(String[] args) throws IOException {
String url = "C:\\Users\\lenovo\\Desktop\\data.dat"; //檔案位址
ObjectInputStream ois = null;
try {
// 開啟輸入流
ois = new ObjectInputStream(new FileInputStream(url));
// 資料類型要與寫入資料類型一緻
System.out.println(ois.readChar());
System.out.println(ois.readDouble());
System.out.println(ois.readUTF());
System.out.println(ois.readObject());
} catch (IOException | ClassNotFoundException e) {
log.error("Error reading fileReader_", e.getMessage());
} finally {
ois.close();
}
}
}