天天看點

Java學習路線-27:IO操作深入與IO操作類繼承體系第17 章 : IO操作深入第18 章 : 輸入與輸出支援第19 章 : 對象序列化

第17 章 : IO操作深入

80 字元編碼常用的編碼

1、GBK/GB2312 國标編碼, GB2312簡體中文,GBK包含簡體和繁體

2、ISO8859-1 國際通用編碼,描述所有字母

3、UNICODE 16進制存儲,描述所有問題

4、UTF 象形文字部分使用16進制,普通字母采用ISO8859-1,主要使用UTF-8

列出本機屬性

System.getProperties().list(System.out);      

項目中出現亂碼問題就是編碼和解碼标準不統一

81 記憶體操作流

檔案操作流 以檔案為操作終端,InputStream、OutputStream

記憶體操作流

1、位元組記憶體操作流 ByteArrayOutputStream ByteArrayInputStream

2、字元記憶體操作流 CharArrayWriter CharArrayReader

繼承關系

OutputStream
    -FileOutputStream
    -ByteArrayOutputStream

InputStream
    -FileInputStream
    -ByteArrayInputStream 

Writer
    -OutputStreamWriter
        -FileWriter
    -CharArrayWriter

Reader
    -InputStreamReader
        -FileReader
    -CharArrayReader
      

示例:利用記憶體流小寫轉大寫操作

import java.io.*;

class Demo{
    public static void main(String[] args) throws IOException {
        String message = "hello java";

        // 将資料儲存到記憶體流中
        InputStream input = new ByteArrayInputStream(message.getBytes());
        OutputStream output = new ByteArrayOutputStream();

        int data = 0;

        // 每次讀取一個資料
        while ((data = input.read())!=-1){
            output.write(Character.toUpperCase(data));
        }

        System.out.println(output);
        // HELLO JAVA

        output.close();
        input.close();
    }
}      

82 管道流

發送資訊 <- 管道 -> 接收資訊      

位元組管道流 PipedInputStream, PipedOutputStream

字元管道流 PipedReader, PipedWriter

InputStream
    -PipedInputStream

OutputStream
    -PipedOutputStream

Reader
    -PipedReader

Writer
    -PipedWriter      

管道發送接收資料

import java.io.*;

class Sender implements Runnable {
    private PipedOutputStream output;

    public Sender() {
        this.output = new PipedOutputStream();
    }

