Java程序設(shè)計(jì)-12-基本輸入輸出處理_第1頁(yè)
Java程序設(shè)計(jì)-12-基本輸入輸出處理_第2頁(yè)
Java程序設(shè)計(jì)-12-基本輸入輸出處理_第3頁(yè)
Java程序設(shè)計(jì)-12-基本輸入輸出處理_第4頁(yè)
Java程序設(shè)計(jì)-12-基本輸入輸出處理_第5頁(yè)
已閱讀5頁(yè),還剩49頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、Java程序設(shè)計(jì)第12章 基本I/O處理學(xué)習(xí)目標(biāo)理解流的概念,掌握I/O類體系理解文本流和字節(jié)流、節(jié)點(diǎn)流和加工流理解流的處理鏈構(gòu)造,熟悉常用加工流并能靈活應(yīng)用理解File,能夠利用File實(shí)例分析文件屬性和基本的文件操作掌握順序文件的讀/寫過程能夠應(yīng)用RandomAccessFile完成隨機(jī)文件訪問理解串行化,能夠定義可串行化的類,并實(shí)現(xiàn)對(duì)象的串行化存取12.1 流I/O的形式分為四種:控制臺(tái)(console, 如DOS窗口)。例如打印到顯示器/鍵盤讀入文件(file)讀/寫,以文件為讀/寫對(duì)象。網(wǎng)絡(luò)接口(TCP/UDP端口)讀/寫,例如,網(wǎng)上沖浪、網(wǎng)絡(luò)聊天、郵件發(fā)送。 程序(線程)間通信,例

2、如,數(shù)據(jù)傳輸。 12.1.1 什么是流 簡(jiǎn)單的說流就是一個(gè)傳送有序的字節(jié)序列。讀者更可以把它想象成為一個(gè)數(shù)據(jù)節(jié)點(diǎn)和程序之間建立起來的連接通道上的字節(jié)序列。換句話說,流就是對(duì)輸入數(shù)據(jù)源和輸出目的地的抽象表示。 下圖 流是輸入和輸出設(shè)備的抽象 當(dāng)把數(shù)據(jù)寫入流時(shí),該流被稱為輸出流。輸出流可以連接硬盤上的文件、網(wǎng)絡(luò)上的另一端等任何可以接收字節(jié)序列的設(shè)備。同樣可以把從中讀取數(shù)據(jù)的流稱為輸入流,輸入流連接的數(shù)據(jù)源可以是任何串行數(shù)據(jù)源,如磁盤文件、網(wǎng)絡(luò)另一端的信息發(fā)送程序、鍵盤等。12.1.2流的分類節(jié)點(diǎn)流可以直接和能夠提供輸入數(shù)據(jù)的數(shù)據(jù)源和接受數(shù)據(jù)的目的地建立直接的聯(lián)系加工流能夠改善應(yīng)用開發(fā)性能和效率的具

3、有特殊功能的I/O流,這些流可以對(duì)流進(jìn)行再處理表12-1 節(jié)點(diǎn)流字符流字節(jié)流FileReader,F(xiàn)ileWriterFileInputStream,F(xiàn)ileOutputStreamCharArrayReader,CharArrayWriterStringReader,StringWriterByteArrayInputStream,ByteArrayOutputStreamPipedReader,PipedWriter;PipedInputStream,PipedOutputStream表12-2 加工流功能字符流字節(jié)流緩沖BufferedReader,BufferedWriterBuffe

4、redInputStream,BufferedOutputStream字節(jié)流到字符流的轉(zhuǎn)換InputStreamReader,OutputStreamWriter連接SequenceInputStream對(duì)象串行化ObjectInputStream,ObjectOutputStream基本數(shù)據(jù)類型轉(zhuǎn)換DataInputStream,DataOutputStream計(jì)數(shù)LineNumberReader推回緩沖區(qū)PushbackReaderPushbackInputStream過濾FilterReader,F(xiàn)ilterWriterFilterInputStream,F(xiàn)ilterOutputStre

5、am打印PrintWriter PrintStream12.1.3輸入流的基本方法表12-3 InputStream的主要方法方法作用int read()從輸入流中讀取數(shù)據(jù)的下一個(gè)字節(jié)。int read(byte b)從輸入流中讀取一定數(shù)量的字節(jié),并將其存儲(chǔ)在緩沖區(qū)數(shù)組 b 中。int read(byte b, int off, int len)將輸入流中最多 len 個(gè)數(shù)據(jù)字節(jié)讀入 byte 數(shù)組。long skip(long n)跳過和丟棄此輸入流中數(shù)據(jù)的 n 個(gè)字節(jié)。表12-4 Reader的主要方法方法作用int read()從輸入流中讀取單個(gè)字符。int read(char cbuf

6、)從輸入流中讀取一定數(shù)量的字符,并將其存儲(chǔ)在緩沖區(qū)數(shù)組 cbuf 中。int read(char cbuf, int off, int len)將輸入流中最多 len 個(gè)數(shù)據(jù)字節(jié)讀入字符數(shù)組中。int read(CharBuffer target)將字符讀入指定的字符緩沖區(qū)。long skip(long n)跳過和丟棄此輸入流中數(shù)據(jù)的 n 個(gè)字節(jié)。12.1.4輸出流的基本方法表12-5 OutputStream的主要方法方法作用void flush()刷新此輸出流并強(qiáng)制寫出所有緩沖的輸出字節(jié)。void write(byte b)將 b.length 個(gè)字節(jié)從指定的 byte 數(shù)組寫入此輸出流。

7、void write(byte b, int off, int len)將指定 byte 數(shù)組中從偏移量 off 開始的 len 個(gè)字節(jié)寫入此輸出流。abstract void write(int b)將指定的字節(jié)寫入此輸出流。表12-6 Writer的主要方法方法作用Writer append(char c)將指定字符添加到此 writer。Writer append(CharSequence csq)將指定字符序列添加到此 writer。abstract void flush()刷新該流的緩沖。如果該流已保存緩沖區(qū)中各種 write() 方法的所有字符,則立即將它們寫入預(yù)期目標(biāo)。void

8、write(char cbuf)寫入字符數(shù)組。void write(int c)寫入單個(gè)字符。要寫入的字符包含在給定整數(shù)值的 16 個(gè)低位中,16 高位被忽略。void write(String str)寫入字符串。12.2字符流和字節(jié)流字符流Reader和Writer是用于讀取字符流的兩個(gè)字符流類的抽象父類Reader和Writer是用于讀取字符流的兩個(gè)字符流類的抽象父類,準(zhǔn)確地說,它們可以象讀寫字符流一樣讀寫字節(jié)流 。字符流是基于Unicode編碼的。字節(jié)流輸入流InputStream和輸出流OutputStream也是抽象類,它們是一切字節(jié)輸入/輸出類的超類,也是抽象類。12.3節(jié)點(diǎn)流節(jié)

9、點(diǎn)流就是能夠直接和內(nèi)存、文件、管道這些數(shù)據(jù)的實(shí)際來源和目的地設(shè)備連接。import java.lang.Exception;class TestInput public static void main(String args) throws Exception /*準(zhǔn)備一個(gè)字節(jié)數(shù)組,用作接收從鍵盤上輸入內(nèi)容的緩沖區(qū)*/ byte b = new byte10; /number保存每次從輸入流中讀入到緩沖區(qū)b的字節(jié)數(shù) int number = 0; number = System.in.read(b); for(int i=0;ib.length;i+) System.out.println(

10、bi); System.out.println(Received number= + number );12.4流的處理鏈12.4.1過濾器流過濾器(Filter)流是為了某種目的過濾字節(jié)或字符的數(shù)據(jù)流。它也是一個(gè)加工流,建立在基本的字符/字節(jié)流。Java的I/O類中包含四個(gè)過濾器流,分別是支持字符和字節(jié)的輸入/輸出流。protected FilterInputStream(InputStream in)protected FilterOutputStream(OutputStream out)protected FilterReader(Reader in)protected FilterW

11、riter(Writer out) 表12-7 FilterInputStream的主要子類類作用BufferedInputStream從緩沖區(qū)中讀取數(shù)據(jù),每個(gè)帶緩沖的輸入流都包含一個(gè)數(shù)組用于保存從輸入流中讀入的數(shù)據(jù)。DataInputStream能夠獨(dú)立于任何機(jī)器的處理Java的基本數(shù)據(jù)類型。LineNumberInputStream跟蹤讀取了多少行。PushbackInputStream允許單字節(jié)向前查找。找到相應(yīng)的字節(jié)后,數(shù)據(jù)流將它推后,以備下一次讀取可以讀到它。表12-8 FilterOutputStream的主要子類類作用BufferedOutputStream帶緩沖的輸出流,應(yīng)用程

12、序可以實(shí)現(xiàn)成塊的輸出,提高輸出的性能DataOutputStream允許應(yīng)用程序按照J(rèn)ava的基本數(shù)據(jù)類型進(jìn)行輸出到輸出流中PrintStream輸出所有基本類型的統(tǒng)一碼格式,包括對(duì)象、字符串,常用的System.out其類型就是PrintStream12.4.2轉(zhuǎn)換流將字節(jié)流轉(zhuǎn)換為字符流上面的語(yǔ)句中,InputStreamReader類的作用是建立起從字節(jié)流到字符流之間的橋梁,它從字節(jié)流中讀入若干字節(jié)的數(shù)據(jù),然后根據(jù)設(shè)定的字符集將其轉(zhuǎn)換為字符。InputStreamReader isr = new InputStreamReader(System.in);OutputStreamWriter

13、 osr = new OutputStreamWriter(System.out);類似的,將字符流轉(zhuǎn)換為字節(jié)流/程序12-2 轉(zhuǎn)換字節(jié)流到字符流import java.io.IOException;import java.io.InputStreamReader;public class InputStreamReaderDemo public static void main(String args) throws IOException InputStreamReader isr=new InputStreamReader(System.in,GBK); int c=0; while(c

14、=isr.read()!=-1)System.out.println(char)c); 12.4.3數(shù)據(jù)輸入和輸出流DataInputStream和DataOutputStream是兩個(gè)可以按照J(rèn)ava數(shù)據(jù)類型(無(wú)關(guān)底層的數(shù)據(jù)類型)進(jìn)行存取的數(shù)據(jù)流。DataInput和DataOutput的實(shí)例public class DataInOutDemo public static void dataIn(String fileName) throws IOExceptionFileInputStream fis=new FileInputStream(fileName); DataInputStre

15、am dis=new DataInputStream(fis);System.out.print(從文件中讀取了:);while(true) try int x=dis.readInt();/從文件讀一個(gè)整數(shù) System.out.printf(%dt,x); catch(EOFException e)/到達(dá)文件尾 break;/退出循環(huán) dis.close(); public class DataInOutDemo /輸出10個(gè)整數(shù)到指定的文件 public static void dataOut(String fileName) throws IOExceptionFileOutputSt

16、ream fos=new FileOutputStream(fileName); DataOutputStream dos=new DataOutputStream(fos);Random rand=new Random(); for(int i=0;i10;i+)int x=rand.nextInt(10000);dos.writeInt(x);dos.close(); 12.4.4緩沖流應(yīng)用程序使用緩沖流,可以減少讀寫的次數(shù),加快輸入和輸出的速度,提高應(yīng)用的性能。緩沖數(shù)據(jù)流中均包含一個(gè)字節(jié)/字符緩沖區(qū)數(shù)組,從而實(shí)現(xiàn)成塊的讀寫。當(dāng)然這個(gè)成塊的讀寫過程對(duì)于應(yīng)用程序來講是透明的,無(wú)須關(guān)心。 例如

