2012-08-11 67 views
5

我遇到了一個非常不尋常的問題。
基本上,我試圖從字符串映射到字符串獲取與鍵相關聯的值。
我知道我使用的鑰匙是存在的;我使用的是我用來放入的同一個字符串!Java Map對於現有密鑰返回null

我一直都在我的代碼打印報表,這是情況下,我有...
這裏是我的字典characterDictionary

{thusChar=∴, spaceChar= , plusChar=+, equalsIndent=#, multiplyChar=×, equalsChar==, newlineChar=\n, divideChar=÷, subjectChar=:, [email protected]} 

的最後關鍵「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擰起來等)

發生什麼事了!?
我有一個狡猾的功能嗎?!
他們對其他一切都很好。

謝謝!

+0

爲了保證這關鍵是存在(UTF-8 BOM 0xEF,爲0xBB,爲0xBF「variableIndent」前),遍歷所有在此映射按鍵和打印他們的價值。 – 2012-08-11 07:07:38

+0

你能展示一些重現行爲嗎? – assylias 2012-08-11 07:08:59

+0

編輯了OP。相信它是文本文件和Eclipse之間的編碼問題。 – 2012-08-11 07:34:50

回答

6

更改爲UTF-8文本文件,其中包含UTF-8的密鑰和值,而不包含BOM。 有三個字節 看到http://en.wikipedia.org/wiki/Byte_order_mark

+0

我該怎麼做呢? – 2012-08-12 08:57:33

+1

你可以使用ultraedit或記事本++ – andy 2012-08-12 14:50:02

+0

@AntiEarth這可能有幫助...無論如何,如果你找到解決方案,請通知我。我很好奇你將如何解決這個奇怪的問題。可悲的是,還沒有任何自動的方法來解決關於SO的問題。 – dantuch 2012-08-12 18:31:22

0

我建議你在調試器中查看你的代碼。我懷疑地圖不是你想象的那樣。

String data = "{thusChar=∴, spaceChar= , plusChar=+, equalsIndent=#, multiplyChar=×, equalsChar==, newlineChar=\\n, divideChar=÷, subjectChar=:, [email protected]}"; 
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)); 
+0

印刷密鑰集和接收 '[thusChar,spaceChar,plusChar,equalsIndent,multiplyChar,equalsChar,newlineChar,divideChar,subjectChar,variableIndent]' – 2012-08-11 07:25:40

0

嗯試試這個代碼,讓我們知道輸出

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

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

上傳:可能要更改鍵和值的類型。

+0

thusChar spaceChar plusChar equalsIndent multiplyChar equalsChar newlineChar divideChar subjectChar variableIndent ∴ + # × = \ n ÷ : @ 與預期完全一樣! 我會嘗試使用密鑰更改 – 2012-08-11 07:22:56

+1

我看到10個密鑰和9個值。 – foklepoint 2012-08-11 07:38:34

+0

其中一個關鍵是空間。 – 2012-08-11 07:46:54

1

如果你害怕編碼問題(這似乎是這裏的問題),你必須確保你的項目編碼設置爲UTF-8。要檢查它,請轉至項目菜單,並選擇屬性。這可能需要從Inherited from container改變文本文件編碼Oher: UTF-8

+0

完成。仍然沒有成功。我絕對難住。 – 2012-08-11 09:00:44

+0

@反地球我想你應該從地圖上打印這兩個字符串的「hashCode()」,而這個是你搜索的,並且什麼也沒有結束。它們應該是相同的,如果它是相同的字符串。 – dantuch 2012-08-11 16:00:56

+0

在其他答案中探討了這一點;它們不是相同的字符串。無論來自文本文件的哪一行首先被處理並且首先被添加到字典中,以某種方式以隱藏的方式「變異」。仍然不知道如何或爲什麼。 – 2012-08-12 01:17:16

0

如果你認爲這是一個編碼問題,那麼請嘗試使用以下方法來實際內容相比較,不管它是什麼樣子。

使用getBytes()來獲取所有來自兩個字符串中的字節數(從地圖的關鍵,以及在你的串碼),並打印

  1. 字節數組
  2. 每個字節的長度作爲一個整數

然後使用getChars()來獲取所有從兩個字符串或charAt()的字符讀取每個字符,並打印

  1. 每個字符都是一個整數。

在這兩項檢查之間,您應該能夠弄清楚兩個字符串在字節級別上的差異。文件保存的字符集是什麼?

編輯

我懷疑你的DataInputStream類的使用是造成被讀取的字節數的問題。

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

的Java文檔爲DataInputStream所說「A數據輸入流允許應用程序以與機器無關的方式從底層輸入流中讀取基本Java數據類型。一個應用程序使用的數據輸出流寫入數據,可以稍後由數據輸入流讀取。「這裏不是從DataOutputStream中讀取數據,而只是一個常規文件。 另外,您已經有了InputStream供InputStreamReader使用。你的代碼改成這樣:

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

EDIT 2

另一件事值得做的,因爲你的字符串從文本文件是3個字節長,正在改變這一

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

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

我對問題進行了更新,使我認爲編碼可能不再相關:P – 2012-08-11 09:16:17

+0

您可以使用所發現的內容更新問題嗎? – 2012-08-11 09:21:29

+0

當然! (對不起,我的速度非常緩慢) – 2012-08-11 09:29:42

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


}