1. 程式人生 > >關於物件的序列化問題(整理收藏)

關於物件的序列化問題(整理收藏)

今天看到一個物件的序列化的知識點。所以整理和收藏了一些東西,說不定以後會用的上。

物件的序列化,好像是一個軟體中很專業的問題。不過這個看著好像是一個基礎問題。是面向物件的一個基礎知識點。

Objective-C序列化和反序列化

http://www.codeios.com/thread-31683-1-1.html
Objective-C可以程式用到的各種物件序列話到檔案,在任何需要的情況下,從檔案中重新讀取資料重新構造物件,下面說一下物件的序列化和反序列化。

利用NSKeyedArchiver把物件序列化到檔案中:
  1. //=================NSKeyedArchiver========================   
  2. NSString *saveStr1 = @"NSKeyedArchiver1";  
  3. NSString *saveStr2 = @"NSKeyedArchiver2";  
  4. NSArray *array = [NSArray arrayWithObjects:saveStr1, saveStr2, nil];   
  5. //—-Save  
  6. //這一句是將路徑和檔名合成檔案完整路徑  
  7. NSString *Path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];   
  8. NSString *filename = [Path stringByAppendingPathComponent:@"saveDatatest"];  
  9. [NSKeyedArchiver archiveRootObject:array toFile:filename];
複製程式碼

利用NSKeyedUnarchiver從檔案中反序列化成物件:

  1. array = [NSKeyedUnarchiver unarchiveObjectWithFile: filename];   
  2.    NSLog(@">>%@",array);

我在這裡說一句,其實不只是NSArray有這個方法,Objective-C中的字典類也有這個功能。他們都可以儲存成xml檔案的。

下邊是另一個有關的東西

物件自動序列化的程式碼例子:

想要對物件進行持久化,就必須實現encode decode方法。如果物件多的話,實在是個體力活。要麼用runtime,要麼用指令碼去生成相應的方法。下面是 CocoaChina 會員 “durian” 分享的物件自動序列化的程式碼例子,

  程式碼解析