17、:還是向文件進(jìn)行輸出,上一小節(jié)中提到了下面的方法:如果加上了緩沖之后,則變成了下面的代碼:PrintStream ps = new PrintStream(out.dat);PrintStream ps = new PrintStream( new BufferedOutputStream( new FileOutputStream(out.dat);兩個(gè)不同輸出程序的效率比較一個(gè)不用緩沖區(qū)輸出數(shù)據(jù)到文件的程序 用緩沖實(shí)現(xiàn)向磁盤上文件輸出數(shù)據(jù)的程序 12.4.5打印輸出流基于數(shù)據(jù)輸出流的文件輸出,保存到文件中的是二進(jìn)制的內(nèi)容,無(wú)法使用文本工具瀏覽文件內(nèi)容。Java提供了PrintStream和

18、PrintWriter把數(shù)據(jù)輸出到文件中,可以方便的使用文本工具進(jìn)行瀏覽public class PrintStreamDemo public static void main(String args) throws FileNotFoundException /PrintStream out = new PrintStream(test.dat);PrintWriter out = new PrintWriter(test.dat);Random rand = new Random();for (int i = 0; i 10; i+) int x = rand.nextInt(100000

19、);out.println(x);out.close(); 12.4.6如何利用流編寫程序基本的I/O過程可以遵從以下原則:確定要訪問設(shè)備的數(shù)據(jù)類型是字節(jié)設(shè)備還是文本設(shè)備,來決定采用何種類型的節(jié)點(diǎn)流進(jìn)行連接。根據(jù)是準(zhǔn)備從數(shù)據(jù)源輸入內(nèi)容,還是準(zhǔn)備向目的地輸出內(nèi)容,確定合適的I/O類創(chuàng)建節(jié)點(diǎn)流。根據(jù)應(yīng)用程序的特性確定選擇合適的輸出流或輸入流,并對(duì)下層輸入輸出流進(jìn)行封裝,如有必要,需要借助InputStreamStreamReader或OutputStreamWriter進(jìn)行轉(zhuǎn)換。常見的如基于文本行的文本輸入輸出、基于Java數(shù)據(jù)類型的數(shù)據(jù)流輸入輸出,格式化輸出流PrintWriter等??紤]是否添

20、加緩沖流來改善輸入和輸出性能,如需要,修改第3步的實(shí)例化過程、一般將緩沖流置于中間層,參見緩沖流中的例子。輸入輸出結(jié)束后,可以直接關(guān)閉最外層的流即可。12.5文件處理應(yīng)用程序中經(jīng)常需要從外部的文件中讀取信息和向外部文件寫出數(shù)據(jù)進(jìn)行保存,在這個(gè)過程中,簡(jiǎn)單的程序如同例9-4和例9-5都已經(jīng)作了簡(jiǎn)單的介紹,但在實(shí)際中,經(jīng)常會(huì)發(fā)生各種意外的情況,例如,如果需要打開的文件不存在,或者要?jiǎng)?chuàng)建的文件沒有創(chuàng)建成功,甚至創(chuàng)建時(shí)覆蓋了一個(gè)已經(jīng)存在的同名文件,等等諸如此類的情況,因此,在文件處理中,除了能夠完成高效的I/O處理外,還要在關(guān)鍵的打開、讀寫和關(guān)閉等關(guān)鍵處理上注意異常的發(fā)生,提高程序的質(zhì)量。12.5.1

21、 File實(shí)際應(yīng)用中直接利用文件名指向一個(gè)將要?jiǎng)?chuàng)建的文件存在一定的風(fēng)險(xiǎn),例如是否有同名的文件存在,抑或在不同的環(huán)境中文件的屬性會(huì)有一定的變化。1 File對(duì)象File是對(duì)文件和路徑名的一種抽象表示,應(yīng)用程序中經(jīng)常使用File對(duì)象來指向自己希望創(chuàng)建或引用的文件或目錄的路徑。具體來說,它有兩個(gè)作用:應(yīng)用程序利用它檢查它所引用的物理文件或目錄,看是否與真實(shí)的文件或目錄相對(duì)應(yīng)。應(yīng)用程序可以利用它創(chuàng)建文件輸出/輸出流,進(jìn)行文件的處理。讀者需要注意的是File對(duì)象并不包含文件內(nèi)容,應(yīng)用程序只是利用它處理文件的各種屬性。 2 創(chuàng)建File對(duì)象下面列出了File對(duì)象的四種構(gòu)造函數(shù),應(yīng)用中可以根據(jù)情況進(jìn)行選擇:

22、File(File parent, String child) 根據(jù) parent 抽象路徑名和 child 路徑名字符串創(chuàng)建一個(gè)新 File 實(shí)例。 File(String pathname) 通過將給定路徑名字符串轉(zhuǎn)換成抽象路徑名來創(chuàng)建一個(gè)新 File 實(shí)例。 File(String parent, String child) 根據(jù) parent 路徑名字符串和 child 路徑名字符串創(chuàng)建一個(gè)新 File 實(shí)例。 File(.URI uri) 通過將給定的 file: URI 轉(zhuǎn)換成一個(gè)抽象路徑名來創(chuàng)建一個(gè)新的 File 實(shí)例,用于網(wǎng)絡(luò)訪問。例如,下面的代碼創(chuàng)建了一個(gè)封裝了指定路徑D:/

