ฉันจะทำให้เป็นอันดับวัตถุและบันทึกลงในไฟล์ใน Android ได้อย่างไร


128

สมมติว่าฉันมีคลาสที่เรียบง่ายและเมื่อมันสร้างอินสแตนซ์เป็นวัตถุที่ฉันต้องการที่จะสามารถทำให้เป็นอันดับเนื้อหาไปยังไฟล์และดึงมันโดยการโหลดไฟล์นั้นในภายหลัง ... ฉันไม่แน่ใจว่าจะเริ่มที่นี่ฉันต้องทำอย่างไรเพื่อทำให้วัตถุนี้เป็นอนุกรมเป็นไฟล์?

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

นี่อาจเป็นคำถามที่ง่ายที่สุดในโลกเพราะนี่เป็นงานง่าย ๆ ใน. NET แต่ใน Android ฉันค่อนข้างใหม่ดังนั้นฉันจึงหลงทางไปหมด

คำตอบ:


250

กำลังบันทึก (ไม่มีรหัสการจัดการข้อยกเว้น):

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

กำลังโหลด (ไม่มีรหัสการจัดการข้อยกเว้น):

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

มีประโยชน์มาก. คุณช่วยอธิบายได้ไหมว่าเราต้องทำให้คลาสเป็นอนุกรมสำหรับการเขียนเป็นไฟล์ออบเจ็กต์หรือไม่
Arun Chettoor

4
ฟังก์ชั่นนี้จะถูกเพิ่มเข้าไปในชั้นเรียนของคุณโดยปริยายถ้าคุณใช้อินเทอร์เฟซ หากสิ่งที่คุณต้องการคือการทำให้เป็นอันดับวัตถุอย่างง่ายนั่นคือสิ่งที่ฉันจะใช้ มันง่ายมากที่จะใช้เช่นกัน developer.android.com/reference/java/io/Serializable.html
mtmurdock

6
+1 สำหรับการบันทึกวัตถุหลายรายการจำเป็นต้องมีเคล็ดลับ: stackoverflow.com/a/1195078/1321401
Luten

2
ควรมีการโทรไปที่ fos.close () และ fis.close () ด้วยหรือไม่
IcedDante

ผมอยากแนะนำให้กระดาษ มันใช้การทำให้เป็นอันดับ Kryo และเร็วกว่ามากแล้วการทำให้เป็นอันดับ Java ทั่วไป
Aleksey Masny

36

ฉันได้ลอง 2 ตัวเลือกนี้ (อ่าน / เขียน) โดยมีวัตถุธรรมดา, อาร์เรย์ของวัตถุ (150 วัตถุ), แผนที่

ตัวเลือกที่ 1:

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

Option2:

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 เร็วกว่าตัวเลือกที่ 1 ถึงสองเท่า

ตัวเลือกที่ 2 ในความไม่สะดวกคือคุณต้องทำรหัสเฉพาะสำหรับการอ่าน:

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
ทำไมคุณถึงบอกว่าตัวเลือก 2 เร็วขึ้น? อาจเป็นเพราะ SharedPreferences ถูกเก็บไว้ในหน่วยความจำและเวลาที่คุณวัดไม่ได้รวมการบันทึกลงในระบบไฟล์ ฉันถามสิ่งนี้เพราะฉันคิดว่าการจัดลำดับวัตถุกระแสจะต้องมีประสิทธิภาพมากกว่าสตริง JSON
CesarPim

10

ฉันเพิ่งสร้างคลาสเพื่อจัดการกับ Generics ดังนั้นจึงสามารถใช้กับทุกประเภทวัตถุที่เป็นอนุกรม:

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

รหัสที่สมบูรณ์พร้อมการจัดการข้อผิดพลาดและการเพิ่มสตรีมไฟล์จะปิดลง เพิ่มไปยังชั้นเรียนของคุณที่คุณต้องการให้เป็นอันดับและ deserialize CreateResumeFormในกรณีของฉันชื่อชั้นเป็น คุณควรเปลี่ยนเป็นชื่อคลาสของคุณเอง Androidอินเทอร์เฟซSerializableไม่เพียงพอที่จะบันทึกวัตถุของคุณลงในไฟล์ แต่จะสร้างเฉพาะสตรีม

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

ใช้อย่างนี้ในของคุณActivity:

form = CreateResumeForm.readFromFile(this);

0

ฉันใช้ 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

คุณต้องเพิ่มคลาส ObjectSerialization ให้กับโปรแกรมของคุณดังต่อไปนี้อาจใช้งานได้

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

}

หากคุณใช้เพื่อเก็บอาร์เรย์ด้วย SharedPreferences มากกว่าการใช้ดังต่อไปนี้: -

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

ในการทำให้เป็นอันดับ: -

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

ในการยกเลิกการซีเรียลไลซ์: -

newarray = (CAST_IT_TO_PROPER_TYPE) ObjectSerializer.deSerialize(sharedPreferences.getString(name),null);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.