// 先看兩個重要的結構體, class和ivar
struct objc_ivar {
    char *ivar_name                                          OBJC2_UNAVAILABLE;
    char *ivar_type                                          OBJC2_UNAVAILABLE;
    int ivar_offset                                          OBJC2_UNAVAILABLE;
#ifdef __LP64__
    int space                                                OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;
 
typedef struct objc_ivar *Ivar;
 
struct objc_class {
    Class isa;
 
#if !__OBJC2__
    Class super_class                                        OBJC2_UNAVAILABLE;
    const char *name                                         OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
    struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache *cache                                 OBJC2_UNAVAILABLE;
    struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;
#endif
 
} OBJC2_UNAVAILABLE;
 
typedef struct objc_class *Class;
 
// 一個class所包含的變數資訊,存在ivars當中。
// Ivar包含有變數的資訊,名字,型別,及距離一個物件例項本身地址的偏移。
// 比如DODog就含有四個變數, name, year, size, point。
// DOServiceDog含有serviceCount一個變數。
// 取得每個ivar所代表的變數的值,然後將其encode,就可以完成序列化。
 
 
- (void)encodeWithCoder:(NSCoder *)encoder {
    Class cls = [self class];
    while (cls != [NSObject class]) {
        unsigned int numberOfIvars = 0;
        // 取得當前class的Ivar陣列
        Ivar* ivars = class_copyIvarList(cls, &numberOfIvars);
        for(const Ivar* p = ivars; p < ivars+numberOfIvars; p++)
        {
            Ivar const ivar = *p;
            // 得到ivar的型別
            const char *type = ivar_getTypeEncoding(ivar);
            // 取得它的名字,比如"year", "name".
            NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
            // 取得某個key所對應的值
            id value = [self valueForKey:key];
            if (value) {
                switch (type[0]) {
                    // 如果是結構體的話,將其轉化為NSData,然後encode.
                    // 其實cocoa會自動將CGRect等四種結構轉化為NSValue,能夠直接用value encode.
                    // 但其他結構體就不可以,所以還是需要我們手動轉一下.
                    case _C_STRUCT_B: {
                        NSUInteger ivarSize = 0;
                        NSUInteger ivarAlignment = 0;
                        // 取得變數的大小
                        NSGetSizeAndAlignment(type, &ivarSize, &ivarAlignment);               
                        // ((const char *)self + ivar_getOffset(ivar))指向結構體變數
                        NSData *data = [NSData dataWithBytes:(const char *)self + ivar_getOffset(ivar)
                                                      length:ivarSize];
                        [encoder encodeObject:data forKey:key];
                    }
                        break;
                    // 如果是其他資料結構,也與處理結構體類似,未實現。
                    // case _C_CHR:    {
                    //}
                    // break;   
                    default:
                        [encoder encodeObject:value
                                       forKey:key];
                        break;
                }                       
            }
        }       
        cls = class_getSuperclass(cls);
    }
}
 
- (id)initWithCoder:(NSCoder *)decoder {
    // NSObject沒有super,所以用了只能用self,應該沒什麼問題。
    // 因為[self init]內部必然會呼叫[super init], 如果一個class有super的話。
    // 這是我的理解,不知道對不對。
    self = [self init];
 
    if (self) {
        Class cls = [self class];
        while (cls != [NSObject
                       class]) {
            unsigned int numberOfIvars = 0;
            Ivar* ivars = class_copyIvarList(cls, &numberOfIvars);
 
            for(const Ivar* p = ivars; p < ivars+numberOfIvars; p++)
            {
                Ivar const ivar = *p;
                const char *type = ivar_getTypeEncoding(ivar);
                NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
                id value = [decoder decodeObjectForKey:key];
                if (value) {
                    switch (type[0]) {
                        case _C_STRUCT_B: {
                            NSUInteger ivarSize = 0;
                            NSUInteger ivarAlignment = 0;
                            NSGetSizeAndAlignment(type, &ivarSize, &ivarAlignment);               
                            NSData *data = [decoder decodeObjectForKey:key];
                            char *sourceIvarLocation = (char*)self+ ivar_getOffset(ivar);                                
                            [data getBytes:sourceIvarLocation length:ivarSize];
                            // 在10.1號我碰到一個很奇怪的問題, 在這個方法內部,我能正確的設定結構體的值。
                            // 但是當self被返回後再列印結構體卻是(0, 0);
                            // 我也不知道如何解決,就加了個memcpy函式,實際上什麼都沒幹,自己copy自己。
                            // 但是值卻被正確的帶出了。
                            // 現在我去掉這個函式,也能正常工作。所以很奇怪,大家看看吧,不知道還會不會出現問題。
//                            memcpy((char *)self + ivar_getOffset(ivar), sourceIvarLocation, ivarSize);
                        }
                            break;
                        default:
                            [self setValue:[decoder decodeObjectForKey:key]
                                    forKey:key];
                            break;
                    }
                }   
            }
            cls = class_getSuperclass(cls);
        }
    }
 
    return self;
}

轉自:http://media.ccidnet.com/media/ciw/681/01370001.htm
  電子郵件的普及拉近了我們與世界的距離,但是針對傳輸電子郵件和釋出新聞而設計的協議卻僅能接收、傳送可顯示的ascii字元。我們怎樣傳輸影象、聲音、應用軟體等大量的二進位制檔案呢?本文的介紹能給您滿意的答案。



  encode和decode即編碼和解碼。

  encode是一種將二進位制檔案轉換成可顯示的ascii碼文字檔案格式的方法,而decode則是將轉換成的ascii檔案再還原為原來的二進位制檔案。



  為什麼要encode和decode

  因為用於傳送電子郵件和釋出新聞的協議被設計成只能傳送可顯示的ascii字元而不能傳送二進位制檔案。但在現實工作中常常需要在internet上通過internetmail和usenetnewsgroups將二進位制檔案傳送出去。

