Bagaimana cara membuat cerita bersambung suatu objek dan menyimpannya ke file di Android?

128

Katakanlah saya memiliki beberapa kelas sederhana dan setelah itu dipakai sebagai objek saya ingin dapat membuat serial isinya ke file, dan mengambilnya dengan memuat file itu di lain waktu ... Saya tidak yakin harus mulai dari mana di sini, apa yang harus saya lakukan untuk membuat serialisasi objek ini ke file?

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? */
   }
}

Ini mungkin pertanyaan termudah di dunia, karena ini adalah tugas yang sangat sederhana di .NET, tetapi di Android saya cukup baru sehingga saya benar-benar tersesat.

Ben Lesh
sumber

Jawaban:

250

Menyimpan (tanpa kode penanganan pengecualian):

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

Memuat (tanpa kode penanganan pengecualian):

FileInputStream fis = context.openFileInput(fileName);
ObjectInputStream is = new ObjectInputStream(fis);
SimpleClass simpleClass = (SimpleClass) is.readObject();
is.close();
fis.close();
Ralkie
sumber
Sangat berguna. Bisakah Anda jelaskan apakah kita harus membuat cerita bersambung kelas untuk ditulis sebagai file objek.
Arun Chettoor
4
Fungsi ini secara implisit ditambahkan ke kelas Anda jika Anda menggunakan antarmuka Serializable. Jika yang Anda inginkan adalah serialisasi objek sederhana, itulah yang akan saya gunakan. Sangat mudah untuk diimplementasikan juga. developer.android.com/reference/java/io/Serializable.html
mtmurdock
6
+1, Untuk menghemat banyak objek ada trik yang diperlukan: stackoverflow.com/a/1195078/1321401
Luten
2
Haruskah ada panggilan ke fos.close () dan fis.close () juga?
IcedDante
Saya akan merekomendasikan Paper . Ini menggunakan serialisasi Kryo dan jauh lebih cepat daripada serialisasi Java umum.
Aleksey Masny
36

Saya sudah mencoba 2 opsi ini (baca / tulis), dengan objek polos, array objek (150 objek), Peta:

Pilihan 1:

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

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

Opsi 2 dua kali lebih cepat dari opsi 1

Opsi 2 ketidaknyamanan adalah Anda harus membuat kode khusus untuk dibaca:

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);
surfealokesea
sumber
3
Mengapa Anda mengatakan opsi 2 lebih cepat? Mungkin karena SharedPreferences disimpan dalam memori dan waktu yang Anda ukur tidak termasuk menyimpannya ke sistem file? Saya bertanya ini karena saya akan membayangkan serialisasi ke aliran objek harus lebih efisien daripada ke String JSON.
CesarPim
10

Saya baru saja membuat kelas untuk menangani hal ini dengan Generics, sehingga dapat digunakan dengan semua jenis objek yang dapat serial:

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

}
Sandro Machado
sumber
7

Kode lengkap dengan penanganan kesalahan dan aliran file ditambahkan ditutup. Tambahkan ke kelas Anda yang Anda ingin bisa membuat serial dan deserialize. Dalam kasus saya nama kelasnya CreateResumeForm. Anda harus mengubahnya ke nama kelas Anda sendiri. Androidantarmuka Serializabletidak cukup untuk menyimpan objek Anda ke file, itu hanya membuat aliran.

// 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;
}

Gunakan seperti ini di Activity:

form = CreateResumeForm.readFromFile(this);
Denis Kutlubaev
sumber
0

Saya menggunakan SharePrefrences:

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

Anda harus menambahkan kelas ObjectSerialization ke program Anda yang berikut ini mungkin berfungsi

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

}

jika Anda menggunakan untuk menyimpan array dengan SharedPreferences daripada menggunakan yang berikut: -

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

Untuk Serialize: -

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

Untuk Deserialize: -

newarray = (CAST_IT_TO_PROPER_TYPE) ObjectSerializer.deSerialize(sharedPreferences.getString(name),null);
Priyanshu Dubey
sumber