最近发现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"));