  二進位制資料包括軟體、影象、聲音、影像等,它們使用了一個位元組中所有256個可能的值。這256個值的某些值代表控制字元,它們或者對傳輸過程產生錯誤的控制作用,或者使資料內容不能正確的傳送出去。

  為了順利傳送二進位制資料,傳送前必須首先對該資料編碼,使其成為一個可安全傳輸的字符集組成的檔案。收件人收到編碼檔案後,通過解碼再還原成原來的二進位制檔案。



  encode和decode的方法

  若干年來,出現了許多不同的方案,用來編碼二進位制檔案,以便它們能夠通過netmail和usenet安全成功的傳送出去。這些方案有mime、uu-encoding、xx-encoding和binhexencoding等等。二進位制檔案經過encoding後,其內容看起來就象一些雜亂無章的字元放在一塊,僅在檔案的最開始部分有幾行可讀的句子。

  無論採用那一種encode和decode方法,其基本原理都是一樣:傳送二進位制檔案的使用者先對該檔案進行編碼,然後將編碼轉換後的文字檔案傳送出去。收件人執行decode程式解碼收到的文字檔案即可恢復獲得原來的二進位制檔案。

  當要傳送的檔案很大時還會出現更復雜的情況。某些e-mail和新聞釋出系統對其傳送的檔案大小有限制,即只能傳送小於某一長度的檔案。為了解決這一問題,先要將檔案劃分為多個部分,分別進行編碼,編碼轉換後產生多個文字檔案。收件人必須收到所有劃分的文字檔案後,再進行解碼、合併,然後才能獲得原來的二進位制檔案。

  編碼傳送和解碼的方法並非只有一種,特別是我們將介紹的這四種方法,它們完全不同、相互不相容但均可將二進位制資料編碼成為文字檔案,這使問題變得有點複雜了,傳送人和收件人都必須事先達成一致,即使同一種方法來進行編碼解碼工作。否則收件人無法還原得到原來的二進位制資料。下面我來介紹這常用的四種方法:

  uu-encoding。這是歷史上發明的第一個方法,它的原理很簡單,但也產生過一些問題,在最初的檔案編碼轉換中使用了空格字元,而許多郵件閘道器會將位於行末尾的空格字元剔除,其結果是使收件人獲得的檔案面目全非。後來引入了新的方法才解決了這一問題。

  xx-encoding。此方法很少使用,它的出現是由於uu-encoding在使用初期時出了問題。但用該方法在使用不同字符集進行encoding時同樣要避免使用空格字元。

  base64。該方法是根據mime標準產生的,從而避免了使用上述兩種方法會出現的問題。但是,在某些計算機中沒有該方法所使用的部分字元。除了具有mime的其它優點外,這種方法還是一種最安全的方法。

  binhex。可在macintosh系統環境下傳送檔案的方法。在macintosh機器中檔案由兩個部分組成:“datafork”和“resourcefork”。對檔案編碼轉換時,首先它會再加上一個檔案頭部分,然後將這三個部分組成單一的一個數據流,再稍加壓縮後才進行編碼。

  實際上,還有一些其它使用得不太廣泛的編碼/解碼方法,如ship或btoa等,由於很難在實際工作中碰到,在此不作介紹。



  採用何種方法進行encode和decode

  首先是避免使用xx-encoding,它是一種陳舊的方法。而binhex必須使用於macintosh系統,它的解碼程式使用並不很廣泛,在其它系統中選擇binhex通常是不明智的。的確,binhex聲稱它在編碼時對檔案進行了壓縮,使得傳輸檔案變得更小。但對已經壓縮的檔案,這就不算什麼優點了。

  值得一提的是,對檔案進行壓縮在檔案傳輸中是很重要的。即不要試圖傳送一個未經壓縮的檔案,這會浪費寶貴的頻寬。gif和jpeg影象已經是一個自壓縮的格式。其它型別的資料在傳輸前應該總是先壓縮成zip檔案或其它類似的壓縮格式。