23、mydata/和一個(gè)文件名為score.txt的文件對(duì)象,它應(yīng)用了第三個(gè)構(gòu)造函數(shù):或者,可以使用第二個(gè)構(gòu)造函數(shù)的形式:注意:上述代碼中應(yīng)該保證在D分區(qū)中有一個(gè)mydata的目錄,該構(gòu)造函數(shù)并不會(huì)直接創(chuàng)建一個(gè)不存在的目錄。File myFile = new File(D:/mydata,score.txt);File myFile = new File(D:/mydata/score.txt);3 路徑分界符及路徑移植性問題 在不同的系統(tǒng)中路徑分隔符是不一樣的,例如在unix系列的操作系統(tǒng)中,分割符定義為/,而在Windows系統(tǒng)下則被定義為,只是由于轉(zhuǎn)義的規(guī)定被寫為。路徑的表示在不同的系統(tǒng)中也

24、是不一樣的,例如Windows系統(tǒng)下的路徑在絕對(duì)表示時(shí),通常包含分區(qū),如C:mydata2006score.txt在Java代碼中即被表示為C:mydata2006score.txt,而在Unix系統(tǒng)下絕對(duì)路徑卻是以/開始,例如/mydata/2006/score.txt。 如何避免?因此在Java應(yīng)用中就需要盡量考慮不要在代碼中直接嵌入具體的路徑表示,而要用相對(duì)路徑來表示,相對(duì)路徑不包括具體的絕對(duì)路徑前綴,避免了不同操作系統(tǒng)的影響。String homeDir = System.getenv(MyAppHome);File myFile = new File(homeDir + File.s

25、eparator + score.txt); 一個(gè)模擬的應(yīng)用String homeDir = System.getenv(MyAppHome);File myFile = new File(homeDir+File.separator+score.txt);if(!myFile.exists() System.out.println(The file has not been found! ); System.exit(-1); /退出程序執(zhí)行 表 12-9 File類中的路徑String getAbsoluteFile() 返回抽象路徑名的絕對(duì)路徑名字符串String getCanonica

26、lPath()返回抽象路徑名的規(guī)范路徑名字符串String getName()返回由此抽象路徑名表示的文件或目錄的名稱String getParent()返回此抽象路徑名的父路徑名的路徑名字符串,如果此路徑名沒有指定父目錄,則返回 nullString getPath()將此抽象路徑名轉(zhuǎn)換為一個(gè)路徑名字符串5 文件的屬性測(cè)試表 12-10 File類中的屬性測(cè)試方法boolean canRead()測(cè)試應(yīng)用程序是否可以讀取此抽象路徑名表示的文件boolean canWrite()測(cè)試應(yīng)用程序是否可以修改此抽象路徑名表示的文件boolean exists()測(cè)試此抽象路徑名表示的文件或目錄是否存

27、在boolean isAbsolute()測(cè)試此抽象路徑名是否為絕對(duì)路徑名boolean isDirectory()測(cè)試此抽象路徑名表示的文件是否是一個(gè)目錄boolean isFile()測(cè)試此抽象路徑名表示的文件是否是一個(gè)標(biāo)準(zhǔn)文件boolean isHidden()測(cè)試此抽象路徑名指定的文件是否是一個(gè)隱藏文件 String homeDir = System.getenv(MyAppHome);File myFile = new File(homeDir+File.separator+score.txt);if(!myFile.exists()System.out.println(The fi

28、le has not been found! );System.exit(0); /退出程序執(zhí)行6 目錄及目錄操作表 12-11 File類中的目錄操作String list()返回由此抽象路徑名所表示的目錄中的文件和目錄的名稱所組成字符串?dāng)?shù)組String list(FilenameFilter filter)返回由包含在目錄中的文件和目錄的名稱所組成的字符串?dāng)?shù)組,這一目錄是通過滿足指定過濾器的抽象路徑名來表示File listFiles()返回一個(gè)抽象路徑名數(shù)組,這些路徑名表示此抽象路徑名所表示目錄中的文件File listFiles(FileFilter filter)返回表示此抽象路徑名

29、所表示目錄中的文件和目錄的抽象路徑名數(shù)組,這些路徑名滿足特定過濾器File listFiles(FilenameFilter filter)返回表示此抽象路徑名所表示目錄中的文件和目錄的抽象路徑名數(shù)組,這些路徑名滿足特定過濾器static File listRoots() 列出可用的文件系統(tǒng)根目錄,例如Windows系統(tǒng)的C:;D:boolean mkdir()創(chuàng)建此抽象路徑名指定的目錄boolean mkdirs()創(chuàng)建此抽象路徑名指定的目錄,包括創(chuàng)建必需但不存在的父目錄7 其它文件操作表 12-12 File類中的其它文件操作boolean renameTo(File dest)重新命名此

