Javaオブジェクトの逆シーケンス化時に発生する例外補足について:java.io.StreamCorruptedException:invalid type code:AC
Javaオブジェクトの逆シーケンス化時に発生する例外補足について:java.io.StreamCorruptedException:invalid type code:AC
皆さん、こんにちは、私はjava学習圏の中で名前を明らかにしたくないので、生を盗む学生です.もし文章に間違いがあれば、許してください.
問題の説明:
//1つのファイルにシーケンス化可能なオブジェクトを書き込むとき、ファイルの最後に1つ以上のシーケンス化可能なオブジェクトを追加するたびに//FileOutputStream(ファイル名、true)を使用してObjectOutputStreamストリームオブジェクトを間接的に構築
理由:
//1つのファイルに1つのファイルのヘッダとファイルボディがあります.FileOutputStream(ファイル名、true)/を複数回使用して構築されたObjectOutputStreamオブジェクトに対して同じファイルにデータを書き込むため、//データを書くたびにこのファイルの末尾にヘッダーを書き込み、書きたいオブジェクトデータを書き込む//読み取り時にこのファイル体のヘッダーに遭遇するとエラーが報告されます.リード時にStreamCorrupted異常が発生
特に注意:
//異常発生コード(プログラム実行時にシステムが自動的にヘッダーを追加する、つまり1回のファイルの最後にヘッダーを追加する)上記の「1回」はjava.exe//FileInputStream(ファイル名、true)で同じファイルにオブジェクトをシーケンス化するため、//毎回ファイルにヘッダーをシーケンス化する実行プロセスを実行することを意味します.逆シーケンス化の場合、//ObjectInputStreamオブジェクトごとにヘッダーが1つしか読み込まれません.2番目のオブジェクトに遭遇するとエラーが発生し、例外が発生します.
具体的なオブジェクトクラスの説明コードは次のとおりです.
解決策一集合にオブジェクトを追加し,集合をファイルから読み出して解析すればよい(ここでは例としてHashSetを採用しているが,仲間たちは他の集合でもあなたのオブジェクトの内容によって判断すればよい)
解決方法二重書きObjectOutputStreamのwriteStreamHeader()方法:
カスタムフロー・クラスの書き換え方法の実装コードを次に示します.
次に、メソッド2の具体的な実装コードを示します.
解決策3逆シーケンス化の過程で、毎回新しいObjectInputStreamを作成してheaderを読み取る.
上のコードの実行結果は次のとおりです.
次に、正しい解決策を見てみましょう.
ここを見るとおおらかな気分になるのではないでしょうか.しかし、この方法では実際に大量のオブジェクトデータを操作するのに時間がかかります.例えば、2つずつ追加すると(追加するオブジェクトの数によって異なります)、集合に記録することができます(集合長が可変なので)、ArrayListを例にとると、インデックスごとに対応するデータが2になります.だから2つ読むたびに新しいoisを作成します
いいねを見終わったらいいね注目してくれる人は運が悪くないそうだよへへへへへ
皆さん、こんにちは、私はjava学習圏の中で名前を明らかにしたくないので、生を盗む学生です.もし文章に間違いがあれば、許してください.
問題の説明:
//1つのファイルにシーケンス化可能なオブジェクトを書き込むとき、ファイルの最後に1つ以上のシーケンス化可能なオブジェクトを追加するたびに//FileOutputStream(ファイル名、true)を使用してObjectOutputStreamストリームオブジェクトを間接的に構築
理由:
//1つのファイルに1つのファイルのヘッダとファイルボディがあります.FileOutputStream(ファイル名、true)/を複数回使用して構築されたObjectOutputStreamオブジェクトに対して同じファイルにデータを書き込むため、//データを書くたびにこのファイルの末尾にヘッダーを書き込み、書きたいオブジェクトデータを書き込む//読み取り時にこのファイル体のヘッダーに遭遇するとエラーが報告されます.リード時にStreamCorrupted異常が発生
特に注意:
//異常発生コード(プログラム実行時にシステムが自動的にヘッダーを追加する、つまり1回のファイルの最後にヘッダーを追加する)上記の「1回」はjava.exe//FileInputStream(ファイル名、true)で同じファイルにオブジェクトをシーケンス化するため、//毎回ファイルにヘッダーをシーケンス化する実行プロセスを実行することを意味します.逆シーケンス化の場合、//ObjectInputStreamオブジェクトごとにヘッダーが1つしか読み込まれません.2番目のオブジェクトに遭遇するとエラーが発生し、例外が発生します.
具体的なオブジェクトクラスの説明コードは次のとおりです.
package io;
import java.io.Serializable;
public class ObjectPerson implements Serializable {
private static final long serialVersionUID = 2017019123524660527L;
private String name;
private String age;
public ObjectPerson(){}
public ObjectPerson(String name,String age){
this.name = name;
this.age = age;
}
public String getName(){
return this.name;
}
public String getAge(){
return this.age;
}
public String toString(){
return "{"+this.name+","+this.age+"}";
}
}
解決策一集合にオブジェクトを追加し,集合をファイルから読み出して解析すればよい(ここでは例としてHashSetを採用しているが,仲間たちは他の集合でもあなたのオブジェクトの内容によって判断すればよい)
ObjectOutputStream oos = null;
try {
HashSet<ObjectPerson> hashSet = new HashSet<ObjectPerson>();
hashSet.add(new ObjectPerson(" ","18"));
hashSet.add(new ObjectPerson(" ","20"));
File file = new File("E://test//Person.txt");
FileOutputStream fos = new FileOutputStream(file);
oos = new ObjectOutputStream(fos);
oos.writeObject(hashSet);
oos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(oos != null) {
oos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
// ,
// , , !
ObjectInputStream ois = null;
try {
FileInputStream fis = new FileInputStream(new File("E://test//Person.txt"));
ois = new ObjectInputStream(fis);
HashSet<ObjectPerson> set= (HashSet<ObjectPerson>)ois.readObject();
Iterator<ObjectPerson> i = set.iterator();
while(i.hasNext()){
ObjectPerson op = i.next();
System.out.println(op);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(ois != null) {
ois.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
解決方法二重書きObjectOutputStreamのwriteStreamHeader()方法:
カスタムフロー・クラスの書き換え方法の実装コードを次に示します.
// ObjectOutputStream , header ( file.length()) < 1
package io;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
public class MyObjectOutputStream extends ObjectOutputStream {
public MyObjectOutputStream(OutputStream out) throws IOException {
super(out);
}
public MyObjectOutputStream() throws IOException, SecurityException {
super();
}
@Override
protected void writeStreamHeader() throws IOException{
return;
}
}
次に、メソッド2の具体的な実装コードを示します.
// , ,
ObjectOutputStream out = null;
ObjectInputStream in = null;
List<ObjectPerson> list = new ArrayList<ObjectPerson>();
list.add(new ObjectPerson(" ", "18"));
list.add(new ObjectPerson(" ", "20"));
String path = "E://test//Person.txt";
try { //
File file = new File(path);
FileOutputStream fos = new FileOutputStream(file,true);
if (file.length() < 1) {
out = new ObjectOutputStream(fos);
} else {
out = new MyObjectOutputStream(fos);
}
//
for (int i = 0; i < list.size(); i++) {
out.writeObject(list.get(i));
}
out.flush();
} catch (Exception ex) {
ex.printStackTrace();
} finally {
try {
if(out != null) { // ,
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(path)));
while (true) {
//EOFException
ObjectPerson op = (ObjectPerson) in.readObject();
System.out.println(op);
}
} catch (EOFException e) {
//
System.out.println(" ");
} catch (Exception ex) {
ex.printStackTrace();
}try {
if(in != null) { // ,
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
解決策3逆シーケンス化の過程で、毎回新しいObjectInputStreamを作成してheaderを読み取る.
// while
ObjectOutputStream oos = null;
try {
FileOutputStream fos = new FileOutputStream(new File("E://test//Person.txt"),true);
oos = new ObjectOutputStream(fos);
oos.writeObject(new ObjectPerson(" ", "18"));
oos.writeObject(new ObjectPerson(" ", "100"));
oos.writeObject(new ObjectPerson(" ", "1000000"));
oos.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(oos != null) {
oos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
ObjectInputStream ois = null;
try {
FileInputStream fis = new FileInputStream(new File("E://test//Person.txt"));
while(fis.available() > 0) {
ois = new ObjectInputStream(fis);
ObjectPerson op = (ObjectPerson)ois.readObject();
System.out.println(op);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(ois != null) {
ois.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
上のコードの実行結果は次のとおりです.
// { ,18}
// java.io.StreamCorruptedException: invalid stream header: 7371007E
, ois header, , header , ( )
次に、正しい解決策を見てみましょう.
ObjectOutputStream oos = null;
try {
FileOutputStream fos = new FileOutputStream(new File("E://test//Person.txt"),true);
oos = new ObjectOutputStream(fos);
//
oos.writeObject(new ObjectPerson(" ", "18"));
oos.writeObject(new ObjectPerson(" ", "100"));
oos.writeObject(new ObjectPerson(" ", "1000000"));
//
// oos.writeObject(new ObjectPerson(" ", "20"));
// oos.writeObject(new ObjectPerson(" ", "21"));
oos.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(oos != null) {
oos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
ObjectInputStream ois = null;
try {
FileInputStream fis = new FileInputStream(new File("E://test//Person.txt"));
// ois
ois = new ObjectInputStream(fis);
ObjectPerson op1 = (ObjectPerson)ois.readObject();
System.out.println(op1);
ObjectPerson op2 = (ObjectPerson)ois.readObject();
System.out.println(op2);
ObjectPerson op3 = (ObjectPerson)ois.readObject();
System.out.println(op3);
// ois
// ois = new ObjectInputStream(fis);
// ObjectPerson op4 = (ObjectPerson)ois.readObject();
// System.out.println(op4);
// ObjectPerson op5 = (ObjectPerson)ois.readObject();
// System.out.println(op5);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(ois != null) {
ois.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
ここを見るとおおらかな気分になるのではないでしょうか.しかし、この方法では実際に大量のオブジェクトデータを操作するのに時間がかかります.例えば、2つずつ追加すると(追加するオブジェクトの数によって異なります)、集合に記録することができます(集合長が可変なので)、ArrayListを例にとると、インデックスごとに対応するデータが2になります.だから2つ読むたびに新しいoisを作成します
いいねを見終わったらいいね注目してくれる人は運が悪くないそうだよへへへへへ