简体   繁体   English

Java Map为当前键返回null

[英]Java Map returns null for a present key

I'm having a very unusual problem. 我有一个非常不寻常的问题。
Basically, I'm trying to get the value associated with a key from a Map of Strings to Strings. 基本上,我正在尝试从字符串映射到字符串获取与键相关联的值。
I know that the key I'm using is present; 我知道我正在使用的钥匙存在; I'm using the same string I used to put it in! 我使用的是与之相同的字符串!

I've print statements all over my code, and this is case I have... 我在我的代码中打印了一些语句,这就是我的情况......
Here is my dictionary characterDictionary 这是我的字典characterDictionary

{thusChar=∴, spaceChar= , plusChar=+, equalsIndent=#, multiplyChar=×, equalsChar==, newlineChar=\n, divideChar=÷, subjectChar=:, variableIndent=@}

The very last key "variableIndent" is the trouble! 最后一个关键“variableIndent”就是麻烦!
Here's the code... 这是代码......

System.out.println  (   characterDictionary.get("variableIndent") );

which inappropriately outputs: null 不恰当地输出: null

I have checked, double checked and triple checked my code. 我已检查,双重检查并三重检查我的代码。
There is absolutely no difference between the key "variableIndent" and the string argument of characterDictionary.get("variableIndent") , yet it's behaving as if this key was not present. “variableIndent”characterDictionary.get("variableIndent")的字符串参数之间完全没有区别,但它的行为就好像这个键不存在一样。

I can absolutely guarantee this key is present, and that the two strings are identical. 我绝对可以保证这个密钥存在,并且两个字符串是相同的。
All the other elements (the ones I've checked; about 3 so far) of the dictionary are retrieved as normal. 所有其他元素(我检查过的那些;到目前为止大约3个)都是正常检索的。 Why is "variableIndent" with it's "@" value playing up? 为什么“variableIndent”的“@”值正在播放?

You might notice the dictionary contains non ASCII characters, like "thusChar". 您可能会注意到该字典包含非ASCII字符,例如“soChar”。 Could this be related? 这有关系吗?

Thanks 谢谢
(This seems like a very simple and trivial problem, as if I've made some pitifully silly mistake, but yet I just can't solve it!) (这似乎是一个非常简单和微不足道的问题,好像我犯了一些可怜的愚蠢错误,但我却无法解决它!)

EDIT: 编辑:

Okay, this HAS to be something about encoding. 好的,这是关于编码的东西。
I took the string key from the dictionary and compared it to my get argument. 我从字典中取出字符串键并将其与我的get参数进行比较。
When printed, they are identical, but java says they are not equal. 打印时,它们是相同的,但java说它们并不相同。
The key string came from a UTF-8 encoded text file, whilst the argument string came from a java Eclipse literal. 键字符串来自UTF-8编码的文本文件,而参数字符串来自java Eclipse文字。
The characters are identical however. 但是字符是相同的。
What is the issue, and how can I resolve it? 问题是什么,我该如何解决?

Thanks! 谢谢!

EDIT: 编辑:

Hmmm, here's what's actually happening behind the scenes. 嗯,这就是幕后实际发生的事情。
I have a UTF-8 text file which contains the following content... 我有一个UTF-8文本文件,其中包含以下内容......

variableIndent,@
equalsIndent,#
spaceChar, 
newlineChar,\n
multiplyChar,×
divideChar,÷
plusChar,+
equalsChar,=
subjectChar,:
thusChar,∴

I 'load' this file by reading in each line of the file as an ArrayList<String> element, by passing the directory of the file: 我通过传递文件的目录,通过读取文件的每一行作为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;  }

Everything is fine up to here. 这里的一切都很好。
I then pass this ArrayList into a function that splits up each element by the "," character (using a function from a personal package; It is definitely not the issue), and adds the first part as a key to the second in the new dictionary. 然后我将这个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;  }

and this produces the dictionary that is causing all the trouble. 这会产生导致所有麻烦的字典。
I have a set of Key Literals that correspond to the character names in the text files, which I use to access the dictionary in the program. 我有一组与文本文件中的字符名称相对应的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";

HERE'S THE PROBLEM: 这是问题所在:

The top line of the textfile 'screws up' in the dictionary. 文本文件的顶行在字典中“搞砸了”。 It is added to the dictionary and appears correctly amongst the keySet and the printed format of the dictionary, but trying to access it returns "null". 它被添加到字典中并正确显示在keySet和字典的打印格式中,但尝试访问它会返回“null”。
(In this case, it's variableIndent. If I put variableIndent somewhere else in the text file, equalsIndent screws up, etc) (在这种情况下,它是variableIndent。如果我将variableIndent放在文本文件中的其他位置,则equalsIndent拧紧等)

What's going on!? 这是怎么回事!?
Do I have a dodgy function?! 我有狡猾的功能吗?!
They've worked well for everything else. 他们对其他一切都很好。

Thanks! 谢谢!

change you UTF-8 text file which contains the key and value to UTF-8 without BOM. 将包含密钥和值的UTF-8文本文件更改为不带BOM的UTF-8。 There are three bytes(UTF-8 BOM 0xEF,0xBB,0xBF before "variableIndent") see http://en.wikipedia.org/wiki/Byte_order_mark 在“variableIndent”之前有三个字节(UTF-8 BOM 0xEF,0xBB,0xBF),请参阅http://en.wikipedia.org/wiki/Byte_order_mark

If you are afraid of encoding issues (that seems to be the problem here), you have to make sure your project's encoding is set to UTF-8 . 如果您害怕编码问题(这似乎是问题),您必须确保项目的编码设置为UTF-8 To check it, go to Project menu, and choose Properties . 要进行检查,请转到“ 项目”菜单,然后选择“ 属性” It may be required to change text file encoding from Inherited from container to Oher: UTF-8 可能需要将文本文件编码Inherited from container更改为Oher: UTF-8

I suggest you look at your code in a debugger. 我建议你在调试器中查看你的代码。 I suspect the map is not what you think it is. 我怀疑地图不是你想象的那样。

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"));

prints 版画

variableIndent is @

can you try 你能试一下吗

for(String key: map.keySet())
   System.out.println("'"+key+"'= "+map.get(key));

Hmm try this code and let us know the output 嗯尝试这段代码,让我们知道输出

for (String key : characterDictionary.keySet() ) {
System.out.println(key);
}

for ( String value :  characterDictionary.values() ) {
System.out.println(value);
}

PS: Might want to change Type of key and value. PS:可能想要更改键和值的类型。

If you think it's an encoding issue, then try using the following methods to compare the actual content, irrespective of what it looks like. 如果您认为这是一个编码问题,那么请尝试使用以下方法来比较实际内容,而不管其外观如何。

Use getBytes() to get all the bytes from both Strings (the key from the map, as well as the string in your code), and print 使用getBytes()从两个字符串中获取所有字节(来自地图的键,以及代码中的字符串),并打印

  1. The length of the byte array 字节数组的长度
  2. Each byte as an integer 每个字节为整数

Then use getChars() to get all the chars from both Strings or charAt() to read each char, and print 然后使用getChars()获取来自Strings或charAt()所有字符以读取每个char,并打印

  1. Each char as an integer. 每个char为整数。

Between these two checks you should be able to figure out how both strings are different at a byte level. 在这两个检查之间,您应该能够弄清楚两个字符串在字节级别上是如何不同的。 What's the character-set that the file is saved in? 保存文件的字符集是什么?

EDIT 编辑

I suspect your use of DataInputStream is causing problems with the bytes being read. 我怀疑你使用DataInputStream会导致读取字节的问题。

InputStream fstream = FileManager.class.getResourceAsStream(ResourceFile);
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));

The Java docs for DataInputStream say "A data input stream lets an application read primitive Java data types from an underlying input stream in a machine-independent way. An application uses a data output stream to write data that can later be read by a data input stream." DataInputStream的Java文档说:“数据输入流允许应用程序以与机器无关的方式从底层输入流中读取原始Java数据类型。应用程序使用数据输出流来写入数据,以后可以通过数据输入读取流。” You're not reading from a DataOutputStream here, just a regular file. 你不是在这里读取DataOutputStream,只是一个常规文件。 Also, you already have an InputStream for the InputStreamReader to use. 此外,您已经有一个InputStream用于InputStreamReader。 Change your code to this: 将您的代码更改为:

InputStream fstream = FileManager.class.getResourceAsStream(ResourceFile);
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));

EDIT 2 编辑2

Another thing worth doing, since your string from the text file is 3 bytes longer, is changing this 另一件值得做的事情,因为你的文本文件中的字符串长3个字节,正在改变它

BaseUnitsCache.put(currentLine.get(0), currentLine.get(1));

to

BaseUnitsCache.put(currentLine.get(0).trim(), currentLine.get(1).trim());

Try it this way... 试试这种方式......

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());


}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM