2011-04-23 22 views
2

我有一個包含字節,字符和一個對象的文件,所有這些文件都需要寫入然後讀取。利用Java的不同IO流寫入和讀取這些數據類型的最佳方式是什麼?更具體地說,是否有適當的方式來添加分隔符並識別這些分隔符,然後觸發應該使用的流?我相信我需要澄清在同一個文件中使用多個流,這是我以前從未學習過的。徹底的解釋將是一個足夠的答案。謝謝!寫入/讀取具有不同IO流的文件的正確方法是什麼

+0

莫非你閱讀整個文件作爲一個te流,然後在那裏找到你的分隔符,把這些部分放入字節數組中並將它們作爲各自的流讀取? – Piskvor 2011-04-23 13:09:32

+0

這可能會工作直到需要閱讀的對象,但我覺得可能有更直接的方式。 – 2011-04-23 13:16:18

回答

2

由於已經建議使用EJP,所以使用ObjectOutputStream和ObjectInputStream an0d將你的其他元素作爲一個對象包裝起來。我正在給出答案,以便我可以展示一個例子(在評論中很難做到這一點)EJP - 如果你想將它嵌入到你的問題中,請做,我會刪除答案。

class MyWrapedData implements serializeable{ 
    private String string1; 
    private String string2; 
    private char char1; 
    // constructors 
    // getters setters 
} 

寫入文件:

ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(fileName)); 
out.writeObject(myWrappedDataInstance); 
out.flush(); 

從文件中讀取

ObjectInputStream in = new ObjectInputStream(new FileInputStream(fileName)); 
Object obj = in.readObject(); 
MyWrapedData wraped = null; 
if ((obj != null) && (obj instanceof MyWrappedData)) 
    wraped = (MyWrapedData)obj; 
// get the specific elements from the wraped object 

在這裏看到很明顯的例子:ReadWrite

+0

這是如何讀寫對象的一個​​很好的例子,但是它沒有解決這個事實,即我還在文件中有必須區分目的。 – 2011-04-24 04:11:09

+0

@Trevor Arjeski - 它正是它所顯示的 - 將原語包裝在「MyWrapedData」對象中。我只包括字符串和字符,它也可以是其他任何原始字符。您將保存包裝它們的對象保存在一個文件中,稍後再讀取對象並以相同的方式提取原語。 – MByD 2011-04-24 06:11:15

+0

哦,對不起,我甚至沒有看這個物體​​。現在我懂了!謝謝 – 2011-04-24 13:27:42

1

重新設計文件。按照目前的設計,沒有明智的實施方式。例如,該對象預先設定了一個ObjectOutputStream,它具有一個標題 - 該去哪裏?你怎麼知道從字節切換到字符?

我可能會使用ObjectOutputStream作爲整個事物,並將所有對象寫入對象。然後序列化爲您解決所有這些問題。畢竟你並不關心文件中的內容,而只關心如何讀寫它。

+0

因此,我將所有文件作爲對象轉儲到文件中,我將如何讀取它? – 2011-04-23 13:51:06

+0

@Trevor Arjeski用writeObject()寫入,用readObject()讀取並轉換爲byte [],char [],類,等等。不能更簡單。 – EJP 2011-04-23 22:32:55

0

你可以改變文件的結構嗎?目前尚不清楚,因爲你的問題的第一句與能夠添加描述符相矛盾。如果可以通過更改文件結構,則可以將不同的數據類型輸出到單獨的文件中。我認爲這是劃定數據流的「正確」方式。

如果你用這種方式卡住文件,那麼你需要編寫一個文件結構的接口,這實際上是一個讀取操作的購物清單和大量的異常處理。一種駭人的編程方式,因爲它需要一個十六進制編輯器和大量的試驗和錯誤,但它在某些情況下工作。

+0

我的錯誤是,我確實控制了文件的結構 – 2011-04-23 15:27:16

0

爲什麼不把這個文件寫成XML,可能用一個像XSTream這樣簡單的庫。如果您擔心空間,請使用gzip壓縮包裝它。

0

如果您可以控制文件格式,但它不是一個特別大的文件(即< 1 GiB),您是否考慮過使用Google協議緩衝區?

它們生成解析(和序列化)文件/字節[]內容的代碼。協議緩衝區對包含(1)字段號和(2)類型的每個值使用標記方法,因此它們具有很好的屬性,例如與可選字段的前向/後向兼容性等。它們針對速度和文件大小,爲短字節[]添加大約2字節的開銷,並在大字節[]字段(VarInt編碼長度)上加上2-4個附加字節來編碼長度。

這可能是矯枉過正,但如果你有一堆不同的字段&類型,protobuf真的很有幫助。請參閱:http://code.google.com/p/protobuf/

另一種方法是通過Facebook的Thrift,支持更多的語言,儘管可能在野外使用最少的我最後檢查。

0

如果你的文件的結構是不固定的,考慮使用每種類型的包裝。首先,您需要創建包裝類的接口。

 
interface MyWrapper extends Serializable { 
    void accept(MyWrapperVisitor visitor); 
} 

然後創建MyWrapperVisitor接口...

 
interface MyWrapperVisitor { 
    void visit(MyString wrapper); 
    void visit(MyChar wrapper); 
    void visit(MyLong wrapper); 
    void visit(MyCustomObject wrapper); 
} 

然後創建您的包裝類...

 
class MyString implements MyWrapper { 
    public final String value; 

    public MyString(String value) { 
     super(); 
     this.value = value; 
    } 

    @Override 
    public void accept(MyWrapperVisitor visitor) { 
     visitor.visit(this); 

    } 
} 
. 
. 
. 

最後你讀你的對象......

 
final InputStream in = new FileInputStream(myfile); 
final ObjectInputStream objIn = new ObjectInputStream(in); 
final MyWrapperVisitor visitor = new MyWrapperVisitor() { 
    @Override 
    public void visit(MyString wrapper) { 
     //your logic here 

    } 
    . 
    . 
    . 
}; 

//loop over all your objects here 
final MyWrapper wrapper = (MyWrapper) objIn.readObject(); 
wrapper.accept(visitor); 
相關問題