最近发现java读取文件在window下正常.但有时在linux就乱码.于是花了点时间找了一下.
以下面的代码为例
FileReader fileReader = null; BufferedReader bufferedReader = null; fileReader = new FileReader(""); bufferedReader = new BufferedReader(fileReader);
FileReader类看了一下源码.其它就是继承InputStreamReader类.而且不能设置字符编码,在多平台很容易出现乱码问题.
所以个人不推荐使用.
接着看InputStreamReader类,默认不传编译的构造方法.FileReader也是使用这个方法.
public InputStreamReader(InputStream in) { super(in); try { sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object } catch (UnsupportedEncodingException e) { // The default encoding should always be available throw new Error(e); } }
这里又扯到StreamDecoder类.再跟进去看看
public static StreamDecoder forInputStreamReader(InputStream paramInputStream, Object paramObject, String paramString) throws UnsupportedEncodingException { String str = paramString; if (str == null) str = Charset.defaultCharset().name(); try { if (Charset.isSupported(str)) return new StreamDecoder(paramInputStream, paramObject, Charset.forName(str)); } catch (IllegalCharsetNameException localIllegalCharsetNameException) { } throw new UnsupportedEncodingException(str); }
接下来关键为如果不传字符编码用Charset.defaultCharset().name();来取的字符编译来做为默认编码.
跟进Charset类的defaultCharset方法.
public static Charset defaultCharset() { if (defaultCharset == null) { synchronized (Charset.class) { GetPropertyAction localGetPropertyAction = new GetPropertyAction("file.encoding"); String str = (String)AccessController.doPrivileged(localGetPropertyAction); Charset localCharset = lookup(str); if (localCharset != null) defaultCharset = localCharset; else defaultCharset = forName("UTF-8"); } } return defaultCharset; }
public class GetPropertyAction implements PrivilegedAction<String> { private String theProp; private String defaultVal; public GetPropertyAction(String paramString) { this.theProp = paramString; } public GetPropertyAction(String paramString1, String paramString2) { this.theProp = paramString1; this.defaultVal = paramString2; } public String run() { String str = System.getProperty(this.theProp); return str == null ? this.defaultVal : str; } }
跟了这么多,关键就是默认字符编码为 System.getProperty("file.encoding");
window中文版一般取出的值的GBK,而linux则要看设置去.
所以当你使用FileReader类去读取一个GBK文件时,你会发现在window上是正常的.但在linux下不一定正常.
而且FileReader无法设置字符编码.很蛋疼的一个类.很容易出现乱码的类.个人强烈推荐不再使用这个类.
推荐直接使用InputStreamReader类.并指定字符编码.
bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "GBK"));