Android 回車換行的持久化

鍵筆刀發表於2019-03-12

問題發現:從後臺獲取文字資訊的時候,通過抓包發現含有\r\n換行符,顯示在TextView上能夠正確的換行,但是通過如下方法將String寫進File,再次使用的時候從File中讀取的時候會發現不再有換行效果。

寫檔案方法

public static void saveJson(String fileName, String info) {
    try {
        FileOutputStream fos = context.openFileOutput(fileName, Context.MODE_PRIVATE);
        OutputStreamWriter osw = new OutputStreamWriter(fos);
        BufferedWriter bw = new BufferedWriter(osw);
        bw.write(info);
        bw.flush();
        bw.close();
        osw.close();
        fos.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
複製程式碼

讀檔案方法

public static String getJson(String fileName) {
    String info = null;
    try {
        FileInputStream fis = context.openFileInput(fileName);
        InputStreamReader isr = new InputStreamReader(fis);
        BufferedReader br = new BufferedReader(isr);
        String Line;
        StringBuffer info2 = new StringBuffer();
        while ((Line = br.readLine()) != null) {
            info2.append(Line);
        }
        info = info2.toString();
        br.close();
        isr.close();
        fis.close();

    } catch (Exception e) {
        LogSwitchUtils.logD(FileUtils2.class, "快取的異常為:" + e);
        return null;
    }
    return info;
}
複製程式碼

通過分析,是因為FileOutputStream、OutputStreamWriter、BufferedWriter等一些流在處理這些轉義字元的時候沒有將其寫入,或者是FileInputStream、InputStreamReader、BufferedReader等沒有將其讀出。PS:應惡補這些知識。

問題解決

方法1:依然使用上述兩個Method,不過在呼叫之前先對目標String進行編碼/解碼,如URLEncoder.encode(schoolDesc)URLDecoder.decode(schoolDescTemp)

方法2:將帶有特殊字元的String寫進SharedPreferences,使用的時候讀出;

方法3:使用位元組流進行處理,但是該方法有一個不足之處,見讀檔案方法的註釋。方法如下;

寫檔案方法

public static void saveStringToFileByByte(Context context, String fileName, String info) {
    try {
        FileOutputStream fos = context.openFileOutput(fileName, Context.MODE_PRIVATE);
        byte[] buf = info.getBytes();
        fos.write(buf);
        fos.close();
    } catch (Exception e) {
        LogSwitchUtils.logE(FileUtils2.class, "fos寫快取時候的異常為:" + e);
        e.printStackTrace();
    }
}
複製程式碼

讀檔案方法

public static String getStringFromFileByByte(Context context, String fileName) {
    String result = null;
    StringBuffer sb = new StringBuffer();
    File file = new File(context.getFilesDir().getAbsolutePath() +"/"+ fileName);
    if (!file.exists()) {
        return result;
    }
    try {
        FileInputStream fis = new FileInputStream(file);
        byte[] buf = new byte[1024 * 2];//陣列的容量不容易確定,如果給的太大,浪費內容;給的太小,在new String的時候將會發生亂碼,因此該方法適用於長度固定的String的File寫入及讀出
        while (fis.read(buf) > 0) {
            sb.append(new String(buf));
        }
        result = sb.toString();
        fis.close();
    } catch (Exception e) {
        LogSwitchUtils.logE(FileUtils2.class, "fis寫快取時候的異常為:" + e);
        e.printStackTrace();
    }
    return result;
}
複製程式碼

方法4:使用RandomAccessFile進行讀寫,方法如下:

寫檔案方法

public static void saveFileByRaf(Context context, String fileName, String info) {
    File path = new File(context.getFilesDir().getAbsolutePath() + "/baike_detail");
    if (!path.exists()) {
        path.mkdir();
    }
    File file = new File(path, fileName);
    if (file.exists()) {
        file.delete();
    }
    try {
        RandomAccessFile raf = new RandomAccessFile(file, "rw");
        raf.writeUTF(info);
    } catch (Exception e) {
        LogSwitchUtils.logE(FileUtils2.class, "寫快取時候的異常為:" + e);
        e.printStackTrace();
    }
}
複製程式碼

讀檔案方法

public static String getFileByRaf(Context context, String fileName) {
    String result = null;
    File path = new File(context.getFilesDir().getAbsolutePath() + "/baike_detail");
    if (!path.exists()) {
        return result;
    };
    File file = new File(path, fileName);
    if (!file.exists()) {
        return result;
    }
    try {
        RandomAccessFile raf = new RandomAccessFile(file, "rw");
        result = raf.readUTF();
    } catch (Exception e) {
        LogSwitchUtils.logE(FileUtils2.class, "讀快取時候的異常為:" + e);
        e.printStackTrace();
    }
    return result;
}
複製程式碼

Java的IO流

##File

File類是java.io包下代表與平臺無關的檔案和目錄,即不管是檔案還是目錄都是使用File來操作的,File能新建、刪除、重新命名檔案和目錄,但不能訪問檔案內容本身。

訪問檔名相關的方法

  1. String getName():返回此File物件所表示的檔名或路徑名(如果是路徑,則返回最後一級子路徑名)
  2. String getPath():返回此File物件所對應的路徑名
  3. File getAbsoluteFile():返回此File物件的絕對路徑(File形式)
  4. String getAbsolutePath():返回此File物件所對應的絕對路徑(String形式)
  5. String getParent():返回此File物件所對應的父目錄名
  6. boolean renameTo(File newName):重新命名此File物件所對應的檔案或目錄,若成功則返回true

檔案檢測相關的方法

  1. boolean exists():判斷File物件所對應的檔案或目錄是否存在
  2. boolean canWrite():判斷File物件所對應的檔案或目錄是否可寫
  3. boolean canRead():判斷File物件所對應的檔案或目錄是否可讀
  4. boolean isFile():判斷File物件所對應的是否是檔案,而不是目錄
  5. Boolean isDirectory():判斷File物件所對應的是否是目錄,而不是檔案
  6. boolean isAbsolute():判斷File物件所對應的檔案或目錄是否是絕對路徑

獲取常規檔案資訊

  1. long lastModified():返回檔案的最後修改時間
  2. long length():返回檔案內容的長度

檔案操作相關的方法

  1. boolean createNewFile():當此File物件所對應的檔案不存在時,該方法將新建一個該File物件所指定的新檔案,如果建立成功則返回true,否則返回false
  2. boolean delete():刪除File物件所對應的檔案或路徑
  3. void deleteOnExit():註冊一個刪除鉤子,指定當Java虛擬機器退出時,刪除File物件所對應的檔案和目錄。
  4. static File createTempFile(String prefix,String suffix)
  5. static File createTempFile(STring prefix,STring suffix,File directory):建立臨時檔案

目錄操作相關方法

  1. boolean mkdir():檢視建立一個File物件(目錄而非檔案)所對應的目錄
  2. String[] list():列出File物件的所有子檔名和路徑名
  3. File[] listFiles():列出File物件所有子檔案和路徑
  4. static File[] listRoots():列出系統的所有的根路徑

##IO流的分類

  1. 輸入流和輸出流
  2. 位元組流(InputStream和OutputStream)和字元流(Reader和Writer)
  3. 節點流和處理流:直接連線到資料來源的是節點流,處理流的使用是為了簡單與高效

訪問檔案的節點流

  1. FileInputStream
  2. FileReader
  3. FileOutputStream
  4. FileWiter

這些節點流讀和寫方法中的容器引數,分別代表讀到容器內,將容器內的內容寫出去。

常用的處理流

  1. 緩衝流:BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter
  2. 轉換流:InputStreamReader、OutputStreamWriter

##RandomAccessFile

簡介:可以直接跳轉到檔案的任意地方來讀寫檔案,但一個最大的侷限是隻能讀寫檔案,不能讀寫其他節點。指標的移動單位是位元組。

方法:

  1. long getFilePointer():返回檔案記錄指標的當前位置。
  2. void seek(long pos):將檔案記錄指標定位到pos位置。
  3. read()
  4. write()
  5. readXxx()
  6. writeXxx()
  7. mode值:"r","rw"

相關文章