30、抽象路徑名表示的文件,利用它的參數(shù)可以實(shí)現(xiàn)重新命名、文件移動(dòng)操作boolean setLastModified(long time)設(shè)置由此抽象路徑名所指定的文件或目錄的最后一次修改時(shí)間boolean setReadOnly()標(biāo)記此抽象路徑名指定的文件或目錄,以便只可對(duì)其進(jìn)行讀操作long length()返回由此抽象路徑名表示的文件的長(zhǎng)度boolean delete()刪除此抽象路徑名表示的文件或目錄boolean createNewFile()當(dāng)且僅當(dāng)不存在具有此抽象路徑名指定的名稱的文件時(shí),原子地創(chuàng)建由此抽象路徑名指定的一個(gè)新的空文件一個(gè)轉(zhuǎn)移目錄下文件的實(shí)例12.5.2順序讀寫文件順序

31、讀寫文件顧名思義,順序讀寫文件就是按照順序一個(gè)字節(jié)或一個(gè)字符的對(duì)文件的內(nèi)容進(jìn)行輸入輸出,不能回讀或回寫,也不能隨意指定讀寫位置,而只能從前到后。public class AccountTools public static Map getAccountFromFile(String fn) throws IOException, NumberFormatException, ParseException Map accounts=new HashMap(); BufferedReader in=new BufferedReader(new FileReader(fn); String info

32、=null;/用來保存每次讀入的文件內(nèi)容 while(true)info=in.readLine();/每次讀取文件一行if(info=null)/若返回值為null,則表示已到文件尾 break;String s=info.split(“,”);/利用文件的內(nèi)容分隔符分解此行Account a=new Account(s0,s1,Integer.parseInt(s2);accounts.put(a.getId(), a); return accounts; 12.5.3隨機(jī)讀寫文件RandomAccessFileJava提供了RandomAccessFile類,用于隨機(jī)存取文件的讀取和寫入

33、。它屬于字節(jié)流,也屬于節(jié)點(diǎn)流的一種,而且本身即是輸入流又是輸出流1. 如何構(gòu)造RandomAccessFile對(duì)象構(gòu)造函數(shù)1:RandomAccessFile(File file, String mode) /創(chuàng)建從中讀取和向其中寫入(可選)的隨機(jī)存取文件流,該文件由 File 參數(shù)指定。 構(gòu)造函數(shù)2:RandomAccessFile(String name, String mode) /創(chuàng)建從中讀取和向其中寫入(可選)的隨機(jī)存取文件流,該文件具有指定名稱。 r以只讀方式打開。調(diào)用結(jié)果對(duì)象的任何write方法都將導(dǎo)致拋出IOException。rw打開以便讀取和寫入。如果該文件尚不存在,則嘗試

34、創(chuàng)建該文件。rws打開以便讀取和寫入,對(duì)于rw,還要求對(duì)文件的內(nèi)容或元數(shù)據(jù)的每個(gè)更新都同步寫入到基礎(chǔ)存儲(chǔ)設(shè)備。rwd打開以便讀取和寫入,對(duì)于rw,還要求對(duì)文件內(nèi)容的每個(gè)更新都同步寫入到基礎(chǔ)存儲(chǔ)設(shè)備。其中,mode 參數(shù)指定用以打開文件的訪問模式。允許的值及其含意為: 例如,如果希望對(duì)已經(jīng)存在的文件進(jìn)行更新操作,可以采用如下代碼:RandomAccessFile raf = new RandomAccessFile(D:/mydata/student.txt,rw); 2 隨機(jī)存取的實(shí)現(xiàn)機(jī)理隨機(jī)存取文件的行為類似存儲(chǔ)在文件系統(tǒng)中的一個(gè)大型字節(jié)數(shù)組。存在指向該隱含數(shù)組的光標(biāo)或索引,稱為文件指針。輸

35、入操作從文件指針指向處開始讀取字節(jié),并隨著對(duì)字節(jié)的讀取而前移此文件指針。如果隨機(jī)存取文件以讀取/寫入模式創(chuàng)建,則輸出操作也可用;輸出操作從文件指針開始寫入字節(jié),并隨著對(duì)字節(jié)的寫入而前移此文件指針。寫入隱含數(shù)組的當(dāng)前末尾之后的輸出操作導(dǎo)致該數(shù)組擴(kuò)展。該文件指針可以通過 getFilePointer 方法讀取,并通過 seek或skipBytes方法設(shè)置隨機(jī)位置. RandomAccessFile類的主要方法表 12-14 RandomAccessFile類long getFilePointer()返回此文件中的當(dāng)前偏移量long length()返回此文件的長(zhǎng)度seek(long pos)設(shè)置到

36、此文件開頭測(cè)量到的文件指針偏移量,在該位置發(fā)生下一個(gè)讀取或?qū)懭氩僮鱥nt skipBytes(int n) 嘗試跳過輸入的 n 個(gè)字節(jié)以丟棄跳過的字節(jié)int read()從此文件中讀取一個(gè)數(shù)據(jù)字節(jié)int read(byte b)將最多 b.length 個(gè)數(shù)據(jù)字節(jié)從此文件讀入字節(jié)數(shù)組int read(byte b, int off, int len)將最多 len 個(gè)數(shù)據(jù)字節(jié)從此文件讀入字節(jié)數(shù)組,類似的還有,readBoolean() readByte() readDouble() readLine()等write(byte b)將 b.length 個(gè)字節(jié)從指定字節(jié)數(shù)組寫入到此文件,并從當(dāng)前

37、文件指針開始,類似的還有,write(byte b, int off, int len) write(int b) writeFloat(float v) writeInt(int v) 隨機(jī)文件訪問程序 第一部分,打開文件public class TestRandomAccessFile public static void main(String args) RandomAccessFile raf = null; String info = null; String rec= null; try raf= new RandomAccessFile(d:/log/student.txt,r

38、w); catch (FileNotFoundException e) System.exit(0); 第二部分,文件更新 try while(info=raf.readLine()!=null) rec = info.split(,); if(pareTo(MATH)=0) raf.seek(raf.getFilePointer()-6); raf.writeBytes(MaTH); raf.skipBytes(2); raf.close(); catch (IOException e) System.exit(0);程序運(yùn)行需要注意:執(zhí)行和分析上面的程序,需要注意的是以下幾個(gè)方面的問題:建

39、立隨機(jī)讀寫文件的模式如何靈活的利用seek和skip實(shí)現(xiàn)靈活的定位隨機(jī)讀寫尚不能支持對(duì)文件的直接插入操作,僅僅實(shí)現(xiàn)了修改操作,因此需要避免因?yàn)閷懭肓吮刃枰薷牡男畔⒍嗟淖止?jié),而導(dǎo)致后續(xù)的內(nèi)容受到破壞。注意讀寫中的異常處理程序沒有考慮字符集的問題,對(duì)于實(shí)驗(yàn)用的文本文件,其原始格式都是按照一個(gè)字符占一個(gè)字節(jié),一個(gè)漢字占2個(gè)字節(jié)進(jìn)行分析的,在運(yùn)行時(shí)讀者需要注意,如果有漢字的話,可能是亂碼,此問題請(qǐng)參考有關(guān)國(guó)際化編程中的有關(guān)解釋。12.6對(duì)象串行化串行化對(duì)象串行化使得應(yīng)用能夠以字節(jié)序列形式保存一個(gè)對(duì)象的狀態(tài)(對(duì)象的屬性值),以便隨后被重新構(gòu)造為原來的對(duì)象。 在Java的I/O類中,有兩個(gè)特別的類Obj

