io流知識學習總結

總結的放到前邊:

  1. 下邊的類圖很重要,心裏邊一定要有個印象,最好可以記住,尤其是標紅的類;
  2. 注意裝飾類的使用,這是一種好的代碼規範,性能的提升;
  3. ByteArrayInputStream,ByteArrayOutStream這兩個類很關鍵,可以把任何內容轉成字節數組(不管你是文件流,對象流,數據流...),放於內存,然後再做響應的處理;
  • 構造File的三種形式;
  • File裏邊的路徑可以是不存在的。
  • 相對路徑和絕對路徑的理解(絕對路徑是帶盤的,相對路徑是不帶盤的,一般在項目中使用的都是相對路徑,默認相對於項目的路徑,這裏項目的路徑是絕對路徑,默認代碼實現如下)

 

System.getProperty("user.dir")  E:\ideaWorkSpaces\tool
file.separatorChar 輸出:\        file.pathSeparatorChar 輸出:

路徑記錄:

File file2 = new File("psb.jpg");  
System.out.println(file2.getPath()); psb.jpg
System.out.println(file2.getAbsolutePath()); E:\ideaWorkSpaces\tool\psb.jpg
System.out.println(System.getProperty("user.dir")); E:\ideaWorkSpaces\tool

類圖:

  • createNewFile方法創建的是文件,不是文件夾;con是操作系統的關鍵字,不能創建;
  • file.mkdir();確保上級目錄存在,不存在創建失敗;
  • file.mkdirs();上級目錄可以不存在,不存在就創建;
  • file.list()方法是返回某個目錄下的所有文件和目錄的文件名,返回的是String數組file.listFiles()方法是返回某個目錄下所有文件和目錄的絕對路徑,返回的是File數組

編碼和解碼:編碼的過程其實就是字符到字節的轉換過程;解碼的過程其實就是字節到字符的轉換過程

  • 亂碼的原因1:字節數不夠,比如,一箇中文在計算機裏邊字節長度是3,如果你減少一個,那麼解碼的時候,即使字符集一樣,也會是亂碼;2:字符集不一致,編碼的時候用的gbk,解碼的時候用的utf-8,那麼也會出現亂碼;
  • 字節流能處理的不一定字符流可以,比如文件,圖片,音頻,視頻;但是字符流可以處理的,字節流也一定可以處理;
  • 流程:創建源--選擇流--操作--釋放
  • FileOutputStream對於不存在的路徑,可以自動創建,並且,可以主動追加(true和false);
outputStream = new FileOutputStream("out.txt",true);
  • FileInpuStream如果文件不存在,不會創建;
  • 如果源頭是磁盤上的文件的話,操作系統不會主動去訪問,所以我們最後通知他釋放資源---通過close()方法去關閉流;如果源頭是電腦上的內存(字節數組(ByteArrayInputStream,ByteArrayOutStream)),java可以直接訪問,所以可以通過gc去釋放,不需要關閉;任何東西都可以轉換成字節數組,但是字節數組不要太大,不然太佔內存;
  • 文件流和字節流的結合:文件-->文件流(FileInputStream)-->字節流(ByteArrayOutStream)-->字節流(ByteArrayInputStream)-->文件流(FileOutputStream)-->文件;
  • BufferedInputStream採用裝飾者模式,可以對InputStream進行裝飾,裏邊默認會有一個8k的緩衝器,當你讀取文件的時候,當讀取的字節達到8k的時候,纔會進行寫出操作;
  • BufferedInputStream和BufferedOutputStream對應
//(1024字節=1k)
private static int DEFAULT_BUFFER_SIZE = 8192;
public BufferedInputStream(InputStream in) {
    this(in, DEFAULT_BUFFER_SIZE);
}

代碼對比:(字節流緩衝前)

