2009-06-10 17 views
5

Tôi đang sử dụng ObjectOutputStream để tạo một tệp các đối tượng được tuần tự hóa. Sau đó tôi sử dụng một ObjectInputStream với phương thức readObject() để lấy các đối tượng ra khỏi tệp.Lỗi ObjectInputStream

Lần đầu tiên nó hoạt động tốt. Có nghĩa là nếu tập tin không tồn tại và tôi mở nó sau đó nối thêm bất kỳ số lượng các đối tượng, tôi có thể mở đối tượng ObjectInputStream và truy cập tất cả các đối tượng.

Tuy nhiên, nếu sau đó tôi mở cùng một tệp (sử dụng tùy chọn chắp thêm) và thêm đối tượng khác, đối tượng ObjectInputStream nhận được lỗi java.io.StreamCorruptedException: "invalid type code: AC", nơi các đối tượng mới sẽ bắt đầu.

Có ai khác chạy vào điều này không? Tôi thậm chí đã quay trở lại một số ví dụ sách giáo khoa cơ bản từ cuốn sách Deitel và vẫn nhận được cùng một lỗi.

Chỉnh sửa: Tôi đã tìm thấy điều này - Bạn không thể nối thêm vào cuối luồng đã được tuần tự hóa sau khi đã đóng và mở lại ở chế độ nối thêm. Các ghi sẽ xuất hiện để làm việc, nhưng khi bạn đi đọc tệp sau này, bạn sẽ nhận được một java.io.StreamCorruptedException. tại "http://mindprod.com/jgloss/gotchas.html#SERIALIZATION"

Trả lời

4

Mỗi đối tượng được serailised như một phần của luồng đối tượng, không phải là một cá nhân. "Giao thức tuần tự hóa luồng đối tượng", giống như hầu hết các định dạng tệp (nhưng không phải ZIP!) Đều có tiêu đề. Đây là những gì mỗi mới ObjectInputStream hy vọng sẽ chỉ tìm thấy ở đầu của một tập tin. Đặt nó ở giữa một dòng sẽ không hoạt động. Ngoài ra các dòng có backreferences, do đó, không có đối tượng được viết ra hai lần (trừ khi có quy định khác).

Vì vậy, những gì bạn cần phải tạo mới ObjectInputStream để khớp với mỗi ObjectOutputStream. Có một số đệm nội bộ, nếu điều đó gây ra sự cố bạn cần phải chia luồng trước khi cho phép Object(In|Out)putStream vào đó.

+0

Không có mối tương quan trực tiếp giữa luồng đầu ra và luồng đầu vào tại đây. Họ thậm chí có thể không được chạy trên cùng một ngày hoặc máy trạm. Một trong những lưu thông tin vào một tập tin mà tại một số điểm sau đó một quá trình khác phải mở và đọc. –

1

Nếu nhà sản xuất và người tiêu dùng của luồng độc lập, bạn nên ghi đè tệp đầu ra mỗi lần và thêm tệp dấu thời gian để người tiêu dùng biết thời gian tải lại.

Ví dụ,

SomeObject[] obj = new SomeObject[numObjects]; 
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("file"); 
out.writeObject(obj); 
out.close(); 
long ts = System.currentTimeMillis(); 
ObjectOutputStream tout = 
     new ObjectOutputStream(new FileOutputStream("timestamp.obj"); 
tout.writeObject(new Long(ts)); 

Người tiêu dùng sau đó có thể thăm dò ý kiến ​​các tập tin timestamp.obj cứ mỗi vài phút và nếu nó đã thay đổi, mở lại SomeObject[] từ suối.

ObjectInputStream in = 
     new ObjectInputStream(new FileInputStream("timestamp.obj")); 
Long ts = (Long)in.readObject(); 

if (ts > prevts) { 
    ObjectInputStream in2 = new ObjectInputStream(new FileInputStream("file")); 
    SomeObject[] obj = (SomeObject[])in.readObject(); 
    prevts = ts; 
} 
1

ObjectStream chứa đầu trang và chân trang. Nó cũng chứa thông tin nhà nước, tức là những gì nó viết dựa trên các đối tượng mà nó đã viết.

Vì vậy, bạn không thể chỉ thêm vào một ObjectStream hiện có. Những gì bạn có thể làm là viết lại tệp và thêm đối tượng mỗi khi bạn làm hoặc kết hợp luồng với giao thức của riêng bạn để bạn có thể viết/đọc nhiều luồng một cách chính xác.

ObjectStream hoạt động tốt nhất khi bạn đọc/ghi dữ liệu với cùng một cơ sở mã (đặc biệt là cho các lớp đọc/ghi) ObjectStream không được thiết kế để di động trên các phiên bản mã hoặc giữa các ứng dụng khác nhau.

+0

khi chúng tôi sử dụng luồng nào? vui lòng trả lời –

+0

@AnshulParashar ObjectOutputStream và ObjectInputStream. –

Các vấn đề liên quan