Android 将捆绑包保存到文件

Android 将捆绑包保存到文件,android,Android,我有上面提到的代码。我只想把包保存到文件中。我找到了write方法,但我无法传递一个bundle,只能传递一个byte[]。我尝试将bundle转换为byte[],但没有成功。我该怎么做才能让它工作?最有效的方法是什么?没有通用的方法从持久性存储中保存和恢复捆绑包。这是因为Parcel类不提供任何android版本兼容性保证。所以我们最好不要序列化它 但若你们真的需要的话,你们可以通过可打包的接口对包进行序列化。将包转换为包(writeToParcel()/readFromParcel()),然

我有上面提到的代码。我只想把包保存到文件中。我找到了write方法,但我无法传递一个bundle,只能传递一个byte[]。我尝试将bundle转换为byte[],但没有成功。我该怎么做才能让它工作?最有效的方法是什么?

没有通用的方法从持久性存储中保存和恢复捆绑包。这是因为Parcel类不提供任何android版本兼容性保证。所以我们最好不要序列化它

但若你们真的需要的话,你们可以通过可打包的接口对包进行序列化。将包转换为包(writeToParcel()/readFromParcel()),然后使用包的marshall()和unmarshall()方法获取字节[]。将字节数组保存/加载到文件。但总有一天,如果用户将其Android操作系统更新为新版本,您将无法恢复数据

使用ObjectOutput/InputStream序列化捆绑包有一种合法但非常完整且不可靠的方法。(获取所有密钥,遍历密钥并将可序列化的密钥=值对保存到文件中,然后从文件中读取密钥=值对,确定值的类型,通过适当的PUTXX(密钥,值)方法将数据放回捆绑包中),但这不值得)

我建议您将自定义的可序列化结构放在Bundle中,以便在其中存储所有必需的值,并仅从文件中保存/加载此结构


或者找到一种更好的方法来管理数据,而不必使用Bundle。

您可以这样做

  Bundle bundle;
  //set data to bundle
  //......


  File file = new File(context.getFilesDir().getAbsolutePath()  + "/data/");
                FileOutputStream fos;
                try {
                     fos = new FileOutputStream(file);
                     //fos.write
                     fos.close();
                } catch (FileNotFoundException exp1) {
                    exp1.printStackTrace();
                } catch ( IOException exp2) {
                    exp2.printStackTrace();
                }

在这里,想法很简单。您将
捆绑包
传递给此方法,然后提取其中的任何数据(在本例中,我们有一个带有
键的字符串
),然后将其写入一个文件。

我不喜欢上面注释中的代码格式,因此您可以这样读取它:

public void write(String fileName, Bundle bundle)
    {
        File root = Environment.getExternalStorageDirectory();
        File outDir = new File(root.getAbsolutePath() + File.separator + "My Bundle");
        if (!outDir.isDirectory())
        {
            outDir.mkdir();
        }
        try
        {
            if (!outDir.isDirectory())
            {
                throw new IOException("Unable to create directory My bundle. Maybe the SD card is mounted?");


    }
        File outputFile = new File(outDir, fileName);
        writer = new BufferedWriter(new FileWriter(outputFile));
        String value=bundle.getString("key");
        writer.write(value);
        Toast.makeText(context.getApplicationContext(), "Report successfully saved to: " + outputFile.getAbsolutePath(), Toast.LENGTH_LONG).show();
        writer.close();
    } catch (IOException e)
    {
        Log.w("error", e.getMessage(), e);
        Toast.makeText(context, e.getMessage() + " Unable to write to external storage.", Toast.LENGTH_LONG).show();
    }

}
请这样读:

Bundle in=yourBundle;
FileOutputStream fos = context.openFileOutput(localFilename, Context.MODE_PRIVATE);
Parcel p = Parcel.obtain(); //creating empty parcel object
in.writeToParcel(p, 0); //saving bundle as parcel 
fos.write(p.marshall()); //writing parcel to file
fos.flush();
fos.close();

下面是一个函数,可以帮助您将
捆绑包
转换为
JSONObject
,请注意,只有当捆绑包仅包含
int
s和
字符串
s时,该函数才起作用