String pathSource=System.getProperty("user.dir")+"\\abc.txt";
String pathTarget=System.getProperty("user.dir")+"\\abcCopy.txt";
InputStream inputStream=null;
OutputStream outputStream=null;
try {
     inputStream = new FileInputStream(pathSource);
     outputStream = new FileOutputStream(pathTarget);
    byte[] inputBytes = new byte[2];//緩衝容器,沒讀兩個就開始寫
    while (inputStream.read(inputBytes)!=-1){
        outputStream.write(inputBytes);
        outputStream.flush();
    }

}

字節流緩衝後:(裝飾)

String pathSource=System.getProperty("user.dir")+"\\abc.txt";
String pathTarget=System.getProperty("user.dir")+"\\abcCopy.txt";
InputStream inputStream=null;
OutputStream outputStream=null;
try {
     inputStream = new BufferedInputStream(new FileInputStream(pathSource));
     outputStream = new BufferedOutputStream(new FileOutputStream(pathTarget));
    byte[] inputBytes = new byte[1024];//緩衝容器,每次讀1024個字節,當達到8k時候纔開始寫操作;
    while (inputStream.read(inputBytes)!=-1){
        outputStream.write(inputBytes);
        outputStream.flush();
    }
}

字符流緩衝前:

String pathSource=System.getProperty("user.dir")+"\\abc.txt";
String pathTarget=System.getProperty("user.dir")+"\\abcCopy.txt";
Reader inputStream=null;
Writer outputStream=null;
try {
     inputStream = new FileReader(pathSource);
     outputStream = new FileWriter(pathTarget);
    char[] inputBytes = new char[2];//緩衝容器,2個2個緩衝
    while (inputStream.read(inputBytes)!=-1){
        outputStream.write(inputBytes);
        outputStream.flush();
    }
}

字符流緩衝後:

String pathSource=System.getProperty("user.dir")+"\\abc.txt";
String pathTarget=System.getProperty("user.dir")+"\\abcCopy.txt";
BufferedReader inputStream=null;
BufferedWriter outputStream=null;
try {
    inputStream = new BufferedReader(new FileReader(pathSource));
    outputStream = new BufferedWriter(new FileWriter(pathTarget));
    String len = "";
    while ((len=inputStream.readLine())!=null){ //一行一行的讀取,一行一行的寫
        outputStream.write(len);
        outputStream.newLine();//換行符
        outputStream.flush();
    }
}

轉換流:InputStreamReader和OutputStreamWriter

InputStreamReader可以把字節(純文本的)轉換成字符,也可以指定相應的字符編碼;

OutputStreamWriter可以把字符輸出,並且可以指定相應的字符編碼;

數據流:DateInputStream和DataOutputStream;有順序之分,讀取的順序和寫出的順序保持一致;不然會報錯或者讀取的結果不正確;

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream);
dataOutputStream.writeInt(1);
dataOutputStream.writeFloat(3);
dataOutputStream.writeUTF("121");
dataOutputStream.flush();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
DataInputStream dataInputStream = new DataInputStream(byteArrayInputStream);
int i = dataInputStream.readInt();
float v = dataInputStream.readFloat();
System.out.println(v);
System.out.println(i);

對象流ObjectInputStream和ObjectOutputStream

1.先寫出後讀取;

2.讀取的順序和寫出的順序保持一致;

3.不是所有的對象都可以序列化,必須實現Serializable接口,相當於一個通行證,告訴虛擬機我可以序列化;

public void test1() throws Exception {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        AA aa = new AA("11",2);
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeInt(2);
        objectOutputStream.writeObject(aa);
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        ObjectInputStream inputStream = new ObjectInputStream(byteArrayInputStream);
        int anInt = inputStream.readInt();
        System.out.println(anInt);
        Object o = inputStream.readObject();
        AA aa1 = (AA)o;
        System.out.println(JsonUtil.toJson(aa1));
    }


class AA implements Serializable {
    private String aa;
    private int bb;

    public AA(String aa, int bb) {
        this.aa = aa;
        this.bb = bb;
    }
}

隨機流:RandomAccessFile

合併流:SequenceInputStream

注意io工具類:前邊的原理明白了,這裏邊的方法主要是封裝;

FileUtilsIOUtils

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章