Android 将捆绑包保存到文件
我有上面提到的代码。我只想把包保存到文件中。我找到了write方法,但我无法传递一个bundle,只能传递一个byte[]。我尝试将bundle转换为byte[],但没有成功。我该怎么做才能让它工作?最有效的方法是什么?没有通用的方法从持久性存储中保存和恢复捆绑包。这是因为Parcel类不提供任何android版本兼容性保证。所以我们最好不要序列化它 但若你们真的需要的话,你们可以通过可打包的接口对包进行序列化。将包转换为包(writeToParcel()/readFromParcel()),然后使用包的marshall()和unmarshall()方法获取字节[]。将字节数组保存/加载到文件。但总有一天,如果用户将其Android操作系统更新为新版本,您将无法恢复数据 使用ObjectOutput/InputStream序列化捆绑包有一种合法但非常完整且不可靠的方法。(获取所有密钥,遍历密钥并将可序列化的密钥=值对保存到文件中,然后从文件中读取密钥=值对,确定值的类型,通过适当的PUTXX(密钥,值)方法将数据放回捆绑包中),但这不值得) 我建议您将自定义的可序列化结构放在Bundle中,以便在其中存储所有必需的值,并仅从文件中保存/加载此结构Android 将捆绑包保存到文件,android,Android,我有上面提到的代码。我只想把包保存到文件中。我找到了write方法,但我无法传递一个bundle,只能传递一个byte[]。我尝试将bundle转换为byte[],但没有成功。我该怎么做才能让它工作?最有效的方法是什么?没有通用的方法从持久性存储中保存和恢复捆绑包。这是因为Parcel类不提供任何android版本兼容性保证。所以我们最好不要序列化它 但若你们真的需要的话,你们可以通过可打包的接口对包进行序列化。将包转换为包(writeToParcel()/readFromParcel()),然
或者找到一种更好的方法来管理数据,而不必使用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);
}
}