Làm cách nào để tôi tuần tự hóa một đối tượng và lưu nó vào một tệp trong Android?


128

Giả sử tôi có một số lớp đơn giản và một khi nó được khởi tạo như một đối tượng tôi muốn có thể tuần tự hóa nội dung của nó thành một tệp và lấy nó bằng cách tải tệp đó vào một lúc sau ... Tôi không chắc bắt đầu từ đâu, Tôi cần làm gì để tuần tự hóa đối tượng này thành một tệp?

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

Đây có lẽ là câu hỏi dễ nhất trên thế giới, bởi vì đây là một nhiệm vụ thực sự đơn giản trong .NET, nhưng trong Android tôi khá mới nên tôi hoàn toàn bị mất.

Câu trả lời:


250

Lưu (mã xử lý ngoại lệ w / o):

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

Đang tải (mã xử lý ngoại lệ):

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

Rất hữu ích. Bạn có thể giải thích liệu chúng ta có phải tuần tự hóa lớp để viết dưới dạng tệp đối tượng không.
Arun Chettoor

4
Chức năng này được thêm vào lớp của bạn nếu bạn sử dụng giao diện Nối tiếp. Nếu tất cả những gì bạn muốn là tuần tự hóa đối tượng đơn giản, đó là những gì tôi sẽ sử dụng. Nó là cực kỳ dễ dàng để thực hiện quá. developer.android.com/reference/java/io/Serializable.html
mtmurdock

6
+1, Để tiết kiệm nhiều đối tượng, cần có mẹo: stackoverflow.com/a/1195078/1321401
Luten

2
Có nên có một cuộc gọi đến fos.close () và fis.close () không?
IcedDante

Tôi muốn giới thiệu Giấy . Nó sử dụng tuần tự hóa Kryo và tuần tự hóa Java phổ biến nhanh hơn nhiều.
Aleksey Masny

36

Tôi đã thử 2 tùy chọn này (đọc / ghi), với các đối tượng đơn giản, mảng các đối tượng (150 đối tượng), Bản đồ:

Lựa chọn 1:

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

Lựa chọn 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();

Tùy chọn 2 nhanh hơn hai lần so với tùy chọn 1

Tùy chọn 2 bất tiện là bạn phải tạo mã cụ thể để đọc:

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
Tại sao bạn lại nói phương án 2 nhanh hơn? Có lẽ vì SharedPreferences được lưu trong bộ nhớ và thời gian bạn đo không bao gồm lưu nó vào hệ thống tệp? Tôi hỏi điều này bởi vì tôi sẽ tưởng tượng việc tuần tự hóa thành một luồng đối tượng phải hiệu quả hơn so với Chuỗi JSON.
CesarPim

10

Tôi vừa tạo một lớp để xử lý việc này với Generics, vì vậy nó có thể được sử dụng với tất cả các loại đối tượng được tuần tự hóa:

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

Mã hoàn chỉnh với xử lý lỗi và luồng tệp bổ sung đóng lại. Thêm nó vào lớp của bạn mà bạn muốn có thể tuần tự hóa và giải tuần tự hóa. Trong trường hợp của tôi tên lớp là CreateResumeForm. Bạn nên thay đổi nó thành tên lớp của riêng bạn. AndroidGiao diện Serializablekhông đủ để lưu các đối tượng của bạn vào tệp, nó chỉ tạo ra các luồng.

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

Sử dụng nó như thế này trong Activity:

form = CreateResumeForm.readFromFile(this);

0

Tôi sử dụng 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());
}
}

0

Bạn phải thêm một lớp ObjectSerialization vào chương trình của bạn sau đây có thể hoạt động

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

}

nếu bạn đang sử dụng để lưu trữ một mảng với SharedPreferences hơn là sử dụng sau: -

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

Để nối tiếp: -

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

Để giải trừ:

newarray = (CAST_IT_TO_PROPER_TYPE) ObjectSerializer.deSerialize(sharedPreferences.getString(name),null);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.