Bir nesneyi nasıl serileştiririm ve Android'de bir dosyaya kaydederim?


128

Diyelim ki basit bir sınıfım var ve bir nesne olarak somutlaştırıldığında, içeriğini bir dosyaya serileştirmek ve bu dosyayı daha sonra yükleyerek geri almak istiyorum ... Buradan nereden başlayacağımı bilmiyorum, Bu nesneyi bir dosyaya serileştirmek için ne yapmam gerekiyor?

public class SimpleClass {
   public string name;
   public int id;
   public void save() {
       /* wtf do I do here? */
   }
   public static SimpleClass load(String file) {
       /* what about here? */
   }
}

Bu muhtemelen dünyadaki en kolay sorudur, çünkü bu .NET'te gerçekten basit bir görevdir, ancak Android'de oldukça yeniyim, bu yüzden tamamen kayboldum.

Yanıtlar:


250

Kaydetme (istisna işleme kodu olmadan):

FileOutputStream fos = context.openFileOutput(fileName, Context.MODE_PRIVATE);
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(this);
os.close();
fos.close();

Yükleme (istisna işleme kodu olmadan):

FileInputStream fis = context.openFileInput(fileName);
ObjectInputStream is = new ObjectInputStream(fis);
SimpleClass simpleClass = (SimpleClass) is.readObject();
is.close();
fis.close();

Çok kullanışlı. Nesne dosyası olarak yazmak için sınıfı serileştirmemiz gerekip gerekmediğini açıklar mısınız?
Arun Chettoor

4
Seri hale getirilebilir arabirimi kullanıyorsanız, bu işlevsellik dolaylı olarak sınıfınıza eklenir. Tek istediğiniz basit nesne serileştirme ise, ben bunu kullanırdım. Uygulaması da son derece kolaydır. developer.android.com/reference/java/io/Serializable.html
mtmurdock

6
+1, Birden fazla nesnenin kaydedilmesi için gerekli hile var: stackoverflow.com/a/1195078/1321401
Luten

2
Fos.close () ve fis.close () için de bir çağrı olmalı mı?
IcedDante

Paper'ı tavsiye ederim . Kryo serileştirme kullanır ve yaygın Java serileştirmeden çok daha hızlıdır.
Aleksey Masny

36

Bu 2 seçeneği (okuma / yazma), düz nesneler, nesne dizisi (150 nesne), Harita ile denedim:

Seçenek 1:

FileOutputStream fos = context.openFileOutput(fileName, Context.MODE_PRIVATE);
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(this);
os.close();

Seçenek 2:

SharedPreferences mPrefs=app.getSharedPreferences(app.getApplicationInfo().name, Context.MODE_PRIVATE);
SharedPreferences.Editor ed=mPrefs.edit();
Gson gson = new Gson(); 
ed.putString("myObjectKey", gson.toJson(objectToSave));
ed.commit();

2. seçenek 1. seçeneğe göre iki kat daha hızlıdır

Seçenek 2 rahatsızlığı, okumak için belirli bir kod yapmanız gerektiğidir:

Gson gson = new Gson();
JsonParser parser=new JsonParser();
//object arr example
JsonArray arr=parser.parse(mPrefs.getString("myArrKey", null)).getAsJsonArray();
events=new Event[arr.size()];
int i=0;
for (JsonElement jsonElement : arr)
    events[i++]=gson.fromJson(jsonElement, Event.class);
//Object example
pagination=gson.fromJson(parser.parse(jsonPagination).getAsJsonObject(), Pagination.class);

3
Neden 2. seçeneğin daha hızlı olduğunu söylüyorsunuz? Belki de SharedPreferences bellekte tutulduğu ve ölçtüğünüz zaman dosya sistemine kaydetmeyi içermediği için? Bunu soruyorum çünkü bir nesne akışına serileştirmenin bir JSON Dizgesine göre daha verimli olması gerektiğini düşünüyorum.
CesarPim

10

Bunu Generics ile halletmek için bir sınıf yaptım, böylece serileştirilebilir tüm nesne türleri ile kullanılabilir:

public class SerializableManager {

    /**
     * Saves a serializable object.
     *
     * @param context The application context.
     * @param objectToSave The object to save.
     * @param fileName The name of the file.
     * @param <T> The type of the object.
     */