  因此只有uu-encoding和base64這兩種方法了。其主要考慮點要放在所使用的電子郵件軟體上。如果該軟體是mime相容的,提供“attach”按base64方法編碼的檔案的功能,那麼就使用這種方法。對mime資訊而言,base64是首選方法。

  此外,可使用uu-encoding方法,它現在仍然是使用得最廣泛的編碼方法。由於越來越多的軟體已成為mime相容軟體,uu-encoding方法將會被base64方法取而代這。但是隻要有收件人使用老的軟體系統,uu-encoding就有存在的可能性,uu-encoding方法是最安全的。

  請注意,mime相容僅指電子郵件軟體能否處理而言。例如,如果你使用uuenview編碼/解碼軟體將資料編碼成base64格式,然後將編碼資料“attach”在傳送的資訊中,則最終傳送的資訊已經不再是mime相容的了。

  該事實很重要,必須理解清楚。因此,如果你的電子郵件並不帶有“attachment”功能,你又必須使用外部編碼器時,最好使用uu-encoding方法。



  檔案的劃分與否與劃分大小標準

  對所有方法來說還有另一個問題,即檔案劃分問題。對發件人和收件人來說,在一個單一郵件中傳送任何東西是最容易的,你不會被如何對檔案進行劃分及再將它們合併起來所困擾。但是你必須確信發出的郵件在傳輸途中並未丟失內容。現在,對電子郵件來說,這已經不是什麼很大的問題了。通常你能一次傳送數兆位元組的郵件。因此建議你先嚐試送出一個完整的大檔案,然後再詢問你的收件人是否檔案完整。如果未能收到完整檔案,只有靠實驗來找出可安全送出的最大檔案長度。但是對新聞釋出則完全不同,有許多閘道器僅允許傳送小於某長度的新聞。通常一次僅能傳送檔案長度約為一千行。就是說大檔案需按每千行一個部分來劃分,再編碼後才能成功傳輸出去。



  必要的檔案資訊

  當你傳送檔案時,應該讓收件人在作解碼前就知道他們得到的是什麼。同樣,大多數人下載編碼檔案後,在檔案解碼之前想知道的也是他們獲得的究竟是什麼。當他們發現他們下載的東西完全是沒有用處時,他們會變得非常腦火。為了避免這種事情發生,發件人應先送一個小資訊來說明該檔案的內容、目的和功能等。不要只是說,你必須擁有這個檔案,而要包括一些必須的檔案說明資訊。

  對小於一千行的編碼檔案,你可將小資訊檔案附在編碼檔案開始。但對於較大的檔案,你必須單獨將資訊檔案傳送出去。



  主題行的構成

  最後,我們必須面臨的問題是如何為郵件建立一個適當主題。主題建立得好,收件人就能很容易地知道收到的是什麼檔案,對於劃整為零的檔案,收件人也能從主題得知,這是檔案的第幾個部分等等。

  下面是主題的一個例項:

  uudeview0.5aforwindows-uudvw05a.zip(001/004)

  首先在主題行的是對檔案的一個簡短描述,應少於40個字元;然後是一個連線“-”,後跟著編碼前的檔名;最後在括號中是檔案的第幾部分和檔案總共有幾個部分組成。在這個例子中,收件人知道,他還應該在收到第2部分至第4部分後再對檔案進行解碼。象上例這個主題行中包括了所有必要的資訊。

  如果為四個部分的檔案附加一個資訊說明檔案,通常應作為該檔案的第零部分。該部分僅有文字描述,不包含有任何編碼資料。對收件人而言,當看到所收到的郵件中有分成幾個部分的檔案,且有一個郵件的部分代號為“0”,則應先行閱讀這第零部分,在這一部分中收件人能知道所收到的檔案是什麼內容,是否有必要對檔案解碼等等。

  注意,如果編碼檔案只有一個部分,也同樣應該將部分代號包括在主題上,且應為(001/001)。這樣收件人就知道該郵件沒有其它部分了。



