1. 程式人生 > 資訊 >今日小雪:雨凝為雪,地氣凍結

今日小雪:雨凝為雪,地氣凍結

java IO流的簡單入門

流的概念

記憶體與儲存裝置之間傳輸資料的通道

流的分類

按方向分:

  • 輸入流:將<儲存裝置>中的內容讀入到<記憶體>中

  • 輸出流:將<記憶體中的內容寫入到<儲存裝置>中

按單位分:

  • 位元組流:以位元組為單位,可以讀寫所有資料

  • 字元流:以字元為單位,只能讀寫文字資料

按功能分:

  • 節點流:具有實際傳輸資料的讀寫功能

  • 過濾流:在節點流的基礎上增強功能

位元組流

位元組流的父類(抽象類)

  • InputStream:位元組輸入流

    • public int read(){}

    • public int read(byte[] b){}

    • public int read(byte[] b, int off, int len){}

  • OutputSream:位元組輸出流

    • public void write(int n){}

    • public void write(byte[] b){}

    • public void write(byte[] b, int off, int len){}

檔案位元組流

  • FileInputStream:

    • public int read(byte[] b) //從流中讀取多個位元組,將讀到內容存入b陣列,返回實際讀到的位元組數;如果到達檔案尾部,則返回-1

    public class Demo1 {

    public static void main(String[] args) throws Exception{
    //1 建立FileInputStream,並指定檔案路徑
    FileInputStream fis = new FileInputStream("d:\\aaa.txt");
    //2 讀取檔案
    //2.1 單個位元組讀取
    int data = 0;
    while((data = fis.read())!=-1){
    System.out.println((char)data);
    }
    //2.2 多個位元組讀取
    byte[] buf = new byte[1024];
    int count = 0;
    while ((count = fis.read(buf))!=-1){
    System.out.println(new String(buf,0,count));
    }
    //3 關閉
    fis.close();
    }
    }

  • FileOutputSream:

    • public void write(byte[] b) //一次寫入多個位元組,將b陣列中所有位元組,寫入輸出流

    public class Demo1 {

    public static void main(String[] args) throws Exception {
    //1 建立FileOutputStream,並指定檔案路徑
    FileOutputStream fos = new FileOutputStream("d:\\aaa.txt",true);
    //true則表示檔案可以繼續寫而不會被覆蓋,預設為false
    //2 寫入檔案
    fos.write(97);
    fos.write('b');
    fos.write('c');

    String string = "helloworld";
    fos.write(string.getBytes());
    //3 關閉
    fos.close();
    }
    }

檔案複製(案例)

public class Demo1 {

public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("d:\\001.jpg");
FileOutputStream fos = new FileOutputStream("d:\\002.jpg");

byte[] buf = new byte[1024];
int count = 0;
while ((count=fis.read(buf))!=-1){
fos.write(buf,0,count);
}

fos.close();
fis.close();
}
}

位元組緩衝流

  • 緩衝流:BufferedInputStream/BufferedOutputStream

    • 提高IO效率,減少磁碟訪問次數

    • 資料儲存在快取區中,flush是將快取區的內容寫入檔案中,也可以直接close

  • 讀檔案

public class Demo1 {
public static void main(String[] args) throws Exception{
FileInputStream fis = new FileInputStream("d:\\aaa.txt");
BufferedInputStream bis = new BufferedInputStream(fis);

int data = 0;
while ((data= bis.read())!=-1){
System.out.println((char)data);
}
//也可以自己建立一個快取區
byte[] buf = new byte[1024];
int count = 0;
while ((count = bis.read(buf))!=-1){
System.out.println(new String(buf,0,count));
}

bis.close();
}
}
  • 寫檔案

public class Demo1 {
public static void main(String[] args) throws Exception{
FileOutputStream fos = new FileOutputStream("d:\\buffer.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);

for (int i = 0; i < 10; i++) {
bos.write("helloworld".getBytes());//寫入8K快取區
bos.flush();//重新整理到硬碟
}
//close內部會呼叫flush方法
bos.close();
}
}

物件流

物件流:ObjectInputStream/ObjectOutputStream

  • 增強了緩衝區功能

  • 增強了讀寫8種基本資料型別和字串功能

  • 增強了讀寫物件的功能

    • readObject() 從流中讀取一個物件(反序列化)

    • writeObject(Object obj) 向流中寫入一個物件(序列化)

學生類

public class student implements Serializable {//實現Serializable介面
private String name;
private int age;

public student(String name, int age) {
this.name = name;
this.age = age;
}

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;
}

@Override
public String toString() {
return "student{" + "name='" + name + '\'' + ", age=" + age + '}';
}
}

序列化

/**
* 要求:序列化的類必須要實現Serializable介面
*/
public class Demo1 {
public static void main(String[] args) throws Exception{
//1 建立物件流
FileOutputStream fos = new FileOutputStream("d:\\stu.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
//2 序列化(寫入操作)
student zhangsan = new student("張三",20);
oos.writeObject(zhangsan);
//3 關閉
oos.close();
}
}

反序列化

public class Demo1 {
public static void main(String[] args) throws Exception {
//建立物件流
FileInputStream fis = new FileInputStream("d:\\stu.bin");
ObjectInputStream ois = new ObjectInputStream(fis);
//讀取檔案
student s = (student) ois.readObject();
//關閉
ois.close();
System.out.println(s.toString());
}
}

序列化和反序列化注意事項

