java之IO處理,javaio
File檔案基礎
檔案與目錄抽象路徑名稱的表示,其構造方法有四個
File(File parent,String child):從抽象父目錄下建立一個File執行個體。
File(String parent,String child):從父目錄下建立一個File執行個體。
File(String pathname):從指定路徑下建立一個File執行個體。
File(URI path):從URI轉換成抽象路徑下建立一個File執行個體。
listFiles()方法:返回一個抽象路徑名數組,這些抽象路徑名表示目錄中的子項(檔案或目錄)
File file = new File("/home/colin");File[] childs = file.listFiles();
listFiles(FileFilter filter):FileFilter是抽象路徑名的過濾器,可以用於返回過濾器要求的子目錄
File file = new File("/home/colin");//有沒有考慮過,java中不允許實現介面執行個體,但是在匿名內部類中卻實現了介面,比如這個FileFilter介面//實際上如果查看編譯後的代碼(會發現編譯後的代碼中有一個class檔案,這個class實現了這個介面,並重寫了這個介面的方法)//所以這是一種虛擬執行個體化介面,或者理解為間接執行個體化介面。File[] childs = file.listFiles(new FileFilter() {@Overridepublic boolean accept(File pathname) {return pathname.getName().startsWith(".");}});
還有一個listFiles(FilenameFileter filter):FilenameFile用於檢測指定檔案是否包含在特定目錄下
其他API相對簡單了,擷取檔案狀態、建立刪除檔案
RandomAccessFile隨機讀寫檔案
File 執行個體只涉及到對檔案的操作,java提供了可以對檔案隨機訪問的操作,訪問包括讀和寫操作,這種實現是基於指標的操作。
兩個構造方法:
RandomAccessFile(File name,String model)
RandomAccessFile(String name,String model)
model指定的是對檔案隨機訪問操作模式,有兩種模式分別是唯讀模式和讀寫入模式,"r"表示檔案的訪問是唯讀,"rw"表示讀和寫入模式。
RandomAccessFile file = new RandomAccessFile("/home/colin","rw");
寫資料:
write(byte[] b):將指定自己數組b寫到隨機讀寫檔案中,寫到指標的位置
write(byte[] b,int off,int len):指定了起始位置和長度
write(int n):將n的低八位寫到檔案中去
他還有寫入特定特性的方法:writeBoolean(boolean b)、writeInt(int n)、writeDouble(double v)、writeChart(chart c)、writeCharts(String s)、writeByte(int n)、writeBytes(String s)、writeFloat(Float t)等
讀資料:
int read():讀取1byte(8位)放到int的低八位中,高24為為0。如果讀到-1,說明讀到了檔案的末尾
int read(byte[] b):最多讀取b.length個位元組到數組中,返回值為實際讀取到的位元組量
int read(byte[] b,int off, int length):指定讀取數組的起始位置和讀取長度
相應的還有讀取特定類型資料的read
readBoolean()、readFloat()等等,特別還有一個readLine()讀取當前位置的一行
這些都是從當前指標位置開始讀取的
釋放關聯的資源:void close()
擷取當前RandomAccessFile的指標:long getFilePoint(),以位元組為單位,比如如果一個Int是4位
移動當前指標位置:void seek(long pos)
跳過n個位元組:int sikpBytes(int n):返回跳過的實際位元組數,n為負數不跳過任何位元組
RandomAccessFile file = null;try {file = new RandomAccessFile("/home/colin/test.txt","rw");//byte[] b = "this is sample RandomAccessFile".getBytes();//file.read(b);byte[] b = new byte[10];while(file.read(b) >0){System.out.println(new String(b));System.out.println(file.getFilePointer());//擷取檔案指標file.skipBytes(1);//每次讀取跳過一個位元組}} catch (FileNotFoundException e) {e.printStackTrace();}finally{if(file != null)file.close();}
基本IO
輸入是指從外界進入程式方向,即當我們需要讀取資料的時候,使用輸入。
輸出是指從程式發送到外界方向,通常我們需要寫出資料到外界,所以輸出是用來寫資料的。
流的分類
根據單位:位元組流(8bit,圖片視頻等)和字元流(16bit,文本)
根據角色:節點流(直接作用在文本上的流,直接與特定的地方(磁碟、記憶體)相連)和處理流(在節點流外層的流,是對一個已經存在流的串連和封裝,在所封裝的流的功能上實現資料的讀寫)
java中40多種流都是從4個基類派生出來的
位元組流 字元流
輸入:InputStream Reader
輸出:OutputStream Writer
InputStream和OutputStream
二者都是位元組流的抽象基類,定義了基本的read和write方法,read()、read(byte[] a,int off,int length)、read(byte[] b)、write(int b)、write(byte[] b)、write(byte[] b,int off ,int len)
Reader和Writer
reader和writer都是字元流的抽象基類,定義了讀取字元的read和write。read()、read(char[] cbuf)、read(char[] cbuf,int off, int len)、write(char c)、write(char[] cbuf)、cbuf(cbuf,int off ,int len)
檔案流
檔案位元組流:
FileOutputStream可以使用以下幾種方法構造:
FileOUtputStream(File file)
FileOutputStream(String name)
指定寫入的檔案,如果該檔案存在的化會清除該檔案上面的內容
FileOutputStream(File file,boolean append)
FileOutputStream(String name,boolean append)
如果指定append參數為true,則如果寫入的檔案存在,是以追加的方式進行寫入的
FileInputStream可以使用以下方法構造:
FileInputStream(File file)
FileOutputStream(String name)
檔案位元組流實現了inputStream和outputStream的基本read和write
注意如果讀取的時候返回-1,則說明讀取到了EOF
利用檔案流實現檔案的複製:
File file1 = new File("/home/colin/hello.py");File file2 = new File("/home/colin/hello2.py");FileInputStream input = null;FileOutputStream output = null;try {input = new FileInputStream(file1);output = new FileOutputStream(file2);byte[] b = new byte[10];int len = -1;while((len=input.read(b))!=-1){output.write(b, 0, len);}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally{try { //先關輸入資料流,再關輸出資料流 if(inputput != null)inputput.close();if(output != null)output.close();} catch (IOException e) {e.printStackTrace();}}
FileReader和FileWriter與FileInputStream和FileOutputStream使用方式一樣。
緩衝流
BufferedInputStream原理:緩衝位元組輸入資料流,內部維護一個緩衝區,該流會儘可能一次性讀取若干位元組到緩衝區,然後逐一返回知道緩衝區中的資料被全部讀取完畢,從而減少讀取次數,提高讀取效率,BIS就是一個處理流,該流提供了緩衝功能。他還提供了mark、reset和skip方法
提供的構造方法:
BufferedInputStream(InputStream input)
BufferedInputStream(InputStream input,int size):size指定緩衝區大小
BufferedOutputStream原理:緩衝輸出資料流,內部維護一個緩衝區,每當向該流寫入資料的時候,都會現將資料存放區緩衝區中,當緩衝區已滿的時候,緩衝流會將資料一次性全部寫出。
提供的構造方法:
BufferedOutputStream(OutputStream out)
BufferedOutputStream(OutputStream out,int size):指定緩衝區大小
BufferedOutputStream只提供了write和flush()方法,flush()清空緩衝區,將緩衝區中的資料強制寫入。
利用緩衝流實現檔案複製:
BufferedInputStream bis = null;BufferedOutputStream bos = null;try {bis = new BufferedInputStream(new FileInputStream(new File("/home/colin/hello.py")));bos = new BufferedOutputStream(new FileOutputStream(new File("/home/colin/hello3.py")));int len = -1;byte[] b = new byte[10];while((len=bis.read(b)) !=-1){bos.write(b, 0, len);}bos.flush();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally{try {//先關輸入資料流,再關輸出資料流if(bis != null)bis.close();if(bos != null)bos.close();} catch (IOException e) {e.printStackTrace();}}
BufferedReader和BufferedWriter與BufferedInputStream和BufferedOutputStream實現原理是一樣的,但是BufferedWriter提供了newLine(),寫入分行符號的方法物件流程
對象序列化:對象存在記憶體中,有時候需要將對象儲存到磁碟上,或者將對象進行傳輸等這樣的操作。這時候需要將對象轉化為一個位元組序列,這個過程稱為對象序列化。
對象還原序列化:有時候需要將位元組序列轉化成為對應的對象,這個過程成為對象的還原序列化。
ObjectOutputStream:用來將對象進行序列化的輸出資料流
提供的構造方法:
ObjectOutputStream()
ObjectOutputStream(OutputStream out)
使用其write方法,將對象轉化成為一個位元組序列後寫出,write方法提供了諸如writeInt()等此類方法。
ObjectInputStream:用來將對象還原序列化
提供的構造方法:
ObjectInputstream()
ObjectInputStream(InputStream input)
使用其提供的readObject()方法,讀取位元組並轉化為對應的對象
這個整體思路是要對對象進行傳遞,需要將對象轉換成為位元組流以便傳輸,所以首先通過ObjectOutputStream進行寫入,將對象寫成位元組進行傳輸。傳遞到目標位置後需要讀取,這時候將傳輸的位元組轉換成為對象。
如果使用ObjectOutputStream進行序列化寫入,需要序列化對象實現Serializable介面,該介面並沒有任何方法只是序列化標誌。通常實現該介面需要給出一個serialVersionUID,表明該類版本,若不顯示聲明編譯器也會經過計算給出一個serialVersionUID,但是不同編譯器實現有所不同,所以如果想要跨平台,都應該顯示聲明版本號碼。當類的對象序列化到磁碟上面,之後隨之需求改變,改變了類的屬性,那麼還原序列化就會出現InvalidClassException,這樣就會造成不相容問題。但當serialVersionUID相同時,會將不一樣的Field以type的預設值還原序列化,可以避開不相容問題
transient關鍵詞:當我們對對對象進行序列化後,得帶的位元組序列往往比較大,有時我們在對一個對象進行序列化時可以忽略某些不必要的屬性,從而對序列化後得到的位元組序列瘦身,可以將其聲明為transient,這樣這些屬性在序列化時會被忽略。
執行個體:
/* *構造Emp類,對其對象進行序列化與還原序列化 */public class Emp implements Serializable {private static final long serialVersionUID = 1L;private String name;private int age;private double salary;private transient String description; //使用transient修飾,在還原序列化時輸出null public Emp(String name,int age,double salary,String description){this.name = name;this.age = age;this.salary = salary;this.description = description;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}@Overridepublic String toString() {return "Emp [name="+name+",age="+age+",salary="+salary+",description="+description+"]";}}/* * 將Emp對象序列化,並且儲存 */ public static void testOos(){ ObjectOutputStream oos = null; try { FileOutputStream fos = new FileOutputStream(new File("/home/colin/oos.obj")); oos = new ObjectOutputStream(fos); Emp emp = new Emp("colin", 23, 13000, "I want you!!!"); oos.writeObject(emp); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ try { if(oos != null) oos.close(); } catch (IOException e) { e.printStackTrace(); } } } /* * 將儲存的Emp對象反序列輸出 */ public static void testOis(){ ObjectInputStream ois = null; try { FileInputStream fis = new FileInputStream(new File("/home/colin/oos.obj")); ois = new ObjectInputStream(fis); Emp emp = (Emp)ois.readObject(); System.out.println(emp.getName()+","+emp.getAge()+","+emp.getSalary()+","+emp.getDescription()); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } }
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。