2012-08-11 16 views
5

Tengo un problema muy inusual.
Básicamente, estoy tratando de obtener el valor asociado con una clave desde un Mapa de Cadenas a Cadenas.
Sé que la clave que estoy usando está presente; ¡Estoy usando la misma cadena que usé para ponerlo!Java Map devuelve nulo para una clave actual

tengo instrucciones de impresión de todo mi código, y este es el caso que tengo ...
Aquí es mi diccionario characterDictionary

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

La última tecla "variableIndent" es la ¡problema!
Aquí está el código ...

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

cual inapropiadamente salidas: null

He comprobado, verificado doble y el triple comprobado mi código.
no hay absolutamente ninguna diferencia entre la clave "variableIndent" y el argumento de cadena de characterDictionary.get("variableIndent"), sin embargo, se comporta como si esta clave no estaba presente.

Puedo garantizar que esta clave está presente, y que las dos cadenas son idénticas.
Todos los demás elementos (los que he comprobado, aproximadamente 3 hasta el momento) del diccionario se recuperan de forma normal. ¿Por qué está "variableIndent" con su valor "@" activo?

Es posible que observe que el diccionario no contiene caracteres ASCII, como "thusChar". ¿Podría esto estar relacionado?

Gracias
(Este parece ser un problema muy simple y trivial, como si yo he cometido un error lamentable tonto, pero sin embargo, yo simplemente no puede resolverlo!)

EDIT:

Bueno, esto tiene que ser algo sobre la codificación.
Cogí la clave de cadena del diccionario y la comparé con mi argumento get.
Cuando se imprimen, son idénticos, pero Java dice que no son iguales.
La cadena de clave provino de un archivo de texto codificado en UTF-8, mientras que la cadena de argumento proviene de un literal de Eclipse de Java.
Sin embargo, los caracteres son idénticos.
¿Cuál es el problema y cómo puedo resolverlo?

Gracias!

EDIT:

Hmmm, esto es lo que realmente está sucediendo detrás de las escenas.
Tengo un archivo de texto UTF-8 que contiene el siguiente contenido ...

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

I 'carga' este archivo mediante la lectura en cada línea del archivo como un elemento ArrayList<String>, pasando el directorio del archivo:

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; } 

todo está bien hasta aquí.
Luego transfiero este ArrayList a una función que divide cada elemento por el carácter "," (usando una función de un paquete personal; definitivamente no es el problema) y agrega la primera parte como clave para el segundo el nuevo diccionario.

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; } 

y esto produce el diccionario que está causando todos los problemas.
Tengo un conjunto de Key Literals que corresponden a los nombres de los caracteres en los archivos de texto, que utilizo para acceder al diccionario en el programa.

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

está aquí el problema:

La línea superior del archivo de texto '' mete la pata en el diccionario. Se agrega al diccionario y aparece correctamente entre keySet y el formato impreso del diccionario, pero al intentar acceder se devuelve "nulo".
(En este caso, es variableIndent. Si pongo VariableIndent en otro lugar en el archivo de texto, igualInstala tornillos, etc.)

¡¿Qué está pasando ?!
¿Tengo una función dudosa ?!
Han funcionado bien para todo lo demás.

Gracias!

+0

Para garantizar que esta clave está presente, iterar sobre todas las llaves en este mapa e imprimir su valor. –

+0

¿Puedes mostrar alguno que reproduzca el comportamiento? – assylias

+0

editó el OP. Creo que es un problema de codificación entre un archivo de texto y Eclipse. –

Respuesta

6

cambie su archivo de texto UTF-8 que contiene la clave y el valor de UTF-8 sin BOM. Hay tres bytes (BOM UTF-8 0xEF, 0xBB, 0xBF antes "variableIndent") ver http://en.wikipedia.org/wiki/Byte_order_mark

+0

¿Cómo voy a hacer eso? –

+1

puede usar ultraedit o bloc de notas ++ – andy

