java學習day16~17--IO流
Input 輸入 Output輸出
一.檔案(File可以用來代表不存在的目錄或檔案,可以建立)
java.io.File 它是對應著實際的檔案或者目錄
New File(String 檔案路徑)
可以用/或者\\作為檔案分隔符,不過為了通用可以使用File.separator獲取不同作業系統的分隔符
檔案的常用方法
isFile(); 判斷是否是一個檔案
isDirectory(); 判斷檔案是否是一個目錄
mkdir(); 建立一個不存在的目錄
mkdirs(); 建立多級目錄
exists(); 用來判斷一個檔案是否存在
listFiles(); 得到一個目錄下的所有子目錄和檔案
delete(); 理解刪除檔案
deleteOnExit(); 程式執行結束後刪除檔案
renameTo(); 重新命名和移動
getAbsoluteFile(); 獲得檔案的絕對路徑
二.IO流
Input 輸入流: 從檔案讀取內容,檔案對我就是輸入流
Output 輸出流:向檔案中寫入內容,檔案對我就是輸出流
InputStream 抽象類 –> FileInputStream 問價輸入流
OutputStream 抽象類 ->FileOutputStream 檔案輸出流
位元組流
InputStream
(*) FileInputStream 從檔案讀取位元組
(*) BufferedInputStream 加入緩衝功能,提高檔案的讀取效率
ByteArrayInputStream 從位元組陣列變成輸入流
OutputStream
(*) FileOutputStream 向檔案寫入位元組
(*) BufferedOutputStream 加入緩衝功能, 提高檔案的寫入效率
ByteArrayOutputStream 把流的內容寫入位元組陣列
PrintStream 實際上就是 System.out
字元流
Reader
(*) InputStreamReader 轉換位元組流為字元流
(*) BufferedReader 功能增強,以行為單位讀取資料 (裝飾器模式)
FileReader 是InputStreamReader子類,將字元編碼固定為作業系統的預設編碼,不能手工改動
Writer
(*) OutputStreamWriter 轉換位元組流為字元流
(*) PrintWriter 以行為單位寫入資料
write 當成字元寫入
print print就是將引數轉為字串後寫入
FileWriter 是OutputStreamWriter的子類,也是固定了字元編碼
檔案的讀取
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
//測試檔案輸入流,讀取外部檔案內容
public class FileInputStreamTest1 {
public static void main(String[] args) throws IOException {
//開啟檔案
File f = new File("F:\\學習練習\\javasePrac\\西部開源\\IO流\\src\\day16\\abc.txt");
//建立檔案輸入流物件
FileInputStream fis = new FileInputStream(f);
// 方式一:一個位元組一個位元組的讀取
// while(true) {
// int r = fis.read();
// if(-1 == r) { //當檔案讀到尾時,跳出迴圈
// break;
// }
//
// System.out.print((char) r + " ");
// }
// 方式二:將讀入的內容轉為陣列,然後輸出
while(true) {
byte[] by = new byte[100];
int r = fis.read(by);
if(-1 == r) {
break;
}
System.out.println(Arrays.toString(by));
}
}
}
檔案的寫入
1.建立輸出流
FileOutputStream fos = new FileOutputStream(“檔名”);
2.向輸出流中寫入資料
fos.write(97);;
3.關閉輸出流
fos.close();
檔案的複製
import java.io.*;
public class Test
{
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("1.txt");
FileOutputStream fos = new FileOutputStream("3.txt");
while(true) {
byte[] buf = new byte[1024];
int len = fis.read(buf);
if(len == -1) {
break;
}
fos.write(buf, 0, len); // 實際讀到len個位元組,就寫入len個位元組
}
fis.close();
fos.close();
}
}
2.用Files的copy方法,引數1是被拷貝的檔案,引數2 是拷貝後的檔案
三.字元流
以字元為單位處理流的內容
Reader 字元輸出流, InputStreamReader
Writer 字元輸出流 OutputStreamWriter
- 先建立位元組流檔案
- 將位元組流檔案轉為字元流
- 讀取(注意轉成char型別)
- 關閉,只需要關閉外層的流即可,內部會幫我們關掉內層的
import java.io.*;
import java.util.*;
public class Test
{
public static void main(String[] args) throws IOException {
// 1. 將位元組流轉換為字元流
FileInputStream fis = new FileInputStream("1.txt");
// 注意:實際檔案編碼要與讀取時的檔案編碼一致
InputStreamReader reader = new InputStreamReader(fis, "utf-8");
// 2. 讀取
/*while(true) {
int c = reader.read();
if(c == - 1) {
break;
}
System.out.println((char)c);
}*/
while(true) {
char[] buf = new char[1024];
int len = reader.read(buf);
if(len == -1) {
break;
}
System.out.println(Arrays.toString(buf));
}
// 3. 關閉, 只需要關閉外層的流, 內部會幫我們關掉內層的流
reader.close();
}
}
BufferedReader是在InputStreamReader的基礎上以行為單位處理字元流,兩者之間是平級關係,父類都是Reader(裝飾者模式)
import java.io.*;
import java.util.*;
public class Test
{
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("1.txt");
InputStreamReader reader = new InputStreamReader(fis, "utf-8");
BufferedReader reader2 = new BufferedReader(reader);
/*System.out.println(reader2.readLine()); // 以行為單位讀取資料
System.out.println(reader2.readLine()); // 以行為單位讀取資料
System.out.println(reader2.readLine()); // 以行為單位讀取資料*/
while(true) {
String line = reader2.readLine();
if(line == null) {
break;
}
System.out.println(line);
}
reader2.close();
}
}
裝飾者模式:
裝飾者與被裝飾者需要有一個共同的父類
裝飾者和被裝飾者之間體現的是組合的關係,而不是繼承的關係,目的是為了更加靈活
裝飾者會對被裝飾者做功能上的增強
四.java中的序列化和反序列化
序列化
將物件中的資訊永久儲存
1.將物件資訊存入資料庫
2.java中提供的序列化方式來永久儲存資料
import java.io.*;
//如果沒有實現Serializable介面,會出現NotSerializableException異常
class Student implements Serializable{
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Test
{
public static void main(String[] args) throws Exception {
Student student = new Student();
student.setId(1);
student.setName("張三");
// 序列化就是將物件變為輸出位元組流
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("d:\\student.obj"));
os.writeObject(student);
os.close();
}
}
注意:
要求物件中的所有屬性也都是可以序列化
如果某個屬性不想序列化,可以在屬性上加"transient"關鍵字
反序列化
把位元組內容讀取進來,還原為java物件
ObjectInputStream用來讀取位元組內容,還原(反序列化)為java物件
import java.io.*;
class Student implements Serializable{
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Test
{
public static void main(String[] args) throws Exception {
ObjectInputStream is = new ObjectInputStream(new FileInputStream("d:\\student.obj"));
Student s = (Student)is.readObject();
System.out.println(s.getId());
System.out.println(s.getName());
System.out.println(s.getAddress());
}
}
除了可以寫入和讀取物件以外,還可以寫入和讀取基本型別(int,long,boolean...) ,讀取和寫入的順序要保持一致
如果不一致,出現EOFException
如果沒有更多內容,也會出現EOFException
建議在寫入時最後一個物件使用null,這樣讀取時就可以根據null來判斷是否讀取完畢