1

我已经启动了一个应用程序,它使用序列化对象 myfirstpath.UserState 保存其状态。

现在我想将此对象的路径更改为 mycleanpath.UserState (相同的对象,只有路径更改)。这将适用于第一次安装应用程序的新用户,但对于更新应用程序的用户,他们将失去他们的状态。

有没有办法将序列化的对象 myfirstpath.UserState 加载到 mycleanpath.UserState 中?(当然没有在我的源代码中保留 myfirstpath.UserState )。

4

2 回答 2

3

我写了一小段代码来搜索/替换包含序列化数据的文件中的旧路径/新路径。我在加载文件之前对其进行了转换,这样我可以将序列化的类移动到新路径,而无需将此类的副本保留在旧路径中。这就是你使用它的方式:

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();
}

这是 SerializeTools.java 的代码。我在这篇很棒的博客文章http://www.javaworld.com/community/node/2915中学习了 java 序列化格式。

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();
}

}
于 2012-04-25T22:56:31.447 回答
1

您必须在您的类中实现Serializable JavadocreadResolve中提到的方法。这必须返回对象。myfirstpath.UserStatereadResolvemycleanpath.UserState

于 2012-04-21T14:55:17.407 回答