    @Override
    public void run() {
        try {
            this.output.write("你好".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            this.output.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public PipedOutputStream getOutput() {
        return this.output;
    }
}

class Receiver implements Runnable {
    private PipedInputStream input;

    public Receiver() {
        this.input = new PipedInputStream();
    }

    @Override
    public void run() {

        try {
            byte[] data = new byte[1024];
            int len = this.input.read(data);
            System.out.println(new String(data, 0, len));
            // 你好
            
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            this.input.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public PipedInputStream getInput() {
        return this.input;
    }
}

class Demo {
    public static void main(String[] args) throws IOException {
        Sender sender = new Sender();
        Receiver receiver = new Receiver();

        // 管道連接配接
        sender.getOutput().connect(receiver.getInput());

        new Thread(sender).start();
        new Thread(receiver).start();
    }
}      

83 RandomAccessFile

随機讀取類,可以移動檔案指針

public RandomAccessFile(String name, String mode)      
import java.io.*;

class Demo {
    public static void main(String[] args) throws IOException {
        // 寫入
        RandomAccessFile writer = new RandomAccessFile("demo.txt", "rw");
        writer.write("你好世界".getBytes());
        writer.close();

        // 讀取
        RandomAccessFile reader = new RandomAccessFile("demo.txt", "rw");
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }

        writer.close();
    }
}      

第18 章 : 輸入與輸出支援

84 列印流

設計思想:裝飾設計模式

為OutputStream 類實作一層包裝

PrintStream

PrintWriter

OutputStream
    -FilterOutputStream
        -PrintStream
Writer
    -PrintWriter      
import java.io.*;

class Demo {
    public static void main(String[] args) throws IOException {

        PrintWriter writer = new PrintWriter(new FileWriter("demo.txt"));
        
        // 換行輸出
        writer.println("你好");

        // 格式化輸出
        writer.printf("姓名 %s, 年齡: %s", "小強", 23);

        writer.close();
    }
}      

隻要是檔案内容輸出時都使用列印流

85 System類對IO的支援

System是系統類

1、标準輸出(顯示器)

2、錯誤輸出

3、标準輸入(鍵盤)

public final class System {
    public final static InputStream in = null;
    public final static PrintStream out = null; // 黑色字型
    public final static PrintStream err = null; // 紅色字型
}      

修改輸出位置

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;

class Demo {
    public static void main(String[] args) throws IOException {
        System.setErr(new PrintStream(new FileOutputStream(new File("demo.txt"))));
        System.err.println("你好");
    }
}      

接收鍵盤輸入(一般不用此方法)

import java.io.IOException;
import java.io.InputStream;

class Demo {
    public static void main(String[] args) throws IOException {
        InputStream input = System.in;
        System.out.println("請輸入姓名:");
        byte[] data = new byte[1024];
        int len = input.read(data);

        System.err.println(new String(data, 0, len));
    }
}      

86 BufferedReader緩沖輸入流

JDK < 1.5

緩沖字元輸入流

Reader
    -BufferedReader      

代碼示例

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

class Demo {
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("請輸入:");
        String msg = reader.readLine();
        System.out.println(msg);
    }
}      

87 Scanner掃描流

JDK > 1.5

替代BufferedReader

構造函數

判斷是否有資料 public boolean hasNext()

讀取資料 public String next()

設定分隔符

import java.io.IOException;
import java.util.Scanner;

class Demo {
    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        System.out.println("請輸入年齡:");
        if(scanner.hasNextInt()){
            int age = scanner.nextInt();
            System.out.println("您輸入的年齡是:" + age);
        } else{
            System.out.println("輸入不正确");
        }
        scanner.close();
    }
}      

可以結合正則進行判斷驗證

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Scanner;

class Demo {
    public static void main(String[] args) throws ParseException {
        Scanner scanner = new Scanner(System.in);

        System.out.println("請輸入生日:");
        if (scanner.hasNext("\\d{4}-\\d{2}-\\d{2}")) {
            String msg = scanner.next("\\d{4}-\\d{2}-\\d{2}");
            System.out.println("您輸入的年齡是:" + new SimpleDateFormat("yyyy-MM-dd").parse(msg));
        } else {
            System.out.println("輸入不正确");
        }

        scanner.close();
    }
}      

讀取檔案

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

class Demo {
    public static void main(String[] args) throws FileNotFoundException {
        Scanner scanner = new Scanner(new File("demo.txt"));

        // 設定換行分隔符
        // scanner.useDelimiter("\n");

        while (scanner.hasNext()) {
            System.out.println(scanner.next());
        }

        scanner.close();
    }
}      

開發中:

輸出使用PrintWriter列印流

輸入使用Scanner掃描流

第19 章 : 對象序列化

88 對象序列化基本概念

對象序列化:

将記憶體中儲存的對象以二進制資料的形式處理,

實作對象的儲存或者網絡傳輸

儲存到檔案
堆記憶體 - 二進制轉換 ->  儲存到資料庫
                     發送到伺服器      

要序列化的對象必須實作java.io.Serializable 接口

沒有任何方法,隻是描述一種能力

示例

import java.io.Serializable;


class Person implements Serializable {
    private String name;
    private int age;

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

89 序列化與反序列化處理

InputStream(ObjectInput, ObjectStreamConstants)
    -ObjectInputStream

OutputStream(ObjectOutput, ObjectStreamConstants)
    -ObjectOutputStream      
import java.io.*;

class Person implements Serializable {
    private String name;
    private int age;

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

class Demo {
    private static final File  SAVE_FILE = new File("demo.person");

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Person person = new Person("Tom", 23);
        // saveObject(person);

        System.out.println(loadObject());
        // Person@15aeb7ab
    }

    // 序列化
    public static void saveObject(Object obj) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(SAVE_FILE));
        oos.writeObject(obj);
        oos.close();
    }

    // 反序列化
    public static Object loadObject() throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(SAVE_FILE));
        Object obj = ois.readObject();
        ois.close();
        return obj;
    }
}      

實際開發中不直接操作ObjectInputStream、ObjectOutputStream

90 transient關鍵字

表示進行序列化處理時,不處理被transient關鍵字修飾的字段

不常用,知道即可

IO繼承體系整合

// 位元組流:
OutputStream(Closeable, Flushable)
    -FileOutputStream
    -ByteArrayOutputStream
    -PipedOutputStream
    -FilterOutputStream
        -PrintStream
    -ObjectOutputStream


InputStream(Closeable)
    -FileInputStream
    -ByteArrayInputStream
    -PipedInputStream
    -ObjectInputStream

// 字元流:
Writer(Appendable, Closeable, Flushable)
    -OutputStreamWriter
        -FileWriter      
    -CharArrayWriter
    -PipedReader
    -PrintWriter
    -BufferedWriter

Reader(Readable, Closeable)
    -InputStreamReader
        -FileReader
    -CharArrayReader
    -PipedWriter
    -BufferedReader