6

我有一个非常不寻常的问题。
基本上,我试图从字符串映射到字符串中获取与键关联的值。
我知道我正在使用的密钥存在;我使用的是我用来放入它的相同字符串!

我已经在我的代码中打印了语句,这是我的情况......
这是我的字典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 字符,例如“thusChar”。这可能有关系吗?

谢谢
(这似乎是一个非常简单和微不足道的问题,好像我犯了一些可怜的愚蠢错误,但我就是无法解决它!)

编辑:

好的,这必须与编码有关。
我从字典中取出字符串键并将其与我的 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;  }

这会产生导致所有麻烦的字典。
我有一组与文本文件中的字符名称相对应的关键文字,我用它们来访问程序中的字典。

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 搞砸了,等等)

这是怎么回事!?
我有一个狡猾的功能吗?
他们在其他所有方面都运作良好。

谢谢!

4

6 回答 6

6

将包含键和值的 UTF-8 文本文件更改为没有 BOM 的 UTF-8。有三个字节(UTF-8 BOM 0xEF,0xBB,0xBF 在“variableIndent”之前)见http://en.wikipedia.org/wiki/Byte_order_mark

于 2012-08-12T08:24:53.063 回答
1

如果你害怕编码问题(这似乎是这里的问题),你必须确保你的项目的编码设置为UTF-8. 要检查它,请转到Project菜单,然后选择Properties。可能需要将文本文件编码从更改Inherited from containerOher: UTF-8

于 2012-08-11T08:28:38.927 回答
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));
于 2012-08-11T07:08:20.397 回答
0

嗯,试试这段代码,让我们知道输出

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

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

PS:可能想要更改键和值的类型。

于 2012-08-11T07:15:28.027 回答
0

如果您认为这是编码问题,请尝试使用以下方法来比较实际内容,无论它看起来如何。

用于getBytes()从两个字符串中获取所有字节(地图中的键,以及代码中的字符串),然后打印

  1. 字节数组的长度
  2. 每个字节为整数

然后用于getChars()从两个字符串中获取所有字符或charAt()读取每个字符,然后打印

  1. 每个 char 作为一个整数。

在这两个检查之间,您应该能够找出两个字符串在字节级别上的不同之处。保存文件的字符集是什么?

编辑

我怀疑您对 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());
于 2012-08-11T09:10:38.240 回答
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());


}
于 2012-08-11T09:21:00.727 回答