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