  小結

  ·如果你的郵件或新聞是mime相容的,可直接“attach”二進位制檔案時,使用base64方法。如果是使用外部編碼器將編碼資料包括在你傳送的資訊中時,採用uuencoding方法。

  ·通常在郵件傳送時並不必要將編碼檔案分成幾個部分,但是如果是通過新聞組來發布新聞時,每個劃分的檔案部分應不超過1000行。除非檔案的確太大,否則傳送的部分不應超過100個。

  ·傳送檔案時先壓縮。

  ·建立一個好的主題行,將所有必要的資訊包括在內,以方便收件人和解碼。某些軟體如“uudeview”在合併檔案時對主題行有特殊要求。

  ·傳送描述檔案時先將部分代號設定為零。

JAVA中的序列化問題

當兩個程序在進行遠端通訊時,彼此可以傳送各種型別的資料。無論是何種型別的資料,都會以二進位制序列的形式在網路上傳送。傳送方需要把這個Java物件轉換為位元組序列,才能在網路上傳送;接收方則需要把位元組序列再恢復為Java物件。

把Java物件轉換為位元組序列的過程稱為物件的序列化。

把位元組序列恢復為Java物件的過程稱為物件的反序列化。

物件的序列化主要有兩種用途:

1) 把物件的位元組序列永久地儲存到硬碟上,通常存放在一個檔案中;

2) 在網路上傳送物件的位元組序列。

一.             JDK類庫中的序列化API

java.io.ObjectOutputStream代表物件輸出流,它的writeObject(Object obj)方法可對引數指定的obj物件進行序列化,把得到的位元組序列寫到一個目標輸出流中。

java.io.ObjectInputStream代表物件輸入流,它的readObject()方法從一個源輸入流中讀取位元組序列,再把它們反序列化為一個物件,並將其返回。、

只有實現了Serializable和Externalizable介面的類的物件才能被序列化。Externalizable介面繼承自Serializable介面,實現Externalizable介面的類完全由自身來控制序列化的行為,而僅實現Serializable介面的類可以採用預設的序列化方式 。

物件序列化包括如下步驟:

1) 建立一個物件輸出流,它可以包裝一個其他型別的目標輸出流,如檔案輸出流;

2) 通過物件輸出流的writeObject()方法寫物件。

物件反序列化的步驟如下:

1) 建立一個物件輸入流,它可以包裝一個其他型別的源輸入流,如檔案輸入流;

2) 通過物件輸入流的readObject()方法讀取物件。

下面讓我們來看一個對應的例子,類的內容如下:

import java.io.*;

import java.util.Date;

/**

 * 物件的序列化和反序列化測試類.    

 * @version 1.0

 * Creation date: 2007-9-15 - 下午21:45:48

 */

public class ObjectSaver {

       /**

        * @param args

        * Creation date: 2007-9-15 - 下午21:45:37

        */

       public static void main(String[] args) throws Exception {

              ObjectOutputStream out = new ObjectOutputStream

                     (new FileOutputStream("D:""objectFile.obj"));

              //序列化物件

              Customer customer = new Customer("阿蜜果", 24);

              out.writeObject("你好!");

              out.writeObject(new Date());

              out.writeObject(customer);

              out.writeInt(123); //寫入基本型別資料

              out.close();

              //反序列化物件

              ObjectInputStream in = new ObjectInputStream

                     (new FileInputStream("D:""objectFile.obj"));

              System.out.println("obj1=" + (String) in.readObject());

              System.out.println("obj2=" + (Date) in.readObject());

              Customer obj3 = (Customer) in.readObject();

              System.out.println("obj3=" + obj3);

              int obj4 = in.readInt();

              System.out.println("obj4=" + obj4);

              in.close();

       }

}

class Customer implements Serializable {

       private String name;

       private int age;

       public Customer(String name, int age) {

              this.name = name;

              this.age = age;

       }

