在處理一些日誌文件的時候,由於數據來源的服務端跟本地處理的編碼不一致,會出現許多亂七八糟的問題,比如無緣無故在文件首多了一些字符,或者寫入文件的時候少了一些內容,又或者亂碼無法顯示等。因此,在讀寫文件的時候,讀入數據流時要指明格式,從數據流寫出到文件時也要指明編碼格式,這樣來說一般沒什麼的問題,因爲你用文件原來的格式正確讀取到了,然後把流中的數據按照你需要的格式寫出了,親測有效。一般來說,讀寫文件比較常用的就是用FileReader和FileWriter,爲了使用更加方便的讀寫接口,可能會使用往這兩者外面再套一層服飾的BufferedReader和BufferedWriter或者在這兩者之上再包裝一層的IO API(Java中的io採用的就是裝飾者模式!如果你願意一層一層一層...)但是,FIleReader和FileWriter無法在你讀寫文件的時候指定文件的編碼格式,按照JDK文檔的解釋,其讀寫採用默認的編碼格式,網上資料有提到默認的編碼格式是指文件本身,也有提到指IDE平臺本身,在我測試之後發現,都沒什麼用:文件本身是utf8的,eclipse也設置成utf8的,讀入的時候在控制檯上顯示一堆亂碼,寫入文件也是一團糟;文件本身是gb2312的,在控制檯能正常顯示,寫入文件也是不得人意。
其實,在JDK文檔對FileWrite(FileReader也類似,就以writer爲例了)的說明中還提及,除了使用默認的編碼,還可以自己去定義OutputStreamWriter的構造函數來指定編碼格式。什麼意思呢?看一下JDK文檔上的FIleWriter樹就懂了:
也即FileWriter是在OutputStreamWriter上再包裝一層的類,因此,使用OutputStreamWriter作爲參數傳入FileWriter時,在構造OutputStreamWriter實例時可以指定文件的編碼格式。當然,使用OutputStreamWriter實例時,不一定再用FileWriter,我可以選擇使用其他IO類來包裝它,或者直接使用OutputStreamWriter示例來寫文件都可以,看個人對API的使用習慣和具體需求。Talk is cheap, show me the code.下面例子是我統計樣本文件中各個特徵取值的範圍的示例
package com.scut.mrshen;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class TestFile {
public static void main(String[] args) throws IOException, InterruptedException {
/**
* gxmobile preprogcess
*/
String srcPath = "E://myArch/Lab/dataYouMi/數據/gxmobile-sample-27730-GB2312.data";
String desPath = "E://myArch/Lab/dataYouMi/數據/gxmobile-sample-featureTypes.data";
String headerPath = "E://myArch/Lab/dataYouMi/數據/gxmobile-sample-header.txt";
// specified charSet when using InputStreamReader or OutputStreamWriter constructor
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(srcPath)), "GB2312"));
BufferedReader hbr = new BufferedReader(new InputStreamReader(new FileInputStream(new File(headerPath)), "GB2312"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(desPath)), "UTF-8"));
// count the feature values
Map<Integer, Set<String>> features = new HashMap<>();
String temp = null;
while((temp = br.readLine()) != null) {
String[] data = temp.split(",");
for(int index = 0; index < data.length; index ++) {
Set<String>fv = features.get(index);
if (fv == null) {
fv = new HashSet<String>();
}
fv.add(data[index]);
features.put(index, fv);
}
}
System.out.println("feature num: " + features.size());
temp = hbr.readLine();
String[]header = temp.split("\t");
// get a sorted keySet
Map<Integer, Set<String>>sortedFeature = new TreeMap<>(features);
for (int key : sortedFeature.keySet()) {
System.out.println("index#" + key + " - valNum#" + features.get(key).size());
bw.write("index#" + key + header[key] + " valNum:" + sortedFeature.get(key).size() + "\n" + sortedFeature.get(key).toString() + "\n\n");
}
bw.flush();
Thread.sleep(3*1000);
br.close();
hbr.close();
bw.close();
}
}