Change the path / class name of a serialized Java object after refactoring

亡梦爱人 提交于 2019-12-11 04:11:04

问题


I've launched an app that saves its state with serialized object myfirstpath.UserState.

Now for I want to change the path of this object to mycleanpath.UserState (same object, only the path changes). This will work for new users installing the app for the first time but for users updating the app, they will lose their state.

Is there a way to load the serialized obect myfirstpath.UserState into mycleanpath.UserState ? (without keeping myfirstpath.UserState in my source code of course).


回答1:


I wrote a little piece of code to search/replace the old path/new path in the file containing the serialized data. I convert the file before I load it, this way I can move the serialized class to the new path without keeping copy of this class at the old path. This is how you you use it :

File baseDirectory = applicationContext.getFilesDir();
File file = new File( baseDirectory, "settings.data" );
if (file.exists()) {
    //We have to convert it to newsettings.Data
    byte[] convertedBytes = common.utils.SerializeTools.changePathInSerializedFile(file, "old.path.data", "new.path.data");

    //Write converted file
    File newFile = new File( baseDirectory, "newsettings.data" );
    FileOutputStream fos = new FileOutputStream(newFile);
    fos.write(convertedBytes);
    fos.close();

    //Remove old file
    file.delete();
}

And this is the code of SerializeTools.java. I've learned the java Serialize format in this great blog post http://www.javaworld.com/community/node/2915 .

package common.utils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class SerializeTools {

static public byte[] changePathInSerializedFile(File f, String fromPath, String toPath) throws IOException {
    byte[] buffer = new byte[(int)f.length()];
    FileInputStream in = new FileInputStream(f);
    in.read(buffer);
    in.close();
    return SerializeTools.changePathInSerializedData(buffer,fromPath,toPath);
}

static public byte[] changePathInSerializedData(byte[] buffer, String fromPath, String toPath) throws IOException {
    byte[] search = fromPath.getBytes("UTF-8");
    byte[] replace = toPath.getBytes("UTF-8");

    ByteArrayOutputStream f = new ByteArrayOutputStream();

    for (int i=0;i<buffer.length;i++) {
        //Search 2 bytes ahead to let us modify the 2 bytes length of the class name (see Serialize format http://www.javaworld.com/community/node/2915 )
        boolean found=false;
        int searchMaxIndex=i+search.length+2;
        if (searchMaxIndex<=buffer.length) {
            found=true;
            for (int j=i+2;j<searchMaxIndex;j++) {
                if (search[j-i-2]!=buffer[j]) {
                    found=false;
                    break;
                }
            }
        }
        if (found) {
            int high=((int)(buffer[i])&0xff);
            int low=((int)(buffer[i+1])&0xff);
            int classNameLength=(high<<8)+low;
            classNameLength+=replace.length-search.length;
            //Write new length
            f.write((classNameLength>>8)&0xff);
            f.write((classNameLength)&0xff);
            //Write replacement path
            f.write(replace);
            i=searchMaxIndex-1;
        } else {
            f.write(buffer[i]);
        }
    }

    f.flush();
    f.close();

    return f.toByteArray();
}

}



回答2:


You must implement the method readResolve, mentioned at Serializable Javadoc, in your myfirstpath.UserState class. This readResolve must return the mycleanpath.UserState object.



来源:https://stackoverflow.com/questions/10259760/change-the-path-class-name-of-a-serialized-java-object-after-refactoring

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!