總結的放到前邊:
- 下邊的類圖很重要,心裏邊一定要有個印象,最好可以記住,尤其是標紅的類;
- 注意裝飾類的使用,這是一種好的代碼規範,性能的提升;
- 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工具類:前邊的原理明白了,這裏邊的方法主要是封裝;
FileUtils和IOUtils