摘要:虛擬機讀取其他進(jìn)程的數(shù)據(jù)對象的方法可以運行平臺上的其他程序該方法產(chǎn)生一個對象對象代表由該程序啟動啟動的子進(jìn)程類提供如下三個方法用于和其子進(jìn)程通信獲取子進(jìn)程的錯誤流獲取子進(jìn)程的輸入流獲取子進(jìn)程的輸出流這里的輸入流輸出流容易混淆從程序的角度思考
Java虛擬機讀取其他進(jìn)程的數(shù)據(jù)
Runtime對象的exec方法可以運行平臺上的其他程序,該方法產(chǎn)生一個Process對象,Process對象代表由該Java程序啟動啟動的子進(jìn)程,Process類提供如下三個方法,用于和其子進(jìn)程通信:
InputStream getErrorStream() 獲取子進(jìn)程的錯誤流
InputStream getInputStream() 獲取子進(jìn)程的輸入流
OutputStream getOutputStream() 獲取子進(jìn)程的輸出流
這里的輸入流輸出流容易混淆.從程序的角度思考,子進(jìn)程讀取程序的數(shù)據(jù),為輸出流.子進(jìn)程讀取數(shù)據(jù),是讓程序把數(shù)據(jù)輸出到子進(jìn)程中.
java//省略代碼 Process p = Runtime.getRuntime().exec("javac"); BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream(),"GBK")); String buff; while ((buff = br.readLine()) != null ) { System.out.println(buff); } //省略代碼
上面程序使用Runtime啟動javac,獲取了運行該程序相應(yīng)的子進(jìn)程.
javapublic class WriteToProcess { public static void main(String[] args) { PrintStream ps = null; try { //返回運行該命令的子進(jìn)程 Process p = Runtime.getRuntime().exec("java ReadStand"); //p進(jìn)程的輸出流創(chuàng)建PrintStream對象 //對本程序是輸出流,對p進(jìn)程則是輸入流 ps = new PrintStream(p.getOutputStream()); BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream())); String content; while ((content = br.readLine()) != null) { System.out.println(content); } ps.println("普通字符串"); ps.println(new WriteToProcess()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if (null != ps) { ps.close(); } } } } class ReadStand { public static void main(String[] args) { PrintStream ps = null; Scanner sc = new Scanner(System.in); try { ps = new PrintStream("src estout.txt"); sc.useDelimiter(" "); while (sc.hasNext()) { ps.print("鍵盤輸入的內(nèi)容是:" + sc.next()); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { sc.close(); ps.close(); } } }
上面的程序,運行結(jié)束產(chǎn)生了一個out.txt文件,該文件由ReadStand產(chǎn)生,該文件的內(nèi)容由WriteToProcess類寫入到ReadStan進(jìn)程里,并由ReadStand讀取這些數(shù)據(jù),并把數(shù)據(jù)保存在out.txt文件.
RandomAccessFileRandomAccessFile是Java輸入/輸出流中功能最豐富的文件內(nèi)容訪問類,提供了眾多方法來訪問文件,既可以支持讀取內(nèi)容,也可以向文件輸出數(shù)據(jù).與普通的輸入/輸出流不同的是,RandomAccessFile支持"隨機訪問"的方式,程序可以直接跳轉(zhuǎn)到文件的任意位置來讀寫數(shù)據(jù).
計算機中"隨機訪問"是由Random Access兩個單詞單詞翻譯而來.Random不僅有隨機的意思,還有任意的意思.如果
能這樣理解Random,可以更好的理解Random Access:任意訪問,也就是說可以自由訪問任意存儲點的存儲器(與磁盤,
磁帶等需要尋道,倒帶才可訪問存儲點的存儲器區(qū)分);而RandomAccessFile的含義是可以自由訪問文件的任意地方(與
InputStream,Reader依次向后讀取區(qū)分).
RandomAccessFile可以自由訪問文件的任意位置,所以如果只希望訪問文件的部分內(nèi)容,RandomAccessFile是更好的選擇.
RandomAccessFile允許自由定位文件記錄指針,所以RandomAccessFile不用從開始地方輸出,所以可以向已存在的文件后追加內(nèi)容.
RandomAccessFile對象包含了一個記錄指針,用以標(biāo)識當(dāng)前讀寫處的位置,當(dāng)程序創(chuàng)建一個新的RandomAccessFile對象時,該對象的的文件記錄指針位于文件頭(0處),讀寫了n個字節(jié)后文件記錄指針將會移動n個字節(jié),除此之外,RandomAccessFile可以自由移動記錄指針,可以向前/向后移動.包含兩個方法來操作文件記錄指針:
void getFilepointer() 返回文件記錄指針的當(dāng)前位置
void seek(long pos) 將文件記錄指針定位到pos位置
RandomAccessFile既可以讀文件又能寫文件,包含了類似于InputStream的三個Read方法,用法和InputStream的三個read方法完全一樣.也包含了OutputStream的三個write方法,用法和OutputStream的write方法完全一樣.此外還包含系列的readXXX和writeXXX方法來完成輸入/輸出.
RandomAccessFile類有兩個構(gòu)造器,基本相同,區(qū)別在于指定的文件形式不同.一個使用String來制定文件名,一個使用File參數(shù)來制定文件本身,之外創(chuàng)建RandomAccessFile對象還需要制定一個mode參數(shù),該參數(shù)指定RandomAccessFile的訪問模式,有如下四個值:
"r" 以只讀的方式打開指定文件.如試圖對該RandomAccessFile指定寫入操作會拋出IOException.
"rw" 以讀取,寫入的方式打開指定文件.如果該文件不存在,則嘗試創(chuàng)建該文件.
"rws" 以讀取,寫入的方式打開指定文件.相對于"rw"模式,還要求對文件的元數(shù)據(jù)或內(nèi)容的每個更新都同步到底層存儲設(shè)備.
"rwd" 以讀取,寫入的方式打開指定文件,對于"rw",還要求對文件內(nèi)容的每個更新都同步寫入底層存儲設(shè)備.
//省略代碼 RandomAccessFile raf = null; //省略代碼 try { raf = new RandomAccessFile("out.txt","rw"); raf.seek(raf.length()); raf.write("追加內(nèi)容 ".getBytes()); }
使用RandomAccessFile對指定文件指定位置插入內(nèi)容:
javapublic static void insert(String fileName,long pos,String insertContent) { RandomAccessFile raf = null; try { raf = new RandomAccessFile(fileName, "rw"); File tmpFile = File.createTempFile("temp", null); tmpFile.deleteOnExit(); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(tmpFile))); BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(tmpFile))); //設(shè)置文件指針位置 raf.seek(pos); String content; /** * 將插入點內(nèi)容保存在臨時文件中 * 讀取插入點后所有文件內(nèi)容 */ while ((content = raf.readLine()) != null) { //將數(shù)據(jù)寫入臨時文件 bw.write(content); } bw.flush(); bw.close(); //重新設(shè)置指針位置 raf.seek(pos); //插入內(nèi)容 raf.write(insertContent.getBytes()); //追加臨時文件中內(nèi)容 while ((content = br.readLine()) != null) { raf.write(content.getBytes()); } br.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { raf.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }對象的序列化和反序列化
對象序列化是將對象保存在磁盤中,或允許在網(wǎng)絡(luò)中直接傳輸對象,對象序列化機制允許把內(nèi)存中的Java對象轉(zhuǎn)換平臺無關(guān)的二進(jìn)制流,從而允許把這種二進(jìn)制流持久保存在磁盤上,通過網(wǎng)絡(luò)將這種二進(jìn)制流傳輸?shù)搅硪粋€網(wǎng)絡(luò)節(jié)點.其他程序獲得了這種二進(jìn)制流,都可以將這種二進(jìn)制流恢復(fù)成原來的Java對象.
序列化的含義和意義序列化機制允許將實現(xiàn)序列化的Java對象轉(zhuǎn)換為字節(jié)序列,這些字節(jié)序列可以被保存在磁盤上,或通過網(wǎng)絡(luò)傳輸,以備以后重新恢復(fù)成原來的對象,序列化機制使得對象可以脫離程序的運行獨立存在.
對象的序列化(Serialize)指將一個Java對象寫入IO流中,于此對應(yīng)的是,對象的反序列化(Deserialize)指從IO流中恢復(fù)該Java對象.
如果要讓某個對象可以支持序列化機制,必須它的類是可序列化的(Serialize).為了讓某個類可序列化,必須實現(xiàn)如下兩個接口之一:
Serializable
Externalizable
Serializable是一個標(biāo)記接口,該接口無需實現(xiàn)任何方法,只是表明該類是可序列化的.所有可能在網(wǎng)絡(luò)上傳輸?shù)膶ο蟮念惗紤?yīng)該是可序列化的,否則程序?qū)霈F(xiàn)異常.比如RMI(Remote Method Invoke,遠(yuǎn)程方法調(diào)用)過程中的參數(shù)和返回值;所有需要保存到磁盤的對象的類都必須是可序列化.如Web中需要保存到HttpSession和ServletContext屬性的Java對象.
通常建議,程序創(chuàng)建的每個JavaBean都實現(xiàn)Serializable接口.
序列化對象實例:
javapublic class ObjectOutputStreamTest { public static void main(String[] args) { ObjectOutputStream oos = null; try { //創(chuàng)建一個ObjectOutputStream輸出流 oos = new ObjectOutputStream(new FileOutputStream("src//io//person.txt")); Person p1 = new Person("swk", 20); //把對象寫入輸出流 oos.writeObject(p1); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { if (null != oos) { oos.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } class Person implements Serializable { private static final long serialVersionUID = 1L; private String name; private int age; public Person(String name,int age) { // TODO Auto-generated constructor stub System.out.println("Person 構(gòu)造函數(shù)"); this.name = name; this.age = age; } 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; } }
從二進(jìn)制流中恢復(fù)Java對象:
java//省略代碼 ObjectInputStream ois = null; try { //創(chuàng)建ObjectInputStream輸入流 ois = new ObjectInputStream(new FileInputStream("src//io//person.txt")); //從流中讀取對象,并強制轉(zhuǎn)換為Person類型 Person p = (Person)ois.readObject(); System.out.println("Age:" + p.getAge() + ",name:" + p.getName()); } //省略代碼
反序列化讀取的只是Java對象的數(shù)據(jù),而不是Java類,因此采用反序列化恢復(fù)Java對象時,必須提供Java對象所屬的class文件,否則引發(fā)ClassNotFoundException.
Person類只有一個有參數(shù)構(gòu)造器,并沒有無參數(shù)構(gòu)造器,而且構(gòu)造函數(shù)內(nèi)有打印語句.當(dāng)反序列化讀取Java對象時,沒有看到程序調(diào)用該構(gòu)造器,這表明反序列化機制無需通過構(gòu)造器來初始化Java對象.
如果向文件中使用序列化多個Java對象,使用反序列化機制恢復(fù)時,必須按實際寫入順序讀取.
程序創(chuàng)建子類實例時,系統(tǒng)會隱式創(chuàng)建為它所有的父類都創(chuàng)建實例.反序列化某個子類的實例時,反序列化機制需要恢復(fù)其關(guān)聯(lián)的父類實例,恢復(fù)這些父類實例有;兩種方式:
使用反序列化機制
使用父類無參數(shù)構(gòu)造器
在上面兩種方式中,反序列化機制優(yōu)先采用第一種機制.如果某個父類既不可序列化,則不能使用第一種機制;又沒有提供無參數(shù)構(gòu)造器,則不可采用第二種機制,反序列化該子類實例將拋出異常.
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/64414.html
摘要:當(dāng)使用節(jié)點流進(jìn)行輸入輸出時,程序直接連接到實際的數(shù)據(jù)源,和時間的輸入輸出節(jié)點連接處理流則用于對一個已存在的流進(jìn)行連接或封裝,通過封裝后的流來實現(xiàn)數(shù)據(jù)讀寫功能,處理流也被稱為高級流。 文件的編碼 文本文件就是字節(jié)序列,可以是任意編碼形式。在中文操作系統(tǒng)上直接創(chuàng)建文本文件,則該文本文件只能識別ANSI編碼,其他編碼方式會產(chǎn)生亂碼 package imooc.io; import java...
摘要:但它融合了和的功能。支持對隨機訪問文件的讀取和寫入。的概述和作為集合的使用了解的概述類表示了一個持久的屬性集??杀4嬖诹髦谢驈牧髦屑虞d。屬性列表中每個鍵及其對應(yīng)值都是一個字符串。 1_序列流(了解) 1.什么是序列流 序列流可以把多個字節(jié)輸入流整合成一個, 從序列流中讀取數(shù)據(jù)時, 將從被整合的第一個流開始讀, 讀完一個之后繼續(xù)讀第二個, 以此類推. 2.使用方式 整合兩個: S...
摘要:把字節(jié)序列恢復(fù)為對象的過程稱為對象的反序列化。代表對象輸入流,它的方法從一個源輸入流中讀取字節(jié)序列,再把它們反序列化為一個對象,并將其返回。接口繼承自接口,實現(xiàn)接口的類完全由自身來控制序列化的行為,而僅實現(xiàn)接口的類可以采用默認(rèn)的序列化方式。 把對象轉(zhuǎn)換為字節(jié)序列的過程稱為對象的序列化。把字節(jié)序列恢復(fù)為對象的過程稱為對象的反序列化。 對象的序列化主要有兩種用途: 1) 把...
摘要:一序列化和反序列化的概念把對象轉(zhuǎn)換為字節(jié)序列的過程稱為對象的序列化把字節(jié)序列恢復(fù)為對象的過程稱為對象的反序列化。代表對象輸入流,它的方法從一個源輸入流中讀取字節(jié)序列,再把它們反序列化為一個對象,并將其返回。 一、序列化和反序列化的概念 把對象轉(zhuǎn)換為字節(jié)序列的過程稱為對象的序列化;把字節(jié)序列恢復(fù)為對象的過程稱為對象的反序列化。 對象的序列化主要有兩種用途: 1) 把對象的字節(jié)序列永久地保...
摘要:減少垃圾收集壓力因為所有長生命周期的數(shù)據(jù)都是在的管理內(nèi)存中以二進(jìn)制表示的,所以所有數(shù)據(jù)對象都是短暫的,甚至是可變的,并且可以重用。當(dāng)然,并不是唯一一個基于且對二進(jìn)制數(shù)據(jù)進(jìn)行操作的數(shù)據(jù)處理系統(tǒng)。 showImg(https://segmentfault.com/img/remote/1460000020044119?w=1280&h=853); 前言 如今,許多用于分析大型數(shù)據(jù)集的開源系...
閱讀 2802·2021-11-22 13:54
閱讀 1152·2021-10-14 09:48
閱讀 2359·2021-09-08 09:35
閱讀 1612·2019-08-30 15:53
閱讀 1218·2019-08-30 13:14
閱讀 679·2019-08-30 13:09
閱讀 2592·2019-08-30 10:57
閱讀 3393·2019-08-29 13:18