緩存文件FileOutputStream ObjectOutputStream

一、對數據進行存儲,提供了openFileOutput() 方法  <數據的寫入>

 

  /**
     * 保存數據
     * @param context
     * @param fileName  保存文件名
     * @param data  保存的數據
     */
    public void saveFile(Context context, String fileName, String data) {
        try {
            FileOutputStream fos = context.openFileOutput(fileName, context.MODE_PRIVATE);
            fos.write(data.getBytes());
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


openFileOutput(): 第一個參數是保存的文件名,如果不存在,android 會自動創建文件;

 

  第二個參數是用於指定操作模式,有四種操作模式:

Context.MODE_PRIVATE    =  0         //爲默認操作模式,代表該文件是私有數據,只能被應用本身訪問,在該模式下,寫入的內容會覆蓋原文件的內容
Context.MODE_APPEND    =  32768      //會檢查文件是否存在,存在就往文件追加內容,否則就創建新文件。
Context.MODE_WORLD_READABLE =  1     //用來控制其他應用是否有權限讀該文件,表示當前文件可以被其他應用讀取
Context.MODE_WORLD_WRITEABLE =  2    //用來控制其他應用是否有權限寫該文件,表示當前文件可以被其他應用寫入爲默認操作模式,代表該文件是私有數據,只能被應用本身訪問,在該模式下,寫入的內容會覆蓋原文件的內容
Context.MODE_APPEND    =  32768      //會檢查文件是否存在,存在就往文件追加內容,否則就創建新文件。
Context.MODE_WORLD_READABLE =  1     //用來控制其他應用是否有權限讀該文件,表示當前文件可以被其他應用讀取
Context.MODE_WORLD_WRITEABLE =  2    //用來控制其他應用是否有權限寫該文件,表示當前文件可以被其他應用寫入

 

 

 

往sdcard 中存儲文件

 

if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
   File sdCardDir = Environment.getExternalStorageDirectory();//獲取SDCard目錄
   File saveFile = new File(sdCardDir, "a.txt");
   FileOutputStream outStream = new FileOutputStream(saveFile);
   outStream.write("test".getBytes());
   outStream.close();
}

 

 

二、對數據的讀取,FileInputStream <數據的讀取>

 

/**
     * 讀取文件
     * @param fileName 需要讀取的文件名
     */
    public void readFile(String fileName) {
        try {
            FileInputStream fis = new FileInputStream(fileName); // 讀取數據 fileName 讀取的文件數據 .txt  等文件
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int length = -1;
            while ((length = fis.read(buffer)) != -1) {
                // buffer : 寫入的數據;  0 : 寫入數據的開始位置 ;  length : 每次寫入的bytes
                baos.write(buffer, 0, length);
            }

            baos.close();
            fis.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

getCacheDir()方法用於獲取/data/data/<package name>/cache目錄
getFilesDir()方法用於獲取/data/data/<package name>/files目錄

 

 

三、對象輸入輸出流  ObjectInputStream ObjectOutputStream

     對象的序列化以及反序列化。主要用於對象信息的寫入以及讀取。 對象信息一旦寫到文件上那麼對象的信息就可以做到持久化了

     對象的輸出流ObjectOutputStream :將指定的對象寫入到文件的過程,就是將對象序列化的過程。(對象實現Serializable

     對象的輸入流ObjctInputStream :   指將指定序列化的對象讀出來的過程,就是將對象反序列化的過程。
 

1、對象的寫入

 

 /**
     * 將對象信息寫入到filePath文件中
     * 定義方法把對象的信息寫到硬盤上------>對象的序列化。
     *
     * @param filePath 寫入對象信息的文件路徑
     * @param object   寫入的對象
     * @return
     */
    public void saveObj(String filePath, Object object) {
        File file = new File(filePath);
        try {
            FileOutputStream fos = new FileOutputStream(file); // 創建文件字節輸出流對象
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(object);
            //最後記得關閉資源,oos.close()內部已經將fos對象資源釋放了,所以只需要關閉objectOutputStream即可
            oos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

 

 

 

2、對象的讀取

 

/**
     * 把文件中的對象信息讀取出來 —— 對象的反序列化過程
     * @param filePath
     */
    private void readObj(String filePath){
        try {
            FileInputStream fis = new FileInputStream(new File(filePath)); // 創建文件字節輸入流對象
            ObjectInputStream ois = new ObjectInputStream(fis);
            Object object = ois.readObject(); // 讀取文件後的對象
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

 

 

 

3、對象的寫入讀取可能存在的異常:

    Exception in thread "main" java.io.InvalidClassException: xuliehua.User; local class incompatible: stream classdesc     serialVersionUID = 2161776237447595412, local class serialVersionUID = -3634244984882257127

 

異常信息解讀:

serialVersionUID 是用於記錄class文件的版本信息的,serialVersionUID這個數字是JVM(JAVA虛擬界)通過一個類的類名、成員、包名、工程名算出的一個數字。而這時候序列化文件中記錄的serialVersionUID與項目中的不一致,即找不到對應的類來反序列化。

如果序列化與反序列化的時候可能會修改類的成員,那麼最好一開始就給這個類指定一個serialVersionUID,如果一類已經指定的serialVersionUID,然後在序列化與反序列化的時候,jvm都不會再自己算這個 class的serialVersionUID了。

不想要某些字段序列化時候,可以用transient關鍵字修飾

 

class Debug implements Serializable{
        private static final  long serialVersionUID = 1L;
        private String debugInfo ;
        private int debugId;    // transient String debug; // 不需要序列化這個變量

        public Debug(String debugInfo, int debugId) {
            this.debugInfo = debugInfo;
            this.debugId = debugId;
        }

        public String getDebugInfo() {
            return debugInfo;
        }

        public void setDebugInfo(String debugInfo) {
            this.debugInfo = debugInfo;
        }

        public int getDebugId() {
            return debugId;
        }

        public void setDebugId(int debugId) {
            this.debugId = debugId;
        }
    }

 

 

4、注意點:

1)對象的反序列化創建對象的時候並不會調用到構造方法的;

2)如果對象需要被寫出到文件上,那麼對象所屬的類必須要實現Serializable接口;

3)serialVersionUID 是用於記錄class文件的版本信息的,serialVersionUID這個數字是通過一個類的類名、成員、包名、工程名算出的一個數字;

4) 使用ObjectInputStream反序列化的時候,ObjeectInputStream會先讀取文件中的serialVersionUID,然後與本地的class文件的serialVersionUID進行對比,如果這兩個id不一致,反序列則失敗;

5) 如果序列化與反序列化的時候可能會修改類的成員,那麼最好一開始就給這個類指定一個serialVersionUID,如果一類已經指定的serialVersionUID,然後在序列化與反序列化的時候,jvm都不會再自己算這個 class的serialVersionUID了;

6)如果一個對象某個數據不想被序列化到硬盤上,可以使用關鍵字transient修飾;

7)如果一個類維護了另外一個類的引用,則另外一個類也需要實現Serializable接口。
 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章