1、Java編碼基礎
對于Java文件中,是采用的雙字節編碼utf-16be;
其中,中文占用2個字節,英文占用2個字節;
對于文本文件,實際上就是字節序列;可以是任意編碼的字節序列;
如果我們在中文機器上直接創建文本文件,那么該文本文件只認識ANSI編碼;對于在該機器上創建的文件,該系統只會認識ANSI編碼文件,其他類型編碼的會識別成亂碼;而對于在其他器件上創建的編碼格式復制到該機器上時,該機器是能夠識別的;但是如果是直接將文本文件里面的內容復制粘貼到該機器中新建的文件中時,機器會自動進行轉換,而不會出現亂碼。
utf-8中一個中文占3個字節
gbk中一個中文占2個字節
2、file類中常用的API
java.io.File類用于表示文件(或者 目錄);
File類只用于表示文件(目錄)的信息(名稱、大小等),不能用于文件內容的訪問;
file類的構造函數類型;File file=new File("E:\\javaio");或者File file1=new File("e:"+File.separator); ?其中,由于Java中“\”表示轉義字符,所以要用雙斜杠\\來表示文件夾目錄,或者用一個“/”也行;另外一種構造方法的File.separator為設置分隔符,無論任何系統,都能夠識別該分隔符表示;
判斷是否是一個目錄或者文件:file.isDirectory();或者file.isFile();
file文件是否存在:file.exists();
如果不存在,則創建該file文件:file.mkdir(); 創建多級目錄:file.mkdirs();
刪除file文件:file.delete();
當直接打印“file”,則打印的是file.toString()的內容,即目錄,而不是file文件內部的內容;此時該方法也可以使用“獲取絕對路徑”的方法:file.getAbsolutePath();
獲取文件的名字:file.getName();獲取目錄文件最后的目錄名;如果是一個文件的名字時,該方法得到的是具體文件的名字;
父目錄:file.getParent(); 或者 file.getParentFile();
3、常用函數
list()方法用于列出當前目錄下的子目錄和文件,返回的是字符串數組(直接子目錄的名稱,不包含子目錄里面的內容)
如果要遍歷子目錄下的內容就需要構造File對象做遞歸操作,File提供了直接返回File對象的API;File[] files=dir.listFiles();//返回的是直接子目錄(文件)的抽象;
4、RandomAccessFile 隨機獲取文件(對文件的內容進行操作)
是Java提供的對文件內容的訪問,既可以讀文件,也可以寫文件;并且該類型還支持隨機訪問文件,可以訪問文件的任意位置;
1)Java文件模型:在硬盤上的文件是byte byte byte存儲的,是數據的集合;
2)打開文件:有兩種模式“rw” “r”(只讀);
RandomAccessFile raf = new RandomAccessFile(file, "rw");指定要打開的文件,以及讀取的方式;
因為是隨機訪問文件,所以內部還包含有一個文件指針;打開文件時,指針在開始的位置,pointer = 0;
3)寫方法:raf.write(int); 內部可以寫一個整數或者其他的;write只能寫一個字節(后八位),同時指針指向下一個位置,準備再次寫入;
4)讀方法:int b = raf.read(); 從指針所在的位置開始讀一個字節,將該字節轉化成整數;
5)文件讀寫完成以后一定要關閉:
5、IO流(輸入流、輸出流)
分別有字節流、字符流
《1》字節流
inputstream和outputstream的相關子類
如:
1)FileInputStream:具體實現了在文件上讀取數據;
2)FileOutputStream:具體實現了向文件中寫出byte數據的方法;
3)DataInputStream / DataOutputStream:是對“流”功能的擴展,可以更加方便地讀取int、long、字符等類型數據;
4)DataOutputStream中的方法有:writeInt() / writeDouble() / writeUTF();這些方法實際上是將OutputStream中的方法進行了封裝,從而可以直接寫出int等類型;
5)BufferedInputStream / BufferedOutputStream:這兩個流類為IO提供了帶緩沖區的操作,一般打開文件進行寫入或讀取操作時,都會加上緩沖,這種流模式提高了IO的性能;
對于上述各種IO流的比較:當從應用程序中把輸入放入文件中時,相當于將一缸水倒入到另一個缸中:
FileOutputStream中write()方法相當于一滴一滴地把水“轉移”過去;
DataOutputStream中的writeXxx()方法會方便一些,相當于一瓢一瓢地把水“轉移”過去;
BufferedOutputStream中的write方法更方便,相當于一瓢一瓢地先放入桶中,再從桶中倒入到另一個缸中;
《2》字符流——操作的基本都是文本文件
字符流的基本實現:
InputStreamReader:完成byte流解析為char流,按照編碼規則解析;
OutputStreamWriter:提供char流到byte流的編碼,按照編碼規則處理;
FileReader/ FileWriter:可以直接對文件進行操作;這兩個類無法識別其他類型的編碼格式,在自己的項目中,只能識別自己的編碼格式,所以在編碼的時候一定要統一成項目的編碼格式;
BufferedReader/ BufferedWriter 字符流的過濾器 ?每次可以讀、寫一行readLine();
PrintWriter:向文本輸出流打印對象的格式化表示形式,方便打印輸出。
《3》對象的序列化和反序列化問題
4)transient 關鍵字修飾的變量不會進行JVM默認的序列化操作,但是可以自己完成這個元素的序列化;
在某些情況下能夠提高性能(不用序列化的就不序列化,需要序列化的自行序列化,從而提高性能);
4)序列化時,當父類實現了序列化接口,則子類也必然是實現了序列化,所以子類不用再實現序列化接口,只用繼承父類即可;(子類會遞歸調用父類的構造函數,無論父類是否實現了序列化接口)
5)反序列化時,當對子類對象進行反序列化操作時,如果其父類沒有實現序列化接口,那么其父類的構造函數將被調用;如果父類實現了序列化接口,則該父類的構造函數將看不到被調用,即子類不會遞歸調用父類的構造函數(調用的前提是該父類沒有實現序列化接口);
因為當子類實現了序列化接口時,相當于對于這個子類中的對象已經可以從存儲的那個文件中直接讀取了,則在反序列化時,就不會調用父類的構造函數;而當子類不能進行序列化時,那么其父類的構造函數會被調用,那么在反序列化時,其父類對象相應地就將會被調用;