我遇到了一个非常不寻常的问题 基本上,我正在尝试从字符串映射到字符串中获取与键相关联的值 我知道我正在使用的钥匙存在;我使用的是与之相同的字符串!
我已在我的代码中打印语句,这就是我的情况......
这是我的词典 characterDictionary
{thusChar=∴, spaceChar= , plusChar=+, equalsIndent=#, multiplyChar=×, equalsChar==, newlineChar=\n, divideChar=÷, subjectChar=:, variableIndent=@}
最后一个关键的“variableIndent”就是麻烦! 这是代码......
System.out.println ( characterDictionary.get("variableIndent") );
不恰当地输出:null
我已经检查过,双重检查并三重检查了我的代码
键 “variableIndent” 与characterDictionary.get("variableIndent")
的字符串参数之间完全没有区别,但它的行为就像没有此键一样。
我绝对可以保证这个密钥存在,并且两个字符串是相同的 所有其他元素(我检查过的那些;到目前为止大约3个)都是正常检索的。为什么“variableIndent”会显示“@”值?
您可能会注意到字典包含非ASCII字符,例如“soChar”。这可能是相关的吗?
感谢
(这似乎是一个非常简单和微不足道的问题,好像我犯了一些可耻的错误,但我却无法解决它!)
修改
好的,这与编码有关
我从字典中取出字符串键并将其与我的get参数进行比较
打印时,它们是相同的,但java说它们不相等
键字符串来自UTF-8编码的文本文件,而参数字符串来自java Eclipse文字
但是字符是相同的。
问题是什么,我该如何解决?
谢谢!
修改
嗯,这就是幕后实际发生的事情 我有一个UTF-8文本文件,其中包含以下内容......variableIndent,@
equalsIndent,#
spaceChar,
newlineChar,\n
multiplyChar,×
divideChar,÷
plusChar,+
equalsChar,=
subjectChar,:
thusChar,∴
我通过传递文件的目录,通过读取文件的每一行作为ArrayList<String>
元素来'加载'这个文件:
private static ArrayList<String> readLinesFile(String ResourceFile) {
ArrayList<String> Lines = new ArrayList<String>();
try{
InputStream fstream = FileManager.class.getResourceAsStream(ResourceFile);
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
String strLine;
while ((strLine = br.readLine()) != null) {
Lines.add(strLine); }
in.close(); }
catch (Exception e) {
System.out.println("Error: " + e.getMessage()); }
return Lines; }
这里的一切都很好。
然后我将这个ArrayList传递给一个函数,该函数用“,”字符分割每个元素(使用个人包中的函数;绝对不是问题),并将第一部分作为第二部分添加到新的第二部分中字典。
private static Map<String, String> generateBaseUnits_Characters_Prefixes(ArrayList<String> FileContent) {
Map<String, String> BaseUnitsCache = new HashMap<String, String>();
ArrayList<String> currentLine;
for (int i=0; i<FileContent.size(); i++) {
currentLine = MiscellaneousFunctions.splitString(FileContent.get(i), ",");
BaseUnitsCache.put(currentLine.get(0), currentLine.get(1)); }
return BaseUnitsCache; }
这会产生导致所有麻烦的字典 我有一组与文本文件中的字符名称相对应的Key Literals,我用它来访问程序中的字典。
public static String variableIndentKey = "variableIndent";
public static String equalsIndentKey = "equalsIndent";
public static String spaceCharKey = "spaceChar";
public static String newlineCharKey = "newlineChar";
public static String multiplyCharKey = "multiplyChar";
public static String divideCharKey = "divideChar";
public static String plusCharKey = "plusChar";
public static String equalsCharKey = "equalsChar";
public static String subjectCharKey = "subjectChar";
public static String thusCharKey = "thusChar";
这是问题所在:
文本文件的顶行在字典中“搞砸了”。
它被添加到字典中并正确显示在keySet和字典的打印格式中,但尝试访问它会返回“null”。
(在这种情况下,它是variableIndent。如果我将variableIndent放在文本文件中的其他位置,则equalsIndent拧紧等等)
发生了什么事!?
我有狡猾的功能吗?!
他们在其他一切方面都运作良好。
谢谢!
答案 0 :(得分:6)
将包含密钥和值的UTF-8文本文件更改为没有BOM的UTF-8。 在“variableIndent”之前有三个字节(UTF-8 BOM 0xEF,0xBB,0xBF) 见http://en.wikipedia.org/wiki/Byte_order_mark
答案 1 :(得分:1)
如果您害怕编码问题(这似乎是问题),您必须确保项目的编码设置为UTF-8
。要进行检查,请转到项目菜单,然后选择属性。可能需要将文本文件编码从Inherited from container
更改为Oher: UTF-8
答案 2 :(得分:0)
我建议你在调试器中查看你的代码。我怀疑地图不是你想象的那样。
String data = "{thusChar=∴, spaceChar= , plusChar=+, equalsIndent=#, multiplyChar=×, equalsChar==, newlineChar=\\n, divideChar=÷, subjectChar=:, variableIndent=@}";
Map<String, String> map = new LinkedHashMap<String, String>();
for (String keyValue : data.substring(1, data.length() - 1).split(", ")) {
String[] parts = keyValue.split("=", 2);
map.put(parts[0], parts[1]);
}
System.out.println("variableIndent is " + map.get("variableIndent"));
打印
variableIndent is @
for(String key: map.keySet())
System.out.println("'"+key+"'= "+map.get(key));
答案 3 :(得分:0)
嗯尝试这段代码,让我们知道输出
for (String key : characterDictionary.keySet() ) {
System.out.println(key);
}
for ( String value : characterDictionary.values() ) {
System.out.println(value);
}
P.S:可能想要更改键和值的类型。
答案 4 :(得分:0)
如果您认为这是编码问题,请尝试使用以下方法来比较实际内容,而不管其外观如何。
使用getBytes()
从两个字符串中获取所有字节(地图中的键,以及代码中的字符串),然后打印
然后使用getChars()
从字符串或charAt()
获取所有字符以读取每个字符,并打印
在这两个检查之间,您应该能够弄清楚两个字符串在字节级别上是如何不同的。保存文件的字符集是什么?
修改强>
我怀疑你使用DataInputStream会导致读取字节出现问题。
InputStream fstream = FileManager.class.getResourceAsStream(ResourceFile);
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
DataInputStream的Java文档说:“数据输入流允许应用程序以与机器无关的方式从底层输入流中读取原始Java数据类型。应用程序使用数据输出流来写入以后可以读取的数据数据输入流。“你不是在这里读取DataOutputStream,只是一个常规文件。 此外,您已经有一个InputStream用于InputStreamReader。将您的代码更改为:
InputStream fstream = FileManager.class.getResourceAsStream(ResourceFile);
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
编辑2
另一件值得做的事情,因为来自文本文件的字符串长3个字节,正在改变这个
BaseUnitsCache.put(currentLine.get(0), currentLine.get(1));
到
BaseUnitsCache.put(currentLine.get(0).trim(), currentLine.get(1).trim());
答案 5 :(得分:0)
以这种方式试试......
Map<String, String> map = new LinkedHashMap<String, String>();
for (Map.Entry<String, String> mp : map.entrySet()){
System.out.println("Key: "+mp.key()+"::"+"Value: "+mp.value());
}