面试官提出的Io问题 如何去做解答呢?
主要內(nèi)容
-
java.io.File類的使用
-
IO原理及流的分類
-
文件流
-
FileInputStream / FileOutputStream / FileReader / FileWriter
-
緩沖流
-
BufferedInputStream / BufferedOutputStream /
-
BufferedReader / BufferedWriter
-
-
轉(zhuǎn)換流
-
InputStreamReader / OutputStreamWriter
-
標(biāo)準(zhǔn)輸入/輸出流
-
打印流(了解)
-
PrintStream / PrintWriter
-
數(shù)據(jù)流(了解)
-
DataInputStream / DataOutputStream
-
對象流 ----涉及序列化、反序列化
-
ObjectInputStream / ObjectOutputStream
-
隨機(jī)存取文件流
-
RandomAccessFile
File類
-
java.io.File類:文件和目錄路徑名的抽象表示形式,與平臺無關(guān)
-
File 能新建、刪除、重命名文件和目錄,但 File 不能訪問文件內(nèi)容本身。如果需要訪問文件內(nèi)容本身,則需要使用輸入/輸出流。
-
File對象可以作為參數(shù)傳遞給流的構(gòu)造函數(shù)
-
File類的常見構(gòu)造方法:
-
public File(String pathname)
-
以pathname為路徑創(chuàng)建File對象,可以是絕對路徑或者相對路徑,如果pathname是相對路徑,則默認(rèn)的當(dāng)前路徑在系統(tǒng)屬性user.dir中存儲。
-
public File(String parent,String child)
以parent為父路徑,child為子路徑創(chuàng)建File對象。
-
File的靜態(tài)屬性String separator存儲了當(dāng)前系統(tǒng)的路徑分隔符。
-
在UNIX中,此字段為'/',在Windows中,為'\\'
常見方法:
?
eg:File dir1 = new File("D:/IOTest/dir1");if (!dir1.exists()) { // 如果D:/IOTest/dir1不存在,就創(chuàng)建為目錄dir1.mkdir(); }// 創(chuàng)建以dir1為父目錄,名為"dir2"的File對象File dir2 = new File(dir1, "dir2");if (!dir2.exists()) { // 如果還不存在,就創(chuàng)建為目錄dir2.mkdirs(); }File dir4 = new File(dir1, "dir3/dir4");if (!dir4.exists()) {dir4.mkdirs();}// 創(chuàng)建以dir2為父目錄,名為"test.txt"的File對象File file = new File(dir2, "test.txt"); ????if (!file.exists()) { // 如果還不存在,就創(chuàng)建為文件file.createNewFile();}IO流用來處理設(shè)備之間的數(shù)據(jù)傳輸。Java IO原理
-
Java程序中,對于數(shù)據(jù)的輸入/輸出操作以"流(stream)" 的方式進(jìn)行。
-
java.io包下提供了各種"流"類和接口,用以獲取不同種類的數(shù)據(jù),并通過標(biāo)準(zhǔn)的方法輸入或輸出數(shù)據(jù)。
流的分類
-
按操作數(shù)據(jù)單位不同分為:字節(jié)流(8 bit),字符流(16 bit)
-
按數(shù)據(jù)流的流向不同分為:輸入流,輸出流
-
按流的角色的不同分為:節(jié)點流,處理流
| (抽象基類) | 字節(jié)流 | 字符流 |
| 輸入流 | InputStream | Reader |
| 輸出流 | OutputStream | Writer |
Java的IO流共涉及40多個類,實際上非常規(guī)則,都是從如上4個抽象基類派生的。
由這四個類派生出來的子類名稱都是以其父類名作為子類名后綴。
字節(jié)流:以byte為單位傳輸
字符流:以char為單位傳輸
IO流體系
InputStream & Reader
-
InputStream 和 Reader 是所有輸入流的基類。
-
InputStream(典型實現(xiàn):FileInputStream)
-
int read()
-
int read(byte[] b)
-
int read(byte[] b, int off, int len)
-
-
Reader(典型實現(xiàn):FileReader)
-
int read()
-
int read(char [] c)
-
int read(char [] c, int off, int len)
-
-
程序中打開的文件 IO 資源不屬于內(nèi)存里的資源,垃圾回收機(jī)制無法回收該資源,所以應(yīng)該顯式關(guān)閉文件 IO 資源。
OutputStream & Writer
-
OutputStream 和 Writer 也非常相似:
-
void write(int b/int c);
-
void write(byte[] b/char[] cbuf);
-
void write(byte[] b/char[] buff, int off, int len);
-
void flush();
-
void close();?需要先刷新,再關(guān)閉此流
-
-
因為字符流直接以字符作為操作單位,所以 Writer 可以用字符串來替換字符數(shù)組,即以 String 對象作為參數(shù)
-
void write(String str);
-
void write(String str, int off, int len);
-
文件流
讀取文件
1.建立一個流對象,將已存在的一個文件加載進(jìn)流。
-
FileReader fr = new FileReader("Test.txt");
2.創(chuàng)建一個臨時存放數(shù)據(jù)的數(shù)組。
-
char[] ch = new char[1024];
3.調(diào)用流對象的讀取方法將流中的數(shù)據(jù)讀入到數(shù)組中。
-
fr.read(ch);
寫入文件
1.創(chuàng)建流對象,建立數(shù)據(jù)存放文件
-
FileWriter fw = new FileWriter("Test.txt");
2.調(diào)用流對象的寫入方法,將數(shù)據(jù)寫入流
-
fw.write("text");
3.關(guān)閉流資源,并將流中的數(shù)據(jù)清空到文件中。
-
fw.close();
注意點:
-
定義文件路徑時,注意:可以用"/"或者"\\"。File.separator()
-
在寫入一個文件時,如果目錄下有同名文件將被覆蓋。
-
在讀取文件時,必須保證該文件已存在,否則出異常。
處理流之一:緩沖流
-
為了提高數(shù)據(jù)讀寫的速度,Java API提供了帶緩沖功能的流類,在使用這些流類時,會創(chuàng)建一個內(nèi)部緩沖區(qū)數(shù)組
-
根據(jù)數(shù)據(jù)操作單位可以把緩沖流分為:
-
BufferedInputStream 和 BufferedOutputStream
-
BufferedReader 和 BufferedWriter
-
緩沖流要"套接"在相應(yīng)的節(jié)點流之上,對讀寫的數(shù)據(jù)提供了緩沖的功能,提高了讀寫的效率,同時增加了一些新的方法
-
對于輸出的緩沖流,寫出的數(shù)據(jù)會先在內(nèi)存中緩存,使用flush()將會使內(nèi)存中的數(shù)據(jù)立刻寫出
?
處理流之二:轉(zhuǎn)換流
-
轉(zhuǎn)換流提供了在字節(jié)流和字符流之間的轉(zhuǎn)換
-
Java API提供了兩個轉(zhuǎn)換流:
-
InputStreamReader和OutputStreamWriter
-
-
字節(jié)流中的數(shù)據(jù)都是字符時,轉(zhuǎn)成字符流操作更高效。
InputStreamReader
-
用于將字節(jié)流中讀取到的字節(jié)按指定字符集解碼成字符。需要和InputStream"套接"。
-
構(gòu)造方法
-
public InputStreamReader(InputStream in)
-
public InputSreamReader(InputStream in,String charsetName)
如: Reader isr = new
InputStreamReader(System.in,"ISO5334_1");//指定字符集
OutputStreamWriter
-
用于將要寫入到字節(jié)流中的字符按指定字符集編碼成字節(jié)。需要和OutputStream"套接"。
-
構(gòu)造方法
-
public OutputStreamWriter(OutputStream out)
-
public OutputStreamWriter(OutputStream out,String charsetName)
?
補(bǔ)充:字符編碼
-
編碼表的由來
計算機(jī)只能識別二進(jìn)制數(shù)據(jù),早期由來是電信號。為了方便應(yīng)用計算機(jī),讓它可以識別各個國家的文字。就將各個國家的文字用數(shù)字來表示,并一一對應(yīng),形成一張表。這就是編碼表。
-
常見的編碼表
-
ASCII:美國標(biāo)準(zhǔn)信息交換碼。
-
用一個字節(jié)的7位可以表示。
-
-
ISO8859-1:拉丁碼表。歐洲碼表
-
用一個字節(jié)的8位表示。
-
-
GB2312:中國的中文編碼表。
-
GBK:中國的中文編碼表升級,融合了更多的中文文字符號。
-
Unicode:國際標(biāo)準(zhǔn)碼,融合了多種文字。
-
所有文字都用兩個字節(jié)來表示,Java語言使用的就是unicode
-
-
UTF-8:最多用三個字節(jié)來表示一個字符。
-
編碼:字符串à字節(jié)數(shù)組
-
解碼:字節(jié)數(shù)組à字符串
-
轉(zhuǎn)換流的編碼應(yīng)用
-
可以將字符按指定編碼格式存儲。
-
可以對文本數(shù)據(jù)按指定編碼格式來解讀。
-
指定編碼表的動作由構(gòu)造器完成。
處理流之三:標(biāo)準(zhǔn)輸入輸出流
-
System.in和System.out分別代表了系統(tǒng)標(biāo)準(zhǔn)的輸入和輸出設(shè)備
-
默認(rèn)輸入設(shè)備是鍵盤,輸出設(shè)備是顯示器
-
System.in的類型是InputStream
-
System.out的類型是PrintStream,其是OutputStream的子類FilterOutputStream 的子類
-
通過System類的setIn,setOut方法對默認(rèn)設(shè)備進(jìn)行改變。
-
public static void?setIn(InputStream?in)
-
public static void?setOut(PrintStream?out)
-
處理流之四:打印流(了解)
-
在整個IO包中,打印流是輸出信息最方便的類。
-
PrintStream(字節(jié)打印流)和PrintWriter(字符打印流)
-
提供了一系列重載的print和println方法,用于多種數(shù)據(jù)類型的輸出
-
PrintStream和PrintWriter的輸出不會拋出異常
-
PrintStream和PrintWriter有自動flush功能
-
System.out返回的是PrintStream的實例
-
?
處理流之五:數(shù)據(jù)流(了解)
-
為了方便地操作Java語言的基本數(shù)據(jù)類型的數(shù)據(jù),可以使用數(shù)據(jù)流。
-
數(shù)據(jù)流有兩個類:(用于讀取和寫出基本數(shù)據(jù)類型的數(shù)據(jù))
-
DataInputStream?和?DataOutputStream
-
分別"套接"在 InputStream 和 OutputStream 節(jié)點流上
-
-
DataInputStream中的方法
boolean readBoolean()????????byte readByte()
char readChar()????????????float readFloat()
double readDouble()????????short readShort()
long readLong()????????????int readInt()
String readUTF() void readFully(byte[] b)
-
DataOutputStream中的方法
-
將上述的方法的read改為相應(yīng)的write即可。
?
處理流之六:對象流
-
ObjectInputStream和OjbectOutputSteam
-
用于存儲和讀取對象的處理流。它的強(qiáng)大之處就是可以把Java中的對象寫入到數(shù)據(jù)源中,也能把對象從數(shù)據(jù)源中還原回來。
-
序列化(Serialize):用ObjectOutputStream類將一個Java對象寫入IO流中
-
反序列化(Deserialize):用ObjectInputStream類從IO流中恢復(fù)該Java對象
-
ObjectOutputStream和ObjectInputStream不能序列化static和transient修飾的成員變量
對象的序列化
-
對象序列化機(jī)制允許把內(nèi)存中的Java對象轉(zhuǎn)換成平臺無關(guān)的二進(jìn)制流,從而允許把這種二進(jìn)制流持久地保存在磁盤上,或通過網(wǎng)絡(luò)將這種二進(jìn)制流傳輸?shù)搅硪粋€網(wǎng)絡(luò)節(jié)點。當(dāng)其它程序獲取了這種二進(jìn)制流,就可以恢復(fù)成原來的Java對象
-
序列化的好處在于可將任何實現(xiàn)了Serializable接口的對象轉(zhuǎn)化為字節(jié)數(shù)據(jù),使其在保存和傳輸時可被還原
-
序列化是 RMI(Remote Method Invoke – 遠(yuǎn)程方法調(diào)用)過程的參數(shù)和返回值都必須實現(xiàn)的機(jī)制,而 RMI 是 JavaEE 的基礎(chǔ)。因此序列化機(jī)制是 JavaEE 平臺的基礎(chǔ)
-
如果需要讓某個對象支持序列化機(jī)制,則必須讓其類是可序列化的,為了讓某個類是可序列化的,該類必須實現(xiàn)如下兩個接口之一:
-
Serializable
-
Externalizable
-
-
凡是實現(xiàn)Serializable接口的類都有一個表示序列化版本標(biāo)識符的靜態(tài)變量:
-
private static final long serialVersionUID;
-
serialVersionUID用來表明類的不同版本間的兼容性
-
如果類沒有顯示定義這個靜態(tài)變量,它的值是Java運(yùn)行時環(huán)境根據(jù)類的內(nèi)部細(xì)節(jié)自動生成的。若類的源代碼作了修改,serialVersionUID 可能發(fā)生變化。故建議,顯示聲明
-
-
顯示定義serialVersionUID的用途
-
希望類的不同版本對序列化兼容,因此需確保類的不同版本具有相同的serialVersionUID
-
不希望類的不同版本對序列化兼容,因此需確保類的不同版本具有不同的serialVersionUID
-
使用對象流序列化對象
-
若某個類實現(xiàn)了 Serializable 接口,該類的對象就是可序列化的:
-
創(chuàng)建一個 ObjectOutputStream
-
調(diào)用 ObjectOutputStream 對象的 writeObject(對象) 方法輸出可序列化對象。注意寫出一次,操作flush()
-
-
反序列化
-
創(chuàng)建一個 ObjectInputStream
-
調(diào)用 readObject() 方法讀取流中的對象
-
-
強(qiáng)調(diào):如果某個類的字段不是基本數(shù)據(jù)類型或 String 類型,而是另一個引用類型,那么這個引用類型必須是可序列化的,否則擁有該類型的 Field 的類也不能序列化
序列化:將對象寫入到磁盤或者進(jìn)行網(wǎng)絡(luò)傳輸。
要求對象必須實現(xiàn)序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("test3.txt"));Person p = new Person("韓梅梅",18,"中華大街",new Pet());oos.writeObject(p);oos.flush();oos.close();//反序列化:將磁盤中的對象數(shù)據(jù)源讀出。ObjectInputStream ois = new ObjectInputStream(new FileInputStream("test3.txt"));Person p1 = (Person)ois.readObject();System.out.println(p1.toString());ois.close();RandomAccessFile 類
-
RandomAccessFile 類支持 "隨機(jī)訪問" 的方式,程序可以直接跳到文件的任意地方來讀、寫文件
-
支持只訪問文件的部分內(nèi)容
-
可以向已存在的文件后追加內(nèi)容
-
-
RandomAccessFile 對象包含一個記錄指針,用以標(biāo)示當(dāng)前讀寫處的位置。RandomAccessFile 類對象可以自由移動記錄指針:
-
long getFilePointer():獲取文件記錄指針的當(dāng)前位置
-
void seek(long pos):將文件記錄指針定位到 pos 位置
-
-
構(gòu)造器
-
public?RandomAccessFile(File?file,?String?mode)
-
public?RandomAccessFile(String?name,?String?mode)
-
-
創(chuàng)建 RandomAccessFile 類實例需要指定一個 mode 參數(shù),該參數(shù)指定 RandomAccessFile 的訪問模式:
-
r: 以只讀方式打開
-
rw:打開以便讀取和寫入
-
rwd:打開以便讀取和寫入;同步文件內(nèi)容的更新
-
rws:打開以便讀取和寫入;同步文件內(nèi)容和元數(shù)據(jù)的更新
-
讀取文件內(nèi)容
RandomAccessFile raf = new RandomAccessFile("test.txt", "rw");????raf.seek(5);byte [] b = new byte[1024];int off = 0;int len = 5;raf.read(b, off, len);String str = new String(b, 0, len);System.out.println(str);raf.close();寫入文件內(nèi)容
RandomAccessFile raf = new RandomAccessFile("test.txt", "rw");raf.seek(5);//先讀出來String temp = raf.readLine();raf.seek(5);raf.write("xyz".getBytes());raf.write(temp.getBytes());raf.close();?
流的基本應(yīng)用小節(jié)
-
流是用來處理數(shù)據(jù)的。
-
處理數(shù)據(jù)時,一定要先明確數(shù)據(jù)源,與數(shù)據(jù)目的地
-
數(shù)據(jù)源可以是文件,可以是鍵盤。
-
數(shù)據(jù)目的地可以是文件、顯示器或者其他設(shè)備。
-
-
而流只是在幫助數(shù)據(jù)進(jìn)行傳輸,并對傳輸?shù)臄?shù)據(jù)進(jìn)行處理,比如過濾處理、轉(zhuǎn)換處理等。
-
字節(jié)流-緩沖流(重點)
-
輸入流InputStream-FileInputStream-BufferedInputStream
-
輸出流OutputStream-FileOutputStream-BufferedOutputStream
-
字符流-緩沖流(重點)
-
輸入流Reader-FileReader-BufferedReader
-
輸出流Writer-FileWriter-BufferedWriter
-
轉(zhuǎn)換流
-
InputSteamReader和OutputStreamWriter
-
對象流ObjectInputStream和ObjectOutputStream(難點)
-
序列化
-
反序列化
-
隨機(jī)存取流RandomAccessFile(掌握讀取、寫入)
最后
作為過來人,小編是整理了很多進(jìn)階架構(gòu)視頻資料、面試文檔以及PDF的學(xué)習(xí)資料,針對上面一套系統(tǒng)大綱小編也有對應(yīng)的相關(guān)進(jìn)階架構(gòu)視頻資料,如’確定好自己未來的道路或者想學(xué)習(xí)提升自己技術(shù)棧、技術(shù)知識的小伙伴們可以點擊這里來獲取免費(fèi)學(xué)習(xí)資料提升自己(全套面試文檔、PDF、進(jìn)階架構(gòu)視頻)
總結(jié)
以上是生活随笔為你收集整理的面试官提出的Io问题 如何去做解答呢?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于Python对Lending Clu
- 下一篇: 部署静态页面到腾讯云服务器