40、ectOutputStream和ObjectInputStream可以實(shí)現(xiàn)對(duì)象的串行化存取。 Java中的串行化首先應(yīng)用在RMI(Remote Method Invocation)環(huán)境,RMI允許在一個(gè)虛擬機(jī)中的對(duì)象通過Internet傳遞參數(shù)去引用存在于另外一個(gè)虛擬機(jī)中的對(duì)象的方法,并獲得返回值。串行化的對(duì)象 如果要使對(duì)象能夠在網(wǎng)絡(luò)內(nèi)傳輸或者持久化保存,就必須使對(duì)象成為可串行化。在Java中,一個(gè)類的對(duì)象要可串行化的必要條件是:定義類的時(shí)候,該類要實(shí)現(xiàn)Serializable接口。import java.io.Serializable;public class Student impleme

41、nts Serializable String sid; /學(xué)號(hào) String name; /姓名 Student(String sid, String name) super(); this.sid = sid; = name; public String toString() return id=+sid+ name=+name; /讀者可自己繼續(xù)添加類的其它部分定義關(guān)于串行化化類在進(jìn)行類的串行化實(shí)現(xiàn)聲明時(shí),要注意類的繼承性。如果一個(gè)類的父類已經(jīng)聲明為可串行化的,那么子類就無(wú)需重復(fù)聲明了。在進(jìn)行屬性聲明時(shí),一定要注意屬性類型是否已實(shí)現(xiàn)串行化。 同時(shí)需要注意的是,Java中的基本數(shù)據(jù)類型、D

