2

インターフェイスを使用して Java で大きなサイズのオブジェクトをシリアル化しようとしていExternalizableます。

コード:

public class ResultsData  implements Externalizable{
    private static final long serialVersionUID = 1L;

    private ArrayList<ALotOfResults1> results1;
    private ArrayList<ALotOfResults2> results2;
    private ArrayList<ALotOfResults3> results3;

    private int selection;

public ResultsData(){

    results1=new ArrayList<ALotOfResults1>();
    results2=new ArrayList<ALotOfResults2>();
    results3=new ArrayList<ALotOfResults3>();

}

//Getter and setter omited   

@Override
public void writeExternal(ObjectOutput out) throws IOException {

    out.writeObject(results1);
    out.writeObject(results2);
    out.writeObject(results3);
}

@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {

    switch(selection) {
        case 0: 
            results1 = (ArrayList)in.readObject();
            break;
        case 1: 
            in.readObject();
            results2 = (ArrayList)in.readObject();
            break;
        case 2:
            in.readObject();
            in.readObject();
            results3 = (ArrayList)in.readObject();
            break;
    }
}

プログラムの実行中にいっぱいになった 3 つの arrayList は、非常に大きなサイズ (それぞれ 14 MB) です。

コード(読み込み/保存処理):

public class ResultsManagement {

public static ResultsData loadResultsData(String path,ResultsData resultsData) {

    try {            

        FileInputStream fisProd = new FileInputStream(path+".res");
        ObjectInputStream oisProd = new ObjectInputStream(fisProd);      
        resultsData.readExternal(oisProd);
        fisProd.close();

    } catch (IOException ioe) {
        System.out.println("Error de IO: " + ioe.getMessage());
    } catch (ClassNotFoundException cnfe) {
        System.out.println("Error de clase no encontrada: " + cnfe.getMessage());
    } catch (Exception e) {
        System.out.println("Error: " + e.getMessage());
    }
    return resultsData;
}

public static void saveResultsData(ResultsData resultsData,String path) {
    try {   
            FileOutputStream fosProd = new FileOutputStream(path+".res");
            ObjectOutputStream oosProd = new ObjectOutputStream(fosProd);
            resultsData.writeExternal(oosProd);
            fosProd.close();

    } catch (IOException ioe) {
        System.out.println("Error de IO: " + ioe.getMessage());
    } catch (Exception e) {
        System.out.println("Error: " + e.getMessage());
    }
}

}

壊れない条件は、たとえば、ファイルを 1 つだけにしたいということです。Documents/Project/project1.res

他の部分をロードせずに、オブジェクトの一部をロードするにはどうすればよいですか? 出来ますか?たとえば、最初の 2 つの arrayList (results1 と results2) をロードする必要はありませんが、3 つ目の arrayList (results3) のみをロードする必要がありますが、results3 にアクセスする唯一の方法は、results1 と results2 を読み取ることです。

Tinke の回答のコード:

ResultsData クラスで:

public static byte[] serialize(Object obj) throws IOException {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    ObjectOutputStream os = new ObjectOutputStream(out);
    os.writeObject(obj);
    return out.toByteArray();
}

public static Object deserialize(byte[] data) throws IOException, ClassNotFoundException             {
    ByteArrayInputStream in = new ByteArrayInputStream(data);
    ObjectInputStream is = new ObjectInputStream(in);
    return is.readObject();
}

@Override
public void writeExternal(ObjectOutput out) throws IOException {

    byte[] r1 = serialize(results1);
    System.out.println("Bytes in r1: "+r1.length);//42392 Bytes
    out.write(r1);

    byte[] r2 = serialize(results2);
    System.out.println("Bytes in r2: "+r2.length);//19268558 Bytes (a lot of results here)
    out.write(r2);

    out.close();

}

@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {

    switch(selection) {
        case 0: 
            byte[] arrayBytes=new byte[42392];
            in.read(arrayBytes);
            results1 = (ArrayList)deserialize(arrayBytes);
            break;
        case 1: 
            in.skipBytes(42392);
            byte[] arrayBytes2=new byte[19268558];
            in.read(arrayBytes2);
            results2 = (ArrayList)deserialize(arrayBytes2);
            break;
    }
}
4

1 に答える 1

0

一般的な解決策として、データを挿入するときに、各リストのサイズ (バイト単位) を挿入します。次に、読み取り中にサイズを読み取り、スキップするリストごとにそれらのバイト数をスキップします。ユースケースとリスト内のデータを挿入/アクセスする方法に応じて、ソリューションをさらに最適化できます。

于 2014-03-17T18:33:12.540 に答える