    public static <T extends Serializable> void saveSerializable(Context context, T objectToSave, String fileName) {
        try {
            FileOutputStream fileOutputStream = context.openFileOutput(fileName, Context.MODE_PRIVATE);
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);

            objectOutputStream.writeObject(objectToSave);

            objectOutputStream.close();
            fileOutputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Loads a serializable object.
     *
     * @param context The application context.
     * @param fileName The filename.
     * @param <T> The object type.
     *
     * @return the serializable object.
     */

    public static<T extends Serializable> T readSerializable(Context context, String fileName) {
        T objectToReturn = null;

        try {
            FileInputStream fileInputStream = context.openFileInput(fileName);
            ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
            objectToReturn = (T) objectInputStream.readObject();

            objectInputStream.close();
            fileInputStream.close();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }

        return objectToReturn;
    }

    /**
     * Removes a specified file.
     *
     * @param context The application context.
     * @param filename The name of the file.
     */

    public static void removeSerializable(Context context, String filename) {
        context.deleteFile(filename);
    }

}

7

Hata işleme ve eklenen dosya akışı ile eksiksiz kod kapanır. Serileştirmek ve serisini kaldırabilmek için bunu sınıfınıza ekleyin. Benim durumumda sınıf adı CreateResumeForm. Bunu kendi sınıf adınızla değiştirmelisiniz. Androidarabirim Serializablenesnelerinizi dosyaya kaydetmek için yeterli değildir, yalnızca akışlar oluşturur.

// Constant with a file name
public static String fileName = "createResumeForm.ser";

// Serializes an object and saves it to a file
public void saveToFile(Context context) {
    try {
        FileOutputStream fileOutputStream = context.openFileOutput(fileName, Context.MODE_PRIVATE);
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        objectOutputStream.writeObject(this);
        objectOutputStream.close();
        fileOutputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}


// Creates an object by reading it from a file
public static CreateResumeForm readFromFile(Context context) {
    CreateResumeForm createResumeForm = null;
    try {
        FileInputStream fileInputStream = context.openFileInput(fileName);
        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
        createResumeForm = (CreateResumeForm) objectInputStream.readObject();
        objectInputStream.close();
        fileInputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    return createResumeForm;
}

Bunu şu şekilde kullanın Activity:

form = CreateResumeForm.readFromFile(this);

0

SharePrefrences kullanıyorum:

package myapps.serializedemo;

import android.content.Context;
import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import java.io.IOException;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

//Create the SharedPreferences
    SharedPreferences sharedPreferences = this.getSharedPreferences("myapps.serilizerdemo", Context.MODE_PRIVATE);
    ArrayList<String> friends = new ArrayList<>();
    friends.add("Jack");
    friends.add("Joe");
    try {

 //Write / Serialize
 sharedPreferences.edit().putString("friends",
    ObjectSerializer.serialize(friends)).apply();
    } catch (IOException e) {
        e.printStackTrace();
    }
//READ BACK
    ArrayList<String> newFriends = new ArrayList<>();
    try {
        newFriends = (ArrayList<String>) ObjectSerializer.deserialize(
                sharedPreferences.getString("friends", ObjectSerializer.serialize(new ArrayList<String>())));
    } catch (IOException e) {
        e.printStackTrace();
    }
    Log.i("***NewFriends", newFriends.toString());
}
}

0

Programınıza bir ObjectSerialization sınıfı eklemelisiniz, aşağıdakiler çalışabilir

    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;

    public class ObjectSerializer {

public static String serialize(Serializable obj) throws IOException {
    if (obj == null) return "";
    try {
        ByteArrayOutputStream serialObj = new ByteArrayOutputStream();
        ObjectOutputStream objStream = new ObjectOutputStream(serialObj);
        objStream.writeObject(obj);
        objStream.close();
        return encodeBytes(serialObj.toByteArray());
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

public static Object deserialize(String str) throws IOException {
    if (str == null || str.length() == 0) return null;
    try {
        ByteArrayInputStream serialObj = new ByteArrayInputStream(decodeBytes(str));
        ObjectInputStream objStream = new ObjectInputStream(serialObj);
        return objStream.readObject();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

public static String encodeBytes(byte[] bytes) {
    StringBuffer strBuf = new StringBuffer();

    for (int i = 0; i < bytes.length; i++) {
        strBuf.append((char) (((bytes[i] >> 4) & 0xF) + ((int) 'a')));
        strBuf.append((char) (((bytes[i]) & 0xF) + ((int) 'a')));
    }

    return strBuf.toString();
}

public static byte[] decodeBytes(String str) {
    byte[] bytes = new byte[str.length() / 2];
    for (int i = 0; i < str.length(); i+=2) {
        char c = str.charAt(i);
        bytes[i/2] = (byte) ((c - 'a') << 4);
        c = str.charAt(i+1);
        bytes[i/2] += (c - 'a');
    }
    return bytes;
}

}

Aşağıdaki kullanmak yerine SharedPreferences ile bir dizi depolamak için kullanıyorsanız: -

SharedPreferences sharedPreferences = this.getSharedPreferences(getPackageName(),MODE_PRIVATE);

Seri hale getirmek için: -

sharedPreferences.putString("name",ObjectSerializer.serialize(array));

Seri Durumdan Çıkarmak için: -

newarray = (CAST_IT_TO_PROPER_TYPE) ObjectSerializer.deSerialize(sharedPreferences.getString(name),null);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.