java.io.File類:檔案和檔案目錄路徑的抽象表示形式,與平臺無關
File 能新建、刪除、重新命名檔案和目錄,但 File 不能存取檔案內容本身。如果需要存取檔案內容本身,則需要使用輸入/輸出流。
想要在Java程式中表示一個真實存在的檔案或目錄,那麼必須有一個File對 象,但是Java程式中的一個File物件,可能沒有一個真實存在的檔案或目錄。
File物件可以作爲參數傳遞給流的構造器
public File(String pathname)
以pathname爲路徑建立File物件,可以是絕對路徑或者相對路徑,如果pathname是相對路徑,則預設的當前路徑在系統屬性user.dir中儲存。
>絕對路徑:是一個固定的路徑,從碟符開始
>相對路徑:是相對於某個位置開始
public File(String parent,String child)
以parent爲父路徑,child爲子路徑建立File物件。
public File(File parent,String child)
根據一個父File物件和子檔案路徑建立File物件
路徑中的每級目錄之間用一個路徑分隔符隔開。
路徑分隔符和系統有關:
>windows和DOS系統預設使用「\」來表示
>UNIX和URL使用「/」來表示
Java程式支援跨平臺執行,因此路徑分隔符要慎用。
爲了解決這個隱患,File類提供了一個常數:public static final String separator。根據操作系統,動態的提供分隔符。
舉例:
File file1 = new File("d:\\study\\info.txt");
File file2 = new File("d:" + File.separator + "study" + File.separator + "info.txt");
File file3 = new File("d:/study");
File類的獲取功能
public String getAbsolutePath():獲取絕對路徑
public String getPath() :獲取路徑
public String getName() :獲取名稱
public String getParent():獲取上層檔案目錄路徑。若無,返回null
public long length() :獲取檔案長度(即:位元組數)。不能獲取目錄的長度。
public long lastModified() :獲取最後一次的修改時間,毫秒值
public String[] list() :獲取指定目錄下的所有檔案或者檔案目錄的名稱陣列
public File[] listFiles() :獲取指定目錄下的所有檔案或者檔案目錄的File陣列
File類的重新命名功能
File類的判斷功能
public boolean isDirectory():判斷是否是檔案目錄
public boolean isFile() :判斷是否是檔案
public boolean exists() :判斷是否存在
public boolean canRead() :判斷是否可讀
public boolean canWrite() :判斷是否可寫
public boolean isHidden() :判斷是否隱藏
File類的建立功能
public boolean createNewFile() :建立檔案。若檔案存在,則不建立,返回false
public boolean mkdir() :建立檔案目錄。如果此檔案目錄存在,就不建立了。
如果此檔案目錄的上層目錄不存在,也不建立。
public boolean mkdirs() :建立檔案目錄。如果上層檔案目錄不存在,一併建立
注意事項:如果你建立檔案或者檔案目錄沒有寫碟符路徑,那麼,預設在專案路徑下。
File類的刪除功能
public boolean delete():刪除檔案或者資料夾
刪除注意事項:Java中的刪除不走回收站。要刪除一個檔案目錄,請注意該檔案目錄內不能包含檔案或者檔案目錄
I/O是Input/Output的縮寫, I/O技術是非常實用的技術,用於處理裝置之間的數據傳輸。如讀/寫檔案,網路通訊等。
Java程式中,對於數據的輸入/輸出操作以「流(stream)」 的方式進行。
java.io包下提供了各種「流」類和介面,用以獲取不同種類的數據,並通過標準的方法輸入或輸出數據。
輸入input:讀取外部數據(磁碟、光碟等儲存裝置的數據)到程式(記憶體)中。
輸出output:將程式(記憶體)數據輸出到磁碟、光碟等儲存裝置中。
按操作數據單位不同分爲:位元組流(8 bit),字元流(16 bit)
按數據流的流向不同分爲:輸入流,輸出流
按流的角色的不同分爲:節點流,處理流
(抽象基礎類別) | 位元組流 | 字元流 |
---|---|---|
輸入流 | InputStream | Reader |
輸出流 | OutputStream | Writer |
Java的IO流共涉及40多個類,實際上非常規則,都是從如下4個抽象基礎類別派生的。
由這四個類派生出來的子類名稱都是以其父類別名作爲子類名後綴。
分類 | 位元組輸入流 | 位元組輸出流 | 字元輸入流 | 字元輸出流 |
---|---|---|---|---|
抽象基礎類別 | InputStream | OutputStream | Reader | Writer |
存取檔案 | FileInputStream | FileOutputStream | FileReader | FileWriter |
存取陣列 | ByteArrayInputStream | ByteArrayOutputStream | CharArrayReader | CharArrayWriter |
存取管道 | PipedInputStream | PipedOutputStream | PipedReader | PipedWriter |
存取字串 | StringReader | StringWriter | ||
緩衝流 | BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter |
轉換流 | InputStreamReader | InputStreamWriter | ||
物件流 | ObjectInputStream | ObjectOutputStream | ||
FilterInputStream | FilterOutputStream | FilterReader | FilterWriter | |
列印流 | PrintStream | PrintWriter | ||
退回輸入流 | PushbackInputStream | PushbackReader | ||
特殊流 | DataInputStream | DataOutputStream |
int read()
從輸入流中讀取數據的下一個位元組。返回 0 到 255 範圍內的 int 位元組值。如果因爲已經到達流末尾而沒有可用的位元組,則返回值 -1。
int read(byte[] b)
從此輸入流中將最多 b.length 個位元組的數據讀入一個 byte 陣列中。如果因爲已經到達流末尾而沒有可用的位元組,則返回值 -1。否則以整數形式返回實際讀取的位元組數。
int read(byte[] b, int off,int len)
將輸入流中最多 len 個數據位元組讀入 byte 陣列。嘗試讀取 len 個位元組,但讀取的位元組也可能小於該值。以整數形式返回實際讀取的位元組數。如果因爲流位於檔案末尾而沒有可用的位元組,則返回值 -1。
public void close() throws IOException
關閉此輸入流並釋放與該流關聯的所有系統資源。
int read()
讀取單個字元。作爲整數讀取的字元,範圍在 0 到 65535 之間 (0x00-0xffff)(2個位元組的Unicode碼),如果已到達流的末尾,則返回 -1
int read(char[] cbuf)
將字元讀入陣列。如果已到達流的末尾,則返回 -1。否則返回本次讀取的字元數。
int read(char[] cbuf,int off,int len)
將字元讀入陣列的某一部分。存到陣列cbuf中,從off處開始儲存,最多讀len個字元。如果已到達流的末尾,則返回 -1。否則返回本次讀取的字元數。
public void close() throws IOException
關閉此輸入流並釋放與該流關聯的所有系統資源。
將指定的位元組寫入此輸出流。write 的常規協定是:向輸出流寫入一個位元組。要寫入的位元組是參數 b 的八個低位。b 的 24 個高位將被忽略。 即寫入0~255範圍的。
void write(byte[] b)
將 b.length 個位元組從指定的 byte 陣列寫入此輸出流。write(b) 的常規協定是:應該與呼叫 write(b, 0, b.length) 的效果完全相同。
void write(byte[] b,int off,int len)
將指定 byte 陣列中從偏移量 off 開始的 len 個位元組寫入此輸出流。
public void flush()throws IOException
重新整理此輸出流並強制寫出所有緩衝的輸出位元組,呼叫此方法指示應將這些位元組立即寫入它們預期的目標。
public void close() throws IOException
關閉此輸出流並釋放與該流關聯的所有系統資源。
void write(int c)
寫入單個字元。要寫入的字元包含在給定整數值的 16 個低位中,16 高位被忽略。 即
寫入0 到 65535 之間的Unicode碼。
void write(char[] cbuf)
寫入字元陣列。
void write(char[] cbuf,int off,int len)
寫入字元陣列的某一部分。從off開始,寫入len個字元
void write(String str)
寫入字串。
void write(String str,int off,int len)
寫入字串的某一部分。
void flush()
重新整理該流的緩衝,則立即將它們寫入預期目標。
public void close() throws IOException
關閉此輸出流並釋放與該流關聯的所有系統資源。
讀取檔案
1.建立一個流物件,將已存在的一個檔案載入進流。
FileReader fr = new FileReader(new File(「Test.txt」));
2.建立一個臨時存放數據的陣列。
char[] ch = new char[1024];
3.呼叫流物件的讀取方法將流中的數據讀入到陣列中。
fr.read(ch);
4.關閉資源。
fr.close();
寫入檔案
1.建立流物件,建立數據存放檔案
FileWriter fw = new FileWriter(new File(「Test.txt」));
2.呼叫流物件的寫入方法,將數據寫入流
fw.write(「abc123」);
3.關閉流資源,並將流中的數據清空到檔案中。
fw.close();
注意
定義檔案路徑時,注意:可以用「/」或者「\」。
在寫入一個檔案時,如果使用構造器FileOutputStream(file),則目錄下有同名檔案將被覆蓋。
如果使用構造器FileOutputStream(file,true),則目錄下的同名檔案不會被覆蓋,在檔案內容末尾追加內容。
在讀取檔案時,必須保證該檔案已存在,否則報異常。
位元組流操作位元組,比如:.mp3,.avi,.rmvb,mp4,.jpg,.doc,.ppt
字元流操作字元,只能操作普通文字檔案。最常見的文字檔案:.txt,.java,.c,.cpp 等語言的原始碼。尤其注意.doc,excel,ppt這些不是文字檔案。
public class BufferedInputStream extends FilterInputStream{
private static int DEFAULT_BUFFER_SIZE = 8192;
}
緩衝流要「套接」在相應的節點流之上,根據數據操作單位可以把緩衝流分爲:
BufferedInputStream和BufferedOutputStream
BufferedReader和BufferedWriter
當讀取數據時,數據按塊讀入緩衝區,其後的讀操作則直接存取緩衝區
當使用BufferedInputStream讀取位元組檔案時,BufferedInputStream會一次性從檔案中讀取8192個(8Kb),存在緩衝區中,直到緩衝區裝滿了,才重新從檔案中讀取下一個8192個位元組陣列。
向流中寫入位元組時,不會直接寫到檔案,先寫到緩衝區中直到緩衝區寫滿,BufferedOutputStream纔會把緩衝區中的數據一次性寫到檔案裡。使用方法flush()可以強制將緩衝區的內容全部寫入輸出流
關閉流的順序和開啓流的順序相反。只要關閉最外層流即可,關閉最外層流也會相應關閉內層節點流
flush()方法的使用:手動將buffer中內容寫入檔案
如果是帶緩衝區的流物件的close()方法,不但會關閉流,還會在關閉流之前重新整理緩衝區,關閉後不能再寫出
轉換流提供了在位元組流和字元流之間的轉換
Java API提供了兩個轉換流:
InputStreamReader:將InputStream轉換爲Reader
OutputStreamWriter:將Writer轉換爲OutputStream
位元組流中的數據都是字元時,轉成字元流操作更高效。
很多時候我們使用轉換流來處理檔案亂碼問題。實現編碼和解碼的功能。
InputStreamReader
實現將位元組的輸入流按指定字元集轉換爲字元的輸入流。
需要和InputStream「套接」。
構造器
public InputStreamReader(InputStream in)
public InputSreamReader(InputStream in,String charsetName)
如: Reader isr = new InputStreamReader(System.in,」UTF-8」);
OutputStreamWriter
實現將字元的輸出流按指定字元集轉換爲位元組的輸出流。
需要和OutputStream「套接」。
構造器
public OutputStreamWriter(OutputStream out)
public OutputSreamWriter(OutputStream out,String charsetName)
System.in和System.out分別代表了系統標準的輸入和輸出裝置
預設輸入裝置是:鍵盤,輸出裝置是:顯示器
System.in的型別是InputStream
System.out的型別是PrintStream,其是OutputStream的子類FilterOutputStream 的子類
重定向:通過System類的setIn,setOut方法對預設裝置進行改變。
public static void setIn(InputStream in)
public static void setOut(PrintStream out)
實現將基本數據型別的數據格式轉化爲字串輸出
列印流:PrintStream和PrintWriter
>提供了一系列過載的print()和println()方法,用於多種數據型別的輸出
>PrintStream和PrintWriter的輸出不會拋出IOException異常
>PrintStream和PrintWriter有自動flush功能
>PrintStream 列印的所有字元都使用平臺的預設字元編碼轉換爲位元組。在需要寫入字元而不是寫入位元組的情況下,應該使用 PrintWriter 類。
>System.out返回的是PrintStream的範例
爲了方便地操作Java語言的基本數據型別和String的數據,可以使用數據流。
數據流有兩個類:(用於讀取和寫出基本數據型別、String類的數據)
DataInputStream和 DataOutputStream
分別「套接」在InputStream 和OutputStream子類的流上
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改爲相應的write即可。
ObjectInputStream和OjbectOutputSteam
用於儲存和讀取基本數據型別數據或物件的處理流。它的強大之處就是可以把Java中的物件寫入到數據源中,也能把物件從數據源中還原回來。
序列化:用ObjectOutputStream類儲存基本型別數據或物件的機制 機製
反序列化:用ObjectInputStream類讀取基本型別數據或物件的機制 機製
ObjectOutputStream和ObjectInputStream不能序列化static和transient修飾的成員變數
物件序列化機制 機製允許把記憶體中的Java物件轉換成平臺無關的二進制流,從而允許把這種二進制流持久地儲存在磁碟上,或通過網路將這種二進制流傳輸到另一個網路節點。//當其它程式獲取了這種二進制流,就可以恢復成原來的Java物件
序列化的好處在於可將任何實現了Serializable介面的物件轉化爲位元組數據,使其在儲存和傳輸時可被還原
序列化是 RMI(Remote Method Invoke – 遠端方法呼叫)過程的參數和返回值都必須實現的機制 機製,而 RMI 是 JavaEE 的基礎。因此序列化機制 機製是JavaEE 平臺的基礎
如果需要讓某個物件支援序列化機制 機製,則必須讓物件所屬的類及其屬性是可序列化的,爲了讓某個類是可序列化的,該類必須實現如下兩個介面之一。否則,會拋出NotSerializableException異常
>Serializable
>Externalizable
凡是實現Serializable介面的類都有一個表示序列化版本識別符號的靜態變數:
>private static final long serialVersionUID;
>serialVersionUID用來表明類的不同版本間的相容性。簡言之,其目的是以序列化物件進行版本控制,有關各版本反序列化時是否相容。
>如果類沒有顯示定義這個靜態常數,它的值是Java執行時環境根據類的內部細節自動生成的。若類的範例變數做了修改,serialVersionUID 可能發生變化。故建議,顯式宣告。
簡單來說,Java的序列化機制 機製是通過在執行時判斷類的serialVersionUID來驗證版本一致性的。在進行反序列化時,JVM會把傳來的位元組流中的serialVersionUID與本地相應實體類的serialVersionUID進行比較,如果相同就認爲是一致的,可以進行反序列化,否則就會出現序列化版本不一致的異常。(InvalidCastException)
若某個類實現了 Serializable 介面,該類的物件就是可序列化的:
>建立一個ObjectOutputStream
>呼叫ObjectOutputStream物件的writeObject(物件)方法輸出可序列化物件
>注意寫出一次,操作lush()一次
反序列化
>建立一個ObjectInputStream
>呼叫readObject()方法讀取流中的物件
強調:如果某個類的屬性不是基本數據型別或 String 型別,而是另一個參照型別,那麼這個參照型別必須是可序列化的,否則擁有該型別的Field 的類也不能序列化
//序列化:將物件寫入到磁碟或者進行網路傳輸。
//要求物件必須實現序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(「data.txt"));
Person p = new Person("韓梅梅", 18, "中華大街", new Pet());
oos.writeObject(p);
oos.flush();
oos.close();
//反序列化:將磁碟中的物件數據源讀出。
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(「data.txt"));
Person p1 = (Person)ois.readObject();
System.out.println(p1.toString());
ois.close();
某個類的屬性不是基本數據型別或 String 型別,而是另一個參照型別,那麼這個參照型別必須是可序列化的,否則擁有該型別的Field 的類也不能序列化
//序列化:將物件寫入到磁碟或者進行網路傳輸。
//要求物件必須實現序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(「data.txt"));
Person p = new Person("韓梅梅", 18, "中華大街", new Pet());
oos.writeObject(p);
oos.flush();
oos.close();
//反序列化:將磁碟中的物件數據源讀出。
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(「data.txt"));
Person p1 = (Person)ois.readObject();
System.out.println(p1.toString());
ois.close();