try {
    FileInputStream fis = openFileInput(localFilename);
    byte[] array = new byte[(int) fis.getChannel().size()];
    fis.read(array, 0, array.length);
    fis.close();
    parcel.unmarshall(array, 0, array.length);
    parcel.setDataPosition(0);
    Bundle out = parcel.readBundle();
    out.putAll(out);
} catch (FileNotFoundException fnfe) {
} catch (IOException ioe) {
} finally {
    parcel.recycle();
}
公共静态JSONObject Bundle JSONObject(Bundle Bundle){
试一试{
JSONObject输出=新的JSONObject();
for(字符串键:bundle.keySet()){
Object=bundle.get(key);
if(整数的对象实例| |字符串的对象实例)
输出。放置(键、对象);
其他的
抛出新的RuntimeException(“只能提取整数和字符串”);
}
返回输出;
}捕获(JSONException e){
抛出新的运行时异常(e);
}
}
公共静态捆绑包JSONObject绑定(JSONObject JSONObject){
试一试{
Bundle=新Bundle();
迭代器keys=jsonObject.keys();
while(keys.hasNext()){
字符串键=(字符串)键。下一步();
Object=jsonObject.get(key);
if(字符串的对象实例)
bundle.putString(键,(字符串)对象);
else if(整数的对象实例)
bundle.putInt(键,(整数)对象);
其他的
抛出新的RuntimeException(“只能重新提取整数和字符串”);
}
返回包;
}捕获(JSONException e){
抛出新的运行时异常(e);
}
}

无法将捆绑包保存到本地文件。您将获得非序列化异常。可能还有其他快捷方式可供存储。在阅读和构建原始对象后,无法100%确定

我认为最好的方法是静态可序列化或任何东西,因为Bundle可以从键进行序列化、序列化和非序列化,您可以使用json或任何东西。例如,如果您将在server和receiver中使用相同的类

bundle->serializable_object->json->file->serializable_object->bundle


任何保证正常工作的操作系统版本

为什么要尝试将捆绑包写入文件?相反,为什么不将捆绑包的数据写入文件?解释一下为什么需要它。你永远不应该这样做。从
Parcel.marshall()
文档中,您在此处检索的数据不得放置在任何类型的永久性存储中(在本地磁盘上、通过网络等)。为此,应该使用标准序列化或其他类型的通用序列化机制。包裹编组表示法针对本地IPC进行了高度优化,因此不会试图保持与在不同版本的平台中创建的数据的兼容性。@vmironov那么,您对序列化有何建议?是的,如果用户有时更新android版本,您可能无法恢复包裹。因此,请不要以这种方式保存关键数据)很抱歉,这是我的错误,因为它是我们正在保存捆绑包的包裹对象;字节[]数组=新字节[(int)fis.getChannel().size()];fis.read(数组,0,数组长度);fis.close();包裹解组(数组,0,数组.长度);包裹。setDataPosition(0);Bundle out=parcel.readBundle();全部(全部)出局;包裹回收();非常感谢您的
setDataPosition()
提示!谁知道它必须被叫来!不要这样做。表示“不适合将任何地块数据放入永久性存储”
public static JSONObject bundleToJsonObject(Bundle bundle) {
    try {
        JSONObject output = new JSONObject();
        for( String key : bundle.keySet() ){
            Object object = bundle.get(key);
            if(object instanceof Integer || object instanceof String)
                    output.put(key, object);
            else
                throw new RuntimeException("only Integer and String can be extracted");
        }
        return output;
    } catch (JSONException e) {
        throw new RuntimeException(e);
    }
}

public static Bundle JsonObjectToBundle(JSONObject jsonObject) {
    try {
        Bundle bundle = new Bundle();
        Iterator<?> keys = jsonObject.keys();
        while( keys.hasNext() ){
            String key = (String)keys.next();
            Object object = jsonObject.get(key);
            if(object instanceof String)
                bundle.putString(key, (String) object);
            else if(object instanceof Integer)
                bundle.putInt(key, (Integer) object);
            else
                throw new RuntimeException("only Integer and String can be re-extracted");
        }
        return bundle;
    } catch (JSONException e) {
        throw new RuntimeException(e);
    }
}