問題發現:從後臺獲取文字資訊的時候,通過抓包發現含有\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能新建、刪除、重新命名檔案和目錄,但不能訪問檔案內容本身。
訪問檔名相關的方法:
- String getName():返回此File物件所表示的檔名或路徑名(如果是路徑,則返回最後一級子路徑名)
- String getPath():返回此File物件所對應的路徑名
- File getAbsoluteFile():返回此File物件的絕對路徑(File形式)
- String getAbsolutePath():返回此File物件所對應的絕對路徑(String形式)
- String getParent():返回此File物件所對應的父目錄名
- boolean renameTo(File newName):重新命名此File物件所對應的檔案或目錄,若成功則返回true
檔案檢測相關的方法:
- boolean exists():判斷File物件所對應的檔案或目錄是否存在
- boolean canWrite():判斷File物件所對應的檔案或目錄是否可寫
- boolean canRead():判斷File物件所對應的檔案或目錄是否可讀
- boolean isFile():判斷File物件所對應的是否是檔案,而不是目錄
- Boolean isDirectory():判斷File物件所對應的是否是目錄,而不是檔案
- boolean isAbsolute():判斷File物件所對應的檔案或目錄是否是絕對路徑
獲取常規檔案資訊:
- long lastModified():返回檔案的最後修改時間
- long length():返回檔案內容的長度
檔案操作相關的方法:
- boolean createNewFile():當此File物件所對應的檔案不存在時,該方法將新建一個該File物件所指定的新檔案,如果建立成功則返回true,否則返回false
- boolean delete():刪除File物件所對應的檔案或路徑
- void deleteOnExit():註冊一個刪除鉤子,指定當Java虛擬機器退出時,刪除File物件所對應的檔案和目錄。
- static File createTempFile(String prefix,String suffix)
- static File createTempFile(STring prefix,STring suffix,File directory):建立臨時檔案
目錄操作相關方法:
- boolean mkdir():檢視建立一個File物件(目錄而非檔案)所對應的目錄
- String[] list():列出File物件的所有子檔名和路徑名
- File[] listFiles():列出File物件所有子檔案和路徑
- static File[] listRoots():列出系統的所有的根路徑
##IO流的分類
- 輸入流和輸出流
- 位元組流(InputStream和OutputStream)和字元流(Reader和Writer)
- 節點流和處理流:直接連線到資料來源的是節點流,處理流的使用是為了簡單與高效
訪問檔案的節點流:
- FileInputStream
- FileReader
- FileOutputStream
- FileWiter
這些節點流讀和寫方法中的容器引數,分別代表讀到容器內,將容器內的內容寫出去。
常用的處理流:
- 緩衝流:BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter
- 轉換流:InputStreamReader、OutputStreamWriter
##RandomAccessFile
簡介:可以直接跳轉到檔案的任意地方來讀寫檔案,但一個最大的侷限是隻能讀寫檔案,不能讀寫其他節點。指標的移動單位是位元組。
方法:
- long getFilePointer():返回檔案記錄指標的當前位置。
- void seek(long pos):將檔案記錄指標定位到pos位置。
- read()
- write()
- readXxx()
- writeXxx()
- mode值:"r","rw"