       public String toString() {

              return "name=" + name + ", age=" + age;

       }

}

       輸出結果如下:

obj1=你好!

obj2=Sat Sep 15 22:02:21 CST 2007

obj3=name=阿蜜果, age=24

obj4=123

    因此例比較簡單,在此不再詳述。

二.實現Serializable介面

ObjectOutputStream只能對Serializable介面的類的物件進行序列化。預設情況下,ObjectOutputStream按照預設方式序列化,這種序列化方式僅僅對物件的非transient的例項變數進行序列化,而不會序列化物件的transient的例項變數,也不會序列化靜態變數。

當ObjectOutputStream按照預設方式反序列化時,具有如下特點:

1)              如果在記憶體中物件所屬的類還沒有被載入,那麼會先載入並初始化這個類。如果在classpath中不存在相應的類檔案,那麼會丟擲ClassNotFoundException;

2)              在反序列化時不會呼叫類的任何構造方法。

如果使用者希望控制類的序列化方式,可以在可序列化類中提供以下形式的writeObject()和readObject()方法。

private void writeObject(java.io.ObjectOutputStream out) throws IOException

private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;

當ObjectOutputStream對一個Customer物件進行序列化時,如果該物件具有writeObject()方法,那麼就會執行這一方法,否則就按預設方式序列化。在該物件的writeObjectt()方法中,可以先呼叫ObjectOutputStream的defaultWriteObject()方法,使得物件輸出流先執行預設的序列化操作。同理可得出反序列化的情況,不過這次是defaultReadObject()方法。

有些物件中包含一些敏感資訊,這些資訊不宜對外公開。如果按照預設方式對它們序列化,那麼它們的序列化資料在網路上傳輸時,可能會被不法份子竊取。對於這類資訊,可以對它們進行加密後再序列化,在反序列化時則需要解密,再恢復為原來的資訊。

預設的序列化方式會序列化整個物件圖,這需要遞迴遍歷物件圖。如果物件圖很複雜,遞迴遍歷操作需要消耗很多的空間和時間,它的內部資料結構為雙向列表。

在應用時,如果對某些成員變數都改為transient型別,將節省空間和時間,提高序列化的效能。

三.             實現Externalizable介面

Externalizable介面繼承自Serializable介面,如果一個類實現了Externalizable介面,那麼將完全由這個類控制自身的序列化行為。Externalizable介面聲明瞭兩個方法:

public void writeExternal(ObjectOutput out) throws IOException

public void readExternal(ObjectInput in) throws IOException , ClassNotFoundException

前者負責序列化操作,後者負責反序列化操作。

在對實現了Externalizable介面的類的物件進行反序列化時,會先呼叫類的不帶引數的構造方法,這是有別於預設反序列方式的。如果把類的不帶引數的構造方法刪除,或者把該構造方法的訪問許可權設定為private、預設或protected級別,會丟擲java.io.InvalidException: no valid constructor異常。

四.             可序列化類的不同版本的序列化相容性

凡是實現Serializable介面的類都有一個表示序列化版本識別符號的靜態變數:

private static final long serialVersionUID;

以上serialVersionUID的取值是Java執行時環境根據類的內部細節自動生成的。如果對類的原始碼作了修改,再重新編譯,新生成的類檔案的serialVersionUID的取值有可能也會發生變化。

類的serialVersionUID的預設值完全依賴於Java編譯器的實現,對於同一個類,用不同的Java編譯器編譯,有可能會導致不同的serialVersionUID,也有可能相同。為了提高哦啊serialVersionUID的獨立性和確定性,強烈建議在一個可序列化類中顯示的定義serialVersionUID,為它賦予明確的值。顯式地定義serialVersionUID有兩種用途:

1)              在某些場合,希望類的不同版本對序列化相容,因此需要確保類的不同版本具有相同的serialVersionUID;

2)              在某些場合,不希望類的不同版本對序列化相容,因此需要確保類的不同版本具有不同的serialVersionUID。

