1. 程式人生 > >java學習day16~17--IO流

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

  1. 先建立位元組流檔案
  2. 將位元組流檔案轉為字元流
  3. 讀取(注意轉成char型別)
  4. 關閉,只需要關閉外層的流即可,內部會幫我們關掉內層的
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來判斷是否讀取完畢