這個(gè)瞬時(shí)主要是針對(duì) 串行化 時(shí)來(lái)說(shuō)的,所謂串行化最大的作用就是恢復(fù)一個(gè)對(duì)象??梢曰謴?fù)的對(duì)象就是可以持久的,不可恢復(fù)的就是瞬時(shí)的。
成都一家集口碑和實(shí)力的網(wǎng)站建設(shè)服務(wù)商,擁有專(zhuān)業(yè)的企業(yè)建站團(tuán)隊(duì)和靠譜的建站技術(shù),十多年企業(yè)及個(gè)人網(wǎng)站建設(shè)經(jīng)驗(yàn) ,為成都上1000家客戶(hù)提供網(wǎng)頁(yè)設(shè)計(jì)制作,網(wǎng)站開(kāi)發(fā),企業(yè)網(wǎng)站制作建設(shè)等服務(wù),包括成都營(yíng)銷(xiāo)型網(wǎng)站建設(shè),成都品牌網(wǎng)站建設(shè),同時(shí)也為不同行業(yè)的客戶(hù)提供網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站建設(shè)的服務(wù),包括成都電商型網(wǎng)站制作建設(shè),裝修行業(yè)網(wǎng)站制作建設(shè),傳統(tǒng)機(jī)械行業(yè)網(wǎng)站建設(shè),傳統(tǒng)農(nóng)業(yè)行業(yè)網(wǎng)站制作建設(shè)。在成都做網(wǎng)站,選網(wǎng)站制作建設(shè)服務(wù)商就選創(chuàng)新互聯(lián)公司。
一個(gè)對(duì)象是否是瞬時(shí)的從邏輯上就可以判斷出來(lái),Thread和FileInputStream都是依賴(lài)外部環(huán)境的,Thread依賴(lài)于cpu當(dāng)時(shí)的狀態(tài),cpu的狀態(tài)是不可逆轉(zhuǎn)的,你的程序沒(méi)法控制cpu在某個(gè)時(shí)間把時(shí)間片分給你,至于FileInputStream本身就是依賴(lài)于外部文件讀入的,恢復(fù)的時(shí)候文件有沒(méi)有還不好說(shuō)呢,怎么給你恢復(fù)。
也就是說(shuō)一般java虛擬機(jī)能給你存在硬盤(pán)里的都是持久的,java虛擬機(jī)沒(méi)辦法存硬盤(pán)里的都是瞬時(shí)的
對(duì)象的壽命通常隨著生成該對(duì)象的程序的終止而終止。有時(shí)候,可能需要將對(duì)象的狀態(tài)保存下來(lái),在需要時(shí)再將對(duì)象恢復(fù)。我們把對(duì)象的這種能記錄自己的狀態(tài)以便將來(lái)再生的能力。叫作對(duì)象的持續(xù)性(persistence)。對(duì)象通過(guò)寫(xiě)出描述自己狀態(tài)的數(shù)值來(lái)記錄自己 ,這個(gè)過(guò)程叫對(duì)象的串行化(Serialization-連續(xù)) 。串行化的主要任務(wù)是寫(xiě)出對(duì)象實(shí)例變量的數(shù)值。如果變量是另一對(duì)象的引用,則引用的對(duì)象也要串行化。這個(gè)過(guò)程是遞歸的,串行化可能要涉及一個(gè)復(fù)雜樹(shù)結(jié)構(gòu)的單行化,包括原有對(duì)象、對(duì)象的對(duì)象、對(duì)象的對(duì)象的對(duì)象等等。對(duì)象所有權(quán)的層次結(jié)構(gòu)稱(chēng)為圖表(graph)。
Java對(duì)象的單行化的目標(biāo)是為Java的運(yùn)行環(huán)境提供一組特性,如下所示:
1) 盡量保持對(duì)象串行化的簡(jiǎn)單扼要 ,但要提供一種途徑使其可根據(jù)開(kāi)發(fā)者的要求進(jìn)行擴(kuò)展或定制。
2) 串行化機(jī)制應(yīng)嚴(yán)格遵守Java的對(duì)象模型 。對(duì)象的串行化狀態(tài)中應(yīng)該存有所有的關(guān)于種類(lèi)的安全特性的信息。
3) 對(duì)象的串行化機(jī)制應(yīng)支持Java的對(duì)象持續(xù)性。
4) 對(duì)象的串行化機(jī)制應(yīng)有足夠的 可擴(kuò)展能力以支持對(duì)象的遠(yuǎn)程方法調(diào)用(RMI)。
5) 對(duì)象串行化應(yīng)允許對(duì)象定義自身 的格式即其自身的數(shù)據(jù)流表示形式,可外部化接口來(lái)完成這項(xiàng)功能。
利用Java實(shí)現(xiàn)串口全雙工通訊
內(nèi)容:
1. SerialBean
2. SerialBuffer
3. ReadSerial
4. SerialExample
一個(gè)嵌入式系統(tǒng)通常需要通過(guò)串口與其主控系統(tǒng)進(jìn)行全雙工通訊,譬如一個(gè)流水線控制系統(tǒng)需要不斷的接受從主控系統(tǒng)發(fā)送來(lái)的查詢(xún)和控制信息,并將執(zhí)行結(jié)果或查詢(xún)結(jié)果發(fā)送回主控系統(tǒng)。本文介紹了一個(gè)簡(jiǎn)單的通過(guò)串口實(shí)現(xiàn)全雙工通訊的Java類(lèi)庫(kù),該類(lèi)庫(kù)大大的簡(jiǎn)化了對(duì)串口進(jìn)行操作的過(guò)程。
本類(lèi)庫(kù)主要包括:SerialBean.java (與其他應(yīng)用程序的接口), SerialBuffer.java (用來(lái)保存從串口所接收數(shù)據(jù)的緩沖區(qū)), ReadSerial.java (從串口讀取數(shù)據(jù)的程序)。另外本類(lèi)庫(kù)還提供了一個(gè)例程SerialExample.java 作為示范。在下面的內(nèi)容中將逐一對(duì)這幾個(gè)部分進(jìn)行詳細(xì)介紹。
1. SerialBean
SerialBean是本類(lèi)庫(kù)與其他應(yīng)用程序的接口。該類(lèi)庫(kù)中定義了SerialBean的構(gòu)造方法以及初始化串口,從串口讀取數(shù)據(jù),往串口寫(xiě)入數(shù)據(jù)以及關(guān)閉串口的函數(shù)。具體介紹如下:
public SerialBean(int PortID)
本函數(shù)構(gòu)造一個(gè)指向特定串口的SerialBean,該串口由參數(shù)PortID所指定。PortID = 1 表示COM1,PortID = 2 表示COM2,由此類(lèi)推。
public int Initialize()
本函數(shù)初始化所指定的串口并返回初始化結(jié)果。如果初始化成功返回1,否則返回-1。初始化的結(jié)果是該串口被SerialBean獨(dú)占性使用,其參數(shù)被設(shè)置為9600, N, 8, 1。如果串口被成功初始化,則打開(kāi)一個(gè)進(jìn)程讀取從串口傳入的數(shù)據(jù)并將其保存在緩沖區(qū)中。
public String ReadPort(int Length)
本函數(shù)從串口(緩沖區(qū))中讀取指定長(zhǎng)度的一個(gè)字符串。參數(shù)Length指定所返回字符串的長(zhǎng)度。
public void WritePort(String Msg)
本函數(shù)向串口發(fā)送一個(gè)字符串。參數(shù)Msg是需要發(fā)送的字符串。
public void ClosePort()
本函數(shù)停止串口檢測(cè)進(jìn)程并關(guān)閉串口。
SerialBean的源代碼如下:
package serial;
import java.io.*;
import java.util.*;
import javax.comm.*;
/**
*
* This bean provides some basic functions to implement full dulplex
* information exchange through the srial port.
*
*/
public class SerialBean
{
static String PortName;
CommPortIdentifier portId;
SerialPort serialPort;
static OutputStream out;
static InputStream in;
SerialBuffer SB;
ReadSerial RT;
/**
*
* Constructor
*
* @param PortID the ID of the serial to be used. 1 for COM1,
* 2 for COM2, etc.
*
*/
public SerialBean(int PortID)
{
PortName = "COM" + PortID;
}
/**
*
* This function initialize the serial port for communication. It startss a
* thread which consistently monitors the serial port. Any signal capturred
* from the serial port is stored into a buffer area.
*
*/
public int Initialize()
{
int InitSuccess = 1;
int InitFail = -1;
try
{
portId = CommPortIdentifier.getPortIdentifier(PortName);
try
{
serialPort = (SerialPort)
portId.open("Serial_Communication", 2000);
} catch (PortInUseException e)
{
return InitFail;
}
//Use InputStream in to read from the serial port, and OutputStream
//out to write to the serial port.
try
{
in = serialPort.getInputStream();
out = serialPort.getOutputStream();
} catch (IOException e)
{
return InitFail;
}
//Initialize the communication parameters to 9600, 8, 1, none.
try
{
serialPort.setSerialPortParams(9600,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
} catch (UnsupportedCommOperationException e)
{
return InitFail;
}
} catch (NoSuchPortException e)
{
return InitFail;
}
// when successfully open the serial port, create a new serial buffer,
// then create a thread that consistently accepts incoming signals from
// the serial port. Incoming signals are stored in the serial buffer.
SB = new SerialBuffer();
RT = new ReadSerial(SB, in);
RT.start();
// return success information
return InitSuccess;
}
/**
*
* This function returns a string with a certain length from the incomin
* messages.
*
* @param Length The length of the string to be returned.
*
*/
public String ReadPort(int Length)
{
String Msg;
Msg = SB.GetMsg(Length);
return Msg;
}
/**
*
* This function sends a message through the serial port.
*
* @param Msg The string to be sent.
*
*/
public void WritePort(String Msg)
{
int c;
try
{
for (int i = 0; i Msg.length(); i++)
out.write(Msg.charAt(i));
} catch (IOException e) {}
}
/**
*
* This function closes the serial port in use.
*
*/
public void ClosePort()
{
RT.stop();
serialPort.close();
}
}
2. SerialBuffer
SerialBuffer是本類(lèi)庫(kù)中所定義的串口緩沖區(qū),它定義了往該緩沖區(qū)中寫(xiě)入數(shù)據(jù)和從該緩沖區(qū)中讀取數(shù)據(jù)所需要的函數(shù)。
public synchronized String GetMsg(int Length)
本函數(shù)從串口(緩沖區(qū))中讀取指定長(zhǎng)度的一個(gè)字符串。參數(shù)Length指定所返回字符串的長(zhǎng)度。
public synchronized void PutChar(int c)
本函數(shù)望串口緩沖區(qū)中寫(xiě)入一個(gè)字符,參數(shù)c 是需要寫(xiě)入的字符。
在往緩沖區(qū)寫(xiě)入數(shù)據(jù)或者是從緩沖區(qū)讀取數(shù)據(jù)的時(shí)候,必須保證數(shù)據(jù)的同步,因此GetMsg和PutChar函數(shù)均被聲明為synchronized并在具體實(shí)現(xiàn)中采取措施實(shí)現(xiàn)的數(shù)據(jù)的同步。
SerialBuffer的源代碼如下:
package serial;
/**
*
* This class implements the buffer area to store incoming data from the serial
* port.
*
*/
public class SerialBuffer
{
private String Content = "";
private String CurrentMsg, TempContent;
private boolean available = false;
private int LengthNeeded = 1;
/**
*
* This function returns a string with a certain length from the incomin
* messages.
*
* @param Length The length of the string to be returned.
*
*/
public synchronized String GetMsg(int Length)
{
LengthNeeded = Length;
notifyAll();
if (LengthNeeded Content.length())
{
available = false;
while (available == false)
{
try
{
wait();
} catch (InterruptedException e) { }
}
}
CurrentMsg = Content.substring(0, LengthNeeded);
TempContent = Content.substring(LengthNeeded);
Content = TempContent;
LengthNeeded = 1;
notifyAll();
return CurrentMsg;
}
/**
*
* This function stores a character captured from the serial port to the
* buffer area.
*
* @param t The char value of the character to be stored.
*
*/
public synchronized void PutChar(int c)
{
Character d = new Character((char) c);
Content = Content.concat(d.toString());
if (LengthNeeded Content.length())
{
available = true;
}
notifyAll();
}
}
3. ReadSerial
ReadSerial是一個(gè)進(jìn)程,它不斷的從指定的串口讀取數(shù)據(jù)并將其存放到緩沖區(qū)中。
public ReadSerial(SerialBuffer SB, InputStream Port)
本函數(shù)構(gòu)造一個(gè)ReadSerial進(jìn)程,參數(shù)SB指定存放傳入數(shù)據(jù)的緩沖區(qū),參數(shù)Port指定從串口所接收的數(shù)據(jù)流。
public void run()
ReadSerial進(jìn)程的主函數(shù),它不斷的從指定的串口讀取數(shù)據(jù)并將其存放到緩沖區(qū)中。
ReadSerial的源代碼如下:
package serial;
import java.io.*;
/**
*
* This class reads message from the specific serial port and save
* the message to the serial buffer.
*
*/
public class ReadSerial extends Thread
{
private SerialBuffer ComBuffer;
private InputStream ComPort;
/**
*
* Constructor
*
* @param SB The buffer to save the incoming messages.
* @param Port The InputStream from the specific serial port.
*
*/
public ReadSerial(SerialBuffer SB, InputStream Port)
{
ComBuffer = SB;
ComPort = Port;
}
public void run()
{
int c;
try
{
while (true)
{
c = ComPort.read();
ComBuffer.PutChar(c);
}
} catch (IOException e) {}
}
}
4. SerialExample
SerialExample是本類(lèi)庫(kù)所提供的一個(gè)例程。它所實(shí)現(xiàn)的功能是打開(kāi)串口COM1,對(duì)其進(jìn)行初始化,從串口讀取信息對(duì)其進(jìn)行處理后將處理結(jié)果發(fā)送到串口。
import serial.*;
import java.io.*;
/**
*
* This is an example of how to use the SerialBean. It opens COM1 and reads
* six messages with different length form the serial port.
*
*/
class SerialExample
{
public static void main(String[] args)
{
//TO DO: Add your JAVA codes here
SerialBean SB = new SerialBean(1);
String Msg;
SB.Initialize();
for (int i = 5; i = 10; i++)
{
Msg = SB.ReadPort(i);
SB.WritePort("Reply: " + Msg);
}
SB.ClosePort();
}
}
5. 編譯與調(diào)試
本類(lèi)庫(kù)中使用了Java Communication API (javax.comm)。這是一個(gè)Java擴(kuò)展類(lèi)庫(kù),并不包括在標(biāo)準(zhǔn)的Java SDK當(dāng)中。如果你尚未安裝這個(gè)擴(kuò)展類(lèi)庫(kù)的話,你應(yīng)該從Sun公司的Java站點(diǎn)下載這個(gè)類(lèi)庫(kù)并將其安裝在你的系統(tǒng)上。在所下載的包里面包括一個(gè)安裝說(shuō)明,如果你沒(méi)有正確安裝這個(gè)類(lèi)庫(kù)及其運(yùn)行環(huán)境的話,運(yùn)行這個(gè)程序的時(shí)候你會(huì)找不到串口。
正確安裝Java Communication API并將上述程序編譯通過(guò)以后,你可以按如下方法測(cè)試這個(gè)程序。如果你只有一臺(tái)機(jī)器,你可以利用一條RS-232電纜將COM1和COM2連接起來(lái),在COM1上運(yùn)行SerialExample,在COM2上運(yùn)行Windows提供的超級(jí)終端程序。如果你有兩臺(tái)機(jī)器的話,你可以利用一條RS-232電纜將兩臺(tái)機(jī)器的COM1(或者是COM2)連接起來(lái),在一端運(yùn)行例程,另外一端運(yùn)行Windows提供的超級(jí)終端程序。如果有必要的話,可以對(duì)SerialExample中所聲明的串口進(jìn)行相應(yīng)改動(dòng)。
本程序在Windows 2000 + Java SDK 1.3環(huán)境下編譯通過(guò)并成功運(yùn)行。
把一個(gè)對(duì)象變成01串,然后在需要的地方重新恢復(fù)成對(duì)象。比如可以將對(duì)象保存在文件,然后再讀出??梢詫⒁粋€(gè)對(duì)象通過(guò)網(wǎng)絡(luò)傳輸。
首先,這個(gè)概念的原文是 Serialization,而串行化這個(gè)翻譯并不是很好,個(gè)人傾向于序列化這個(gè)翻譯,下面我都會(huì)用序列化這個(gè)名詞。
所謂序列化是指把一個(gè)對(duì)象通過(guò)某種規(guī)則轉(zhuǎn)化為一串二進(jìn)制串,字符串就是一種二進(jìn)制串。但為何要把對(duì)象轉(zhuǎn)化為二進(jìn)制串呢?因?yàn)槲覀冃枰4婊蛘咴诰W(wǎng)絡(luò)上傳輸它們,而存在于 JVM 內(nèi)存中的對(duì)象并沒(méi)有使用者可見(jiàn)的二進(jìn)制形式。雖然內(nèi)存中的所有東西仍然是二進(jìn)制的,但 JVM 向我們屏蔽了內(nèi)存操作相關(guān)的信息,我們不一定能確定某個(gè) JVM 實(shí)現(xiàn)是如何在內(nèi)存中存儲(chǔ)和組織一個(gè) Java 對(duì)象的內(nèi)容的(C/C++ 就可以直接獲取內(nèi)存塊來(lái)作為序列化的二進(jìn)制串)。
當(dāng)然,光序列化是不夠的,我們還需要反序列化,也就是如何從二進(jìn)制串重新轉(zhuǎn)回對(duì)象。這樣當(dāng)我們從文件中讀取或者在網(wǎng)絡(luò)的另一頭收到某個(gè)對(duì)象的二進(jìn)制串之后,我們才能重新還原回那個(gè)對(duì)象。
Java 默認(rèn)實(shí)現(xiàn)了自己的序列化,就是使用的內(nèi)存數(shù)據(jù)。然而除了 Java 自己的序列化,我們還有很多中序列化方式,例如 hessian。或者說(shuō)將 Java 對(duì)象轉(zhuǎn)成 json、xml 也是一種序列化。
舉一個(gè)非常簡(jiǎn)單的例子,例如我們有一個(gè)對(duì)象 Integer v = 1;。當(dāng)我們使用 hessian 對(duì)其序列化的時(shí)候,我們可能會(huì)拿到 I1 這樣的字串(并不確定 hessian 生成的串是不是真的是這樣,但是也差不多),其中 i 表示類(lèi)型是 Integer,而 1 就是這個(gè)變量的值,而 I1 就是序列化后的二進(jìn)制串(一個(gè)字符串)。