成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Java IO (三) 讀取其他進(jìn)程數(shù)據(jù),RandomAccessFile,序列化和反序列化

zhangfaliang / 1148人閱讀

摘要:虛擬機讀取其他進(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文件.

RandomAccessFile

RandomAccessFile是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方法,用法和OutputStreamwrite方法完全一樣.此外還包含系列的readXXXwriteXXX方法來完成輸入/輸出.

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

相關(guān)文章

  • Java 輸入/輸出 I/O流 RandomAccessFile

    摘要:當(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...

    Eirunye 評論0 收藏0
  • Java編程基礎(chǔ)23——IO(其他流)&Properties

    摘要:但它融合了和的功能。支持對隨機訪問文件的讀取和寫入。的概述和作為集合的使用了解的概述類表示了一個持久的屬性集??杀4嬖诹髦谢驈牧髦屑虞d。屬性列表中每個鍵及其對應(yīng)值都是一個字符串。 1_序列流(了解) 1.什么是序列流 序列流可以把多個字節(jié)輸入流整合成一個, 從序列流中讀取數(shù)據(jù)時, 將從被整合的第一個流開始讀, 讀完一個之后繼續(xù)讀第二個, 以此類推. 2.使用方式 整合兩個: S...

    vvpale 評論0 收藏0
  • Java 列化和反列化

    摘要:把字節(jié)序列恢復(fù)為對象的過程稱為對象的反序列化。代表對象輸入流,它的方法從一個源輸入流中讀取字節(jié)序列,再把它們反序列化為一個對象,并將其返回。接口繼承自接口,實現(xiàn)接口的類完全由自身來控制序列化的行為,而僅實現(xiàn)接口的類可以采用默認(rèn)的序列化方式。 把對象轉(zhuǎn)換為字節(jié)序列的過程稱為對象的序列化。把字節(jié)序列恢復(fù)為對象的過程稱為對象的反序列化。    對象的序列化主要有兩種用途:   1) 把...

    jcc 評論0 收藏0
  • Java 列化與反列化

    摘要:一序列化和反序列化的概念把對象轉(zhuǎn)換為字節(jié)序列的過程稱為對象的序列化把字節(jié)序列恢復(fù)為對象的過程稱為對象的反序列化。代表對象輸入流,它的方法從一個源輸入流中讀取字節(jié)序列,再把它們反序列化為一個對象,并將其返回。 一、序列化和反序列化的概念 把對象轉(zhuǎn)換為字節(jié)序列的過程稱為對象的序列化;把字節(jié)序列恢復(fù)為對象的過程稱為對象的反序列化。 對象的序列化主要有兩種用途: 1) 把對象的字節(jié)序列永久地保...

    I_Am 評論0 收藏0
  • Flink 源碼解析 —— 深度解析 Flink 是如何管理好內(nèi)存的?

    摘要:減少垃圾收集壓力因為所有長生命周期的數(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ù)集的開源系...

    Edison 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<