/*
* @(#)BeanXML.java 1.00 2005-10-7
*
* Copyright 2005 BeanSoft Studio. All rights reserved.
* PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package beansoft.xml;

import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;

/**
* BeanXML
*
* Chinese documents:
*
* @author BeanSoft
* @version 1.00 2005-10-7
*/
public class BeanXML {
/**
* 使用 java.beans.XMLEncoder 將 物件編碼為 XML.
* @param bean 物件
* @return String - 編碼後的 XML
*/
public static String encodeBean(Object bean) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
XMLEncoder encoder = new XMLEncoder(out);
encoder.writeObject(bean);
encoder.close();

return out.toString();
}

/**
* 使用 java.beans.XMLDecoder 將 XML 解碼為 物件.
* @param xml - 編碼後的 XML
* @return Object 反編碼後的物件
*/
public static Object decodeBean(String xml) {
try {
// FIXME 必須使用 GBK 解碼才對, 否則出來的文字是亂碼?
XMLDecoder decoder = new XMLDecoder(new ByteArrayInputStream(xml.getBytes("GBK")));
return decoder.readObject();
} catch (UnsupportedEncodingException e) {
}

return null;
}
}

相關推薦

關於物件序列問題整理收藏

今天看到一個物件的序列化的知識點。所以整理和收藏了一些東西,說不定以後會用的上。 物件的序列化,好像是一個軟體中很專業的問題。不過這個看著好像是一個基礎問題。是面向物件的一個基礎知識點。 Objective-C序列化和反序列化http://www.codeios.com/thread-31683-1-1.h

Java高階系列——不得不說的物件序列serialize

1、什麼是Java物件序列化? Java的物件序列化是將那些實現了Serializable介面的物件轉化成一個位元組序列,並能夠在以後將這些位元組序列完全恢復成原來的物件。簡單來說序列化就是將物件轉化成位元組流,反序列化就是將位元組流轉化成物件。 物件必須在

Android物件序列Activity之間傳遞物件,Parcelable小例子

Android中為了能夠在Activity之間傳遞值,需要只用Intent中的put函式。 其中bundle.putParcelable可以實現傳遞物件,但是這個物件的類必須實現Parcelable接口才能夠使用。 下面是一個簡單的在Activity之間傳遞物件的例子

Java IO操作——物件序列Serializable介面、ObjectOutputStream、以及與Externalizable介面的用法和區別

學習目標 掌握物件序列化的作用。 掌握Serializable介面的作用。 可以使用ObjectOutputStream進行物件的序列化操作。 可以使用ObjectInputStream進行物件的反序

序列層序

反序列化操作(層序):將序列生成層序遍歷的二叉樹 取出string陣列中的每一個str[i]元素,根據str[i]是否是#進行處理, (1)當str[i]=="#"時,返回NULL,不建立新節點 (2)當str[i]!="#"時,建立新的節點,返回該節點 #include &

序列先序