  • 序列化的類必須要實現Serializable介面

  • 序列化的類中的物件屬性也要求實現Serializable介面

  • serialVersionUID:序列化版本號ID,保證序列化的類和反序列化的類是同一個類

private static final long serialVersionUID = 100L;//這個數值是可以自定義的
  • 使用transient(瞬間的)修飾屬性,這個屬性就不能被序列化

  • 靜態屬性不能序列化

  • 序列化多個物件時,可以藉助集合實現

public class Demo1 {
public static void main(String[] args) throws Exception {
//1 建立物件流
FileOutputStream fos = new FileOutputStream("d:\\stu.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
//2 序列化(寫入操作)
student zhangsan = new student("張三", 20);
student lisi = new student("李四", 22);
// oos.writeObject(zhangsan);
// oos.writeObject(lisi);
ArrayList<student> list = new ArrayList<>();
list.add(zhangsan);
list.add(lisi);
oos.writeObject(list);

oos.close();
}
}
public class Demo2 {
public static void main(String[] args) throws Exception{
FileInputStream fis = new FileInputStream("d:\\stu.bin");
ObjectInputStream ois = new ObjectInputStream(fis);
//讀取檔案
ArrayList<student> list = (ArrayList<student>) ois.readObject();
//關閉
ois.close();
System.out.println(list.toString());
}
}

字元流

常見的字元編碼

編碼方式和解碼方式不一樣時會出現亂碼

  • ISO-8859-1 包括ASCII 西歐 希臘語 泰語 阿拉伯語 希伯來語對應的文字元號(一個位元組,只能表示255個字元)

  • UTF-8 萬國碼(1/2/3個位元組表示)

  • GB2312 簡體中文(1/2個位元組表示)

  • GBK 簡體中文,擴充(1/2個位元組表示)

  • BIG5 臺灣,繁體中文

字元流的父類(抽象類)

  • Reader:字元輸入流

    • public int read(){}

    • public int read(char[] c){}

    • public int read(char[] c, int off, int len){}

  • Writer:字元輸出流

    • public void write(int n){}

    • public void write(String str){}

    • public void write(char[] c){}

檔案字元流

  • FileReader:

    • public int read(char[] c) //從流中讀取多個字元,將讀到內容存入c陣列,返回實際讀到的字元數;如果到達檔案尾部,則返回-1

public class Demo1 {
public static void main(String[] args) throws Exception {
FileReader fr = new FileReader("d:\\hello.txt");
//單個字元讀取
int data=0;
while ((data=fr.read())!=-1){
System.out.print((char) data);
}
//自建快取區,一次性讀取
char[] buf = new char[1024];
int count = 0;
while ((count= fr.read(buf))!=-1){
System.out.println(new String(buf,0,count));
}
fr.close();
}
}
  • FileWriter:

    • public void write(String str) //一次寫入多個字元

public class Demo1 {
public static void main(String[] args) throws Exception {
FileWriter fw = new FileWriter("d:\\hello.txt");
//單個字元讀取
for (int i = 0; i < 10; i++) {
fw.write("Java是世界上最好的語言\r\n");
fw.flush();
}
fw.close();
}
}

使用FileReader和FileWriter只能複製文字檔案,不能複製圖片或者二進位制檔案

因為圖片和二進位制檔案沒有字元編碼

字元緩衝流

  • 緩衝流:BufferedReader/BufferedWriter

  • 優點

    • 高效讀寫

    • 支援輸入換行符

    • 可一次寫一行,讀一行

  • BufferedReader

public class Demo1 {
public static void main(String[] args) throws Exception {
FileReader fr = new FileReader("d:\\write.txt");
BufferedReader br = new BufferedReader(fr);
//一行一行讀
String line = null;
while ((line = br.readLine())!=null){
System.out.println((line);
}
//可以自己建立一個快取區
char[] buf = new char[1024];
int count = 0;
while ((count = br.read(buf))!=-1){
System.out.println(new String(buf,0,count));
}

br.close();
}
}
  • BufferedWriter

public class Demo1 {
public static void main(String[] args) throws Exception {
FileWriter fw = new FileWriter("d:\\write.txt");
BufferedWriter bw = new BufferedWriter(fw);

for (int i = 0; i < 10; i++) {
bw.write("好好學習,天天向上");
bw.newLine();//寫入一個換行符(每個系統的換行符不一樣,但這個方法均適配)
bw.flush();
}
bw.close();
}
}

列印流

  • PrintWriter:

    • 封裝了print()/println()方法,支援寫入後換行

    • 支援資料原樣列印

public class Demo1 {
public static void main(String[] args) throws Exception {
PrintWriter pw = new PrintWriter("d:\\print.txt");

pw.println(97);
pw.println(true);
pw.println(3.14);
pw.println('a');

pw.close();
}
}

轉換流

  • 橋轉換流:InputStreamReader/OutputStreamWriter

    • 可將位元組流轉換為字元流

    • 可設定字元的編碼方式

  • InputStreamReader

public class Demo1 {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("d:\\writer.txt");
InputStreamReader irs = new InputStreamReader(fis,"utf-8");

int data = 0;
while ((data = irs.read())!=-1){
System.out.print((char)data);
}

irs.close();
}
}
  • OutputStreamWriter

public class Demo1 {
public static void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream("d:\\info.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");

for (int i = 0; i < 10; i++) {
osw.write("我愛川農\r\n");
osw.flush();
}

osw.close();
}
}