HashMap 对汉字的行为不符合预期
HashMap does not behave as expected for Chinese characters
China-中国,CN
Angola-安哥拉,AO
Afghanistan-阿富汗,AF
Albania-阿尔巴尼亚,AL
Algeria-阿尔及利亚,DZ
Andorra-安道尔共和国,AD
Anguilla-安圭拉岛,AI
在 Java 中,我正在从文件中读取上述文本并创建一个映射,其中键将是逗号之前的部分,值将是逗号之后的区域代码。
代码如下:
public static void main(String[] args) {
BufferedReader br;
Map<String,String> mymap = new HashMap<String,String>();
try {
br = new BufferedReader(new InputStreamReader(new FileInputStream("C:/Users/IBM_ADMIN/Desktop/region_code_abbreviations_Chinese.csv"), "UTF-8"));
String line;
while ((line = br.readLine()) != null) {
//System.out.println(line);
String[] arr= line.split(",");
mymap.put(arr[0], arr[1]);
}
br.close();
} catch (IOException e) {
System.out.println("Failed to read users file.");
} finally {}
for(String s: mymap.keySet()){
System.out.println(s);
if(s.equals("China-中国")){
System.out.println("Got it");
break;
}
}
System.out.println("----------------");
System.out.println("Returned from map "+ mymap.get("China-中国"));
mymap = new HashMap<String,String>();
mymap.put("China-中国","Explicitly Put");
System.out.println(mymap.get("China-中国"));
System.out.println("done");
}
输出:
:
:
Egypt-埃及
Guyana-圭亚那
New Zealand-新西兰
China-中国
Indonesia-印度尼西亚
Laos-老挝
Chad-乍得
Korea-韩国
:
:
Returned from map null
Explicitly Put
done
地图已正确加载,但是当我在地图上搜索 "China-中国" 时 - 我没有得到该值。
如果我明确地将 "China-中国" 放入映射中,那么它会 returns 一个值。
为什么会这样?
由于您对第一个值有疑问,我会检查文件是否以 BOM(字节顺序标记)开头。
如果是这样,请尝试在处理之前剥离 BOM。
参见:Byte order mark screws up file reading in Java
检查您的资源文件是否不是 UTF-8,例如UTF-8Y,以 BOM 字节开头。但这只会推断出第一个值。如果把test改成从中间取一个值,你有值还是没有?如果不是,那么这不是问题。
第二种可能是您的源代码文件不是UTF-8。因此,您的资源文件和源代码文件的 "China-中国" 字节序列不相等,您将无法匹配。但是您明确地将值包含在源代码字节序列中,它将被找到。
其实这不是HashMap的问题,而是字符或文件编码的问题。
您可以使用 org.apache.commons.io.input.BOMInputStream.
BufferedReader br= new BufferedReader(new InputStreamReader(new BOMInputStream(new FileInputStream("filepath")),"UTF-8"))
China-中国,CN
Angola-安哥拉,AO
Afghanistan-阿富汗,AF
Albania-阿尔巴尼亚,AL
Algeria-阿尔及利亚,DZ
Andorra-安道尔共和国,AD
Anguilla-安圭拉岛,AI
在 Java 中,我正在从文件中读取上述文本并创建一个映射,其中键将是逗号之前的部分,值将是逗号之后的区域代码。
代码如下:
public static void main(String[] args) {
BufferedReader br;
Map<String,String> mymap = new HashMap<String,String>();
try {
br = new BufferedReader(new InputStreamReader(new FileInputStream("C:/Users/IBM_ADMIN/Desktop/region_code_abbreviations_Chinese.csv"), "UTF-8"));
String line;
while ((line = br.readLine()) != null) {
//System.out.println(line);
String[] arr= line.split(",");
mymap.put(arr[0], arr[1]);
}
br.close();
} catch (IOException e) {
System.out.println("Failed to read users file.");
} finally {}
for(String s: mymap.keySet()){
System.out.println(s);
if(s.equals("China-中国")){
System.out.println("Got it");
break;
}
}
System.out.println("----------------");
System.out.println("Returned from map "+ mymap.get("China-中国"));
mymap = new HashMap<String,String>();
mymap.put("China-中国","Explicitly Put");
System.out.println(mymap.get("China-中国"));
System.out.println("done");
}
输出:
:
:
Egypt-埃及
Guyana-圭亚那
New Zealand-新西兰
China-中国
Indonesia-印度尼西亚
Laos-老挝
Chad-乍得
Korea-韩国
:
:
Returned from map null
Explicitly Put
done
地图已正确加载,但是当我在地图上搜索 "China-中国" 时 - 我没有得到该值。
如果我明确地将 "China-中国" 放入映射中,那么它会 returns 一个值。 为什么会这样?
由于您对第一个值有疑问,我会检查文件是否以 BOM(字节顺序标记)开头。
如果是这样,请尝试在处理之前剥离 BOM。
参见:Byte order mark screws up file reading in Java
检查您的资源文件是否不是 UTF-8,例如UTF-8Y,以 BOM 字节开头。但这只会推断出第一个值。如果把test改成从中间取一个值,你有值还是没有?如果不是,那么这不是问题。
第二种可能是您的源代码文件不是UTF-8。因此,您的资源文件和源代码文件的 "China-中国" 字节序列不相等,您将无法匹配。但是您明确地将值包含在源代码字节序列中,它将被找到。
其实这不是HashMap的问题,而是字符或文件编码的问题。
您可以使用 org.apache.commons.io.input.BOMInputStream.
BufferedReader br= new BufferedReader(new InputStreamReader(new BOMInputStream(new FileInputStream("filepath")),"UTF-8"))