先序遍歷的序列化操作: 使用先序遍歷遍歷每一個節點, (1)當該結點的值為NULL時,返回"#!" (2)當該結點的值不為NULL時,str = T->data + "!"; (3)遞迴遍歷左子樹、右子樹 str = str + preSerialize(T->lch

序列先序

【注意】 反序列化操作,只有先序序列化,從來沒聽說過中序序列化、後序序 列化。實際上有中序後序序列化反序列化 要求:將vector<string> str容器中的字串生成二叉樹 解答: 依次獲取每一個字串str[index],進行序列化操作:

序列先序——split : string-->vector<string>

反序列化:將string生成二叉樹 先序反序列化操作具體步驟: (1)先將string字串進行分割,生成多個string構成的集合儲存在vector<string>中; (2)將vec<string>中的每一個元素存入到queue<string>中

《Java工程師成神之路-基礎篇》Java基礎知識——序列已完結

本文是《成神之路系列文章》中的一篇,主要是關於Java中序列化的一些介紹。 持續更新中 Java物件的序列化與反序列化 深入分析Java的序列化與反序列化 單例與序列化的那些事兒 Google Protocol Buffer 的使用和原理 拓展內容 關於 Java

Java---序列與反序列ObjectOutputStream/ObjectInputStream

一:什麼是序列化與反序列化 序列化: 將記憶體中的物件變為二進位制位元組流的形式進行傳輸或儲存在文字中; 並不是所有物件都要被序列化, 一般物件要進行傳輸需要被序列化; 物件若要被序列化輸出,該類需要實現Serializable介面。即只有實現Serializable

配置RedisTemplate、JedisPoolConfig、JedisConnectionFactory+自定義序列 java方式

java方式配置RedisTemplate   //spring注入ben    //@Bean(name = "redisTemplate") public RedisTemplate initRedisTemplate(){ JedisPoolConfig poolCo

序列json,shelve

    比如,我們在python程式碼中計算的一個數據需要給另外一段程式使用,那我們怎麼給? 現在我們能想到的方法就是存在檔案

JAVA 序列 和 反序列 Externalizable Serializable 那些事

序列化控制 當我們對序列化進行控制時,可能某個特定子物件不想讓Java序列化機制自動儲存與恢復。如果子物件表示的是我們不希望將其序列化的敏感資訊(如密碼),通常會面臨這種情況。即使物件中的這些資訊

java基礎類庫學習六.6物件序列

前言 物件序列化:允許把記憶體中的物件轉換成平臺無關的二進位制流,從而把這種二進位制流持久的儲存自磁碟上,通過網路將這種二進位制流傳輸到網路的另一個節點,其他程式一旦獲得了這種二進位制流,都可以將這種二進位制流恢復成原來的java物件 物件的序列化是指將一個java物件寫入io流中,

IO流File類,IO流的分類,位元組流和字元流,轉換流,緩衝流,物件序列

1.File類 File類可以在程式中 操作檔案和目錄。File類是通過建立File類物件,在呼叫File類的物件來進行相關操作的。 示例: --------------------- 本文來自 dajiahuooo 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net/

JavaSE——序列與反序列深拷貝使用了該技術克隆物件原型模式

在最近學習Spring原始碼系列的時候,接觸到了一個設計模式——原型模式(資料內容相同,但是是兩個完全不同的物件例項) 原理就是實現介面重寫clone方法。如果單純的呼叫super.clone方法就屬於淺拷貝,只會拷貝8大基本資料型別和String型別。而Date和物件屬性就是引用的同一個物

Java IO詳解六)------序列與反序列物件

1、什麼是序列化與反序列化? 序列化:指把堆記憶體中的 Java 物件資料,通過某種方式把物件儲存到磁碟檔案中或者傳遞給其他網路節點(在網路上傳輸)。這個過程稱為序列化。通俗來說就是將資料結構或物件轉換成二進位制串的過程   反序列化:把磁碟檔案中

Java基礎五十六-物件序列

物件例項化 所謂的物件序列化指的是將記憶體中儲存的物件以二進位制資料流的形式進行處理,可以實現物件的儲存或者是網路傳輸。 、 @SuppressWarnings("serial") class Person implements Serializable {

Java物件序列Serialization和反序列詳解

1.序列化和反序列化 序列化(Serialization)是將物件的狀態資訊轉化為可以儲存或者傳輸的形式的過程,一般將一個物件儲存到一個儲存媒介,例如檔案或記憶體緩衝等,在網路傳輸過程中,可以是位元組或者XML等格式;而位元組或者XML格式的可以還原成完全相等

Java 物件序列和反序列 實現 Serializable 介面

序列化和反序列化的概念 把物件轉換為位元組序列的過程稱為物件的序列化。 把位元組序列恢復為物件的過程稱為物件的反序列化。 物件的序列化主要有兩種用途: 把物件的位元組序列永久地儲存到硬碟上,通常存放在一個檔案中; 在網路上傳送物件的位元組序列。 JDK