+0

@AntiEarth Esto puede ayudar ... De todos modos, si encuentra una solución, informe también a mí. Tengo curiosidad de cómo vas a resolver un problema tan extraño. Lamentablemente, no hay ninguna forma automática de preguntas en barbecho en SO. – dantuch

0

Te sugiero que mires tu código en un depurador. Sospecho que el mapa no es lo que crees que es.

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

impresiones

variableIndent is @ 

pueden intentar

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

imprime el conjunto de claves y recibieron '[thusChar, spaceChar, plusChar, equalsIndent, multiplyChar, equalsChar, newlineChar, divideChar, subjectChar, variableIndent]' –

0

Hmm prueba este código y haznos saber la salida

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

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

P.S: Podría querer cambiar Tipo de clave y valor.

+0

thusChar spaceChar plusChar equalsIndent multiplyChar equalsChar newlineChar divideChar subjectChar variableIndent ∴ + # × = \ n ÷ : @ ¡Exactamente como se esperaba! Lo intentaré con la clave changd –

+1

Veo 10 claves y 9 valores. – foklepoint

+0

Una de las claves es un espacio. –

1

Si tiene miedo de problemas de codificación (que parece ser el problema aquí), debe asegurarse de que la codificación de su proyecto esté configurada en UTF-8. Para verificarlo, vaya al menú Proyecto, y elija Propiedades. Puede ser necesario cambiar la codificación de archivos de texto Inherited from container-Oher: UTF-8

+0

Hecho. Todavía no hay éxito Estoy absolutamente perplejo. –

+0

@Anti Earth Supongo que debe imprimir 'hashCode()' de "both" Strings - this1 del mapa, y this1 que busca y termina con nada. Deberían ser lo mismo, si es la misma Cadena. – dantuch

+0

Exploré esto en otras respuestas; no son la misma cadena. Cualquiera que sea la línea del archivo de texto que se procesa primero y se agrega primero al diccionario, de alguna manera 'muta' de forma oculta. Todavía no sé cómo ni por qué. –

0

Si usted piensa que es un problema de codificación, a continuación, intente utilizar los siguientes métodos para comparar el contenido real, independientemente de lo que parece.

Uso getBytes() para obtener todos los bytes de ambas cadenas (la clave del mapa, así como la cadena en su código), e imprimir

  1. La longitud de la matriz de bytes
  2. Cada byte como un entero

a continuación, utilice getChars() para obtener todos los caracteres de ambas cadenas o charAt() para leer cada char, e imprimir

  1. Cada carácter como un número entero.

Entre estas dos comprobaciones, debe ser capaz de descubrir cómo ambas cadenas son diferentes en un nivel de byte. ¿Cuál es el conjunto de caracteres en el que se guarda el archivo?

EDITAR

que sospecha que su uso de DataInputStream está causando problemas con los bytes que se leen.

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

La documentación de Java para DataInputStream dicen "Un flujo de entrada de datos permite a una aplicación leer tipos de datos primitivos de Java a partir de un flujo de entrada subyacente de una manera independiente de la máquina. Una aplicación utiliza una corriente de salida de datos para escribir datos que pueden más tarde será leído por una secuencia de entrada de datos ". No está leyendo desde un DataOutputStream aquí, solo un archivo normal. Además, ya tiene un InputStream para que el InputStreamReader lo use. Cambiar el código para esto:

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

EDIT 2

Otra cosa vale la pena hacerlo, ya que la cadena del archivo de texto es de 3 bytes más tiempo, está cambiando esta

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

a

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

Tengo una actualización del problema que me hace pensar que la codificación puede no ser relevante: P –

+0

¿Podría actualizar la pregunta con lo que ha encontrado? –

+0

¡Ciertamente! (Lo siento, soy notablemente lento en todo) - –

0

Pruébalo de esta manera ...

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


} 
Cuestiones relacionadas