最近剛看完b站上高淇老師的java300集教程,中間IO流那趴尤其云里霧里吼虎,前前后后看了幾遍又對比了代碼淋纲,IO流這部分的知識點差不多在腦子里也形成了一個體系,下面就總結(jié)一下教程中166到193講的IO流部分的內(nèi)容洪橘,就是我對這部分知識的理解。
首先IO流有三種分類:第一棵帽,輸入流熄求,輸出流。這就很好理解逗概,就是從程序的角度看弟晚,獲得信息就是輸入,給出信息就是輸出逾苫;第二卿城,字節(jié)流,字符流铅搓。字節(jié)流就是二進制的存儲方式瑟押,可以處理一切文件,而字符流就只能處理純文本星掰;第三多望,節(jié)點流嫩舟,處理流。節(jié)點流就是直接代表信息的源頭怀偷,而處理流只能起到增強功能家厌,所以必須包裹節(jié)點流才行。
IO流中有兩個重要的抽象類椎工,InputStream和OutputStream饭于,他們是字節(jié)流,也就是用byte處理數(shù)據(jù)维蒙。一種具體實現(xiàn)有FileInputStream和FileOutputStream掰吕,這里的File代表著一個源頭或目的地的意思,就是從文件讀或?qū)懭胛募Ee個栗子:
// 從文件讀取
File src = new File("e:/a.txt");
InputStream is = new FileInputStream(src);
byte[] flush = new byte[1024];
int len = 0;
while(len=is.read(flush)!=-1){
? ? String info = new String(flush, 0, len);
}
// 寫入文件
OutputStream os = new FileOutputStream(f, true);
byte data = "some information".getBytes();
os.write(data);
os.flush();
os.close();
這里的FileInputStream和FileOutputStream是字節(jié)流殖熟,所以讀取和寫入都用了byte數(shù)組。另外八千,在讀取時吗讶,采用了分段讀取的方法,就是一部分一部分地讀進flush中恋捆。
另外還有就是字符流照皆,讀純文本的,Reader和Writer沸停,實現(xiàn)類FileReader和FileWriter膜毁。具體方法找API吧,反正都是read write這種方法愤钾。
處理流瘟滨,BufferedInputStream, BufferedOutputStream, BufferedReader, BufferedWriter。這些是要包在節(jié)點流外面的能颁,起到一種提高性能的效果杂瘸。還有另外一個處理流,轉(zhuǎn)換流伙菊,起到解碼败玉,編碼的作用,能字符流和字節(jié)流相互轉(zhuǎn)換镜硕。InputStreamReader和OutputStreamWriter运翼。
其他的一個節(jié)點流,ByteArrayInputStream和ByteArrayOutputStream兴枯。這里ByteArray和File那對的命名有一定區(qū)別血淌,比如FileOutputStream是指輸出到File上,而ByteArrayOutputStream是指把ByteArray寫到OutputStream上财剖,就是ByteArray是被操作的對象悠夯,而File是目的地癌淮,這里很容易搞暈。這個節(jié)點流和上面一樣疗疟,用分段讀取的方法來操作该默,舉個栗子瞳氓,分析這個題目策彤,把文件中的一張圖,寫到byte數(shù)組中:從程序的角度看匣摘,首先我們要把圖讀到程序中店诗,就是輸入,從文件音榜,那就是FileInputStream庞瘸;接下來,把程序中的內(nèi)容赠叼,寫出去擦囊,就是輸出,到byte數(shù)組嘴办,就是ByteArrayOutputStream瞬场,大致相關(guān)的代碼如下,省略了異常還有聲明等部分:
InputStream is = new FileInputStream(new File("..."));
OutputStream os = new?ByteArrayOutputStream();
while(len=is.read(flush)!=-1){
? ? os.write(flush, 0, len);
}
os.flush();
return os.toByteArray();
還有兩種處理流涧郊,DataInputStream, DataOutputStream和ObjectInputStream, ObjectOutputStream贯被。對命名的理解和ByteArray是一樣的,就是被操作的對象是什么類型妆艘。其中一個很重要的應用就是序列化反序列化彤灶。把object寫到流中再讀出來,深克隆就用了這個操作批旺。因為這倆是處理流幌陕,所以需要包裹節(jié)點流。舉一個序列化反序列化的例子汽煮,把object寫到流中搏熄,即輸出,用ObjectOutputStream逗物,因為要包裹OutputStream搬卒,所以還要用到ByteArrayOutputStream;之后翎卓,把流中的object讀到程序里契邀,即輸入,用ObjectInputStream失暴,要包裹InputStream坯门,所以還要用到ByteArrayInputStream微饥。代碼:
// 寫到流中
ByteArrayOutputStream baos = new?ByteArrayOutputStream();
ObjectOutputStream oos = new?ObjectOutputStream(baos);
oos.writeObject(obj);
// 從流中讀
ByteArrayInputStream bais = new?ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new?ObjectInputStream(bais);
return ois.readObject();