42、ate類等已經(jīng)實(shí)現(xiàn)了可串行化,在應(yīng)用中可直接使用。ObjectOutputStream的主要輸出方法表 12-15 writeBoolean(boolean val)寫入一個(gè) boolean 值writeByte(int val) 寫入一個(gè) 8 位的字節(jié)值writeBytes(String str)以字節(jié)序列形式寫入一個(gè) StringwriteChar(int val)寫入一個(gè) 16 位的 char 值writeChars(String str)以 char 序列形式寫入一個(gè) StringwriteDouble(double val)寫入一個(gè) 64 位的 double 值writeFloat(

43、float val)寫入一個(gè) 32 位的 float 值writeInt(int val)寫入一個(gè) 32 位的 int 值writeLong(long val)寫入一個(gè) 64 位的 long 值writeObject(Object obj)將指定的對(duì)象寫入 ObjectOutputStreamwriteShort(int val)寫入一個(gè) 16 位的 short 值write(byte buf)寫入一個(gè)字節(jié)數(shù)組對(duì)象的串行化存取 public class StudentManager /限制了該列表只處理Student類型的對(duì)象 private List students = new Array

44、List(10); StudentManager() /將對(duì)象追加到列表對(duì)象中 void addStudent(Student student) this.students.add(student); void save(String filename) throws FileNotFoundException, IOException / void restore(String filename) throws FileNotFoundException, IOException /將列表中的對(duì)象都保存在文件中void save(String filename) throws FileNot

45、FoundException, IOException ObjectOutputStream out = null;/判斷集合中是否有對(duì)象存在,如果沒有,就不再執(zhí)行保存操作if(this.students.size()=0) return; /* 開始保存對(duì)象列表,首先創(chuàng)建一個(gè)對(duì)象輸出流,運(yùn)行中可能拋出異常*/out = new ObjectOutputStream( new BufferedOutputStream( new FileOutputStream(filename); /首先將需要保存的對(duì)象總數(shù)保存到文件開始處,以便讀取時(shí)容易處理out.writeInt(students.siz

46、e();for(Student student:students)/開始循環(huán)保存每個(gè)對(duì)象out.writeObject(student);out.close();/關(guān)閉輸出流void restore(String filename) throws FileNotFoundException, IOException ObjectInputStream in =null; Object student=null; this.students.clear(); /首先將列表對(duì)象清空 in = new ObjectInputStream( new BufferedInputStream(new Fi

47、leInputStream(filename); try int count = in.readInt(); /首先讀取該文件中對(duì)象的數(shù)量 int i=0; while(icount) student=in.readObject(); /返回的類型是Object this.addStudent(Student)student); System.out.println(student); i+; catch (ClassNotFoundException e) /e.printStackTrace(); finally in.close(); /關(guān)閉輸入流 串行化的問題 串行化看起來比較簡(jiǎn)單,只須實(shí)現(xiàn)一個(gè)沒有任何方法的接口即可,但實(shí)際上還是會(huì)出現(xiàn)一些特別的情況需要考慮。例如,下面的幾個(gè)問題:一個(gè)對(duì)象是否一定能夠被串行化?如果不希望保存對(duì)象的某些屬性怎么辦?一個(gè)對(duì)象的狀態(tài)發(fā)生了改變,再次保存時(shí)是重新保存還是覆蓋原有的內(nèi)容?串行化的問題(cont.)1 串行化的條件在實(shí)現(xiàn)Serializable接口時(shí),為了類對(duì)象能夠充分串行化,則要求該類中的所有字段必須均為可串行化的,但是實(shí)際中可能還有一

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論