forname example convertir charset java string character-encoding nio bytebuffer

example - convertir string a utf-8 java



Java: conversión de String ay desde ByteBuffer y problemas asociados (4)

A menos que las cosas hayan cambiado, estará mejor con

public static ByteBuffer str_to_bb(String msg, Charset charset){ return ByteBuffer.wrap(msg.getBytes(charset)); } public static String bb_to_str(ByteBuffer buffer, Charset charset){ byte[] bytes; if(buffer.hasArray()) { bytes = buffer.array(); } else { bytes = new byte[buffer.remaining()]; buffer.get(bytes); } return new String(bytes, charset); }

Por lo general, buffer.hasArray () siempre será verdadero o siempre falso según su caso de uso. En la práctica, a menos que realmente desee que funcione bajo ninguna circunstancia, es seguro optimizar la rama que no necesita.

Estoy usando Java NIO para mis conexiones de socket, y mi protocolo está basado en texto, así que necesito poder convertir cadenas en ByteBuffers antes de escribirlas en el SocketChannel, y convertir los ByteBuffers entrantes a cadenas. Actualmente, estoy usando este código:

public static Charset charset = Charset.forName("UTF-8"); public static CharsetEncoder encoder = charset.newEncoder(); public static CharsetDecoder decoder = charset.newDecoder(); public static ByteBuffer str_to_bb(String msg){ try{ return encoder.encode(CharBuffer.wrap(msg)); }catch(Exception e){e.printStackTrace();} return null; } public static String bb_to_str(ByteBuffer buffer){ String data = ""; try{ int old_position = buffer.position(); data = decoder.decode(buffer).toString(); // reset buffer''s position to its original so it is not altered: buffer.position(old_position); }catch (Exception e){ e.printStackTrace(); return ""; } return data; }

Esto funciona la mayor parte del tiempo, pero me pregunto si esta es la forma preferida (o la más simple) de hacer cada dirección de esta conversión, o si hay otra forma de intentarlo. Ocasionalmente, y aparentemente al azar, las llamadas a encode() y decode() arrojarán una excepción java.lang.IllegalStateException: Current state = FLUSHED, new state = CODING_END , o similar, incluso si estoy usando un nuevo objeto ByteBuffer cada vez una conversión esta hecha. ¿Necesito sincronizar estos métodos? ¿Alguna mejor forma de convertir entre cadenas y ByteBuffers? ¡Gracias!


Consulte las descripciones de la API CharsetEncoder y CharsetDecoder : debe seguir una secuencia específica de llamadas a métodos para evitar este problema. Por ejemplo, para CharsetEncoder :

  1. Restablezca el codificador mediante el método de reset , a menos que no se haya utilizado antes;
  2. Invoque el método de encode cero o más veces, siempre que la entrada adicional esté disponible, pase false para el argumento endOfInput y llene el búfer de entrada y vacíe el búfer de salida entre invocaciones;
  3. Invoque el método de encode una vez final, pasando true para el argumento endOfInput; y entonces
  4. Invoque el método de flush para que el codificador pueda descargar cualquier estado interno al buffer de salida.

Por cierto, este es el mismo enfoque que estoy usando para NIO, aunque algunos de mis colegas están convirtiendo cada char directamente en un byte con el conocimiento de que solo están usando ASCII, lo que me imagino es probablemente más rápido.


La respuesta de Adamski es buena y describe los pasos en una operación de codificación cuando se utiliza el método de codificación general (que toma un búfer de bytes como una de las entradas)

Sin embargo, el método en cuestión (en esta discusión) es una variante de encode - encode (CharBuffer in) . Este es un método de conveniencia que implementa toda la operación de codificación . (Por favor, consulte la referencia de documentos java en PS)

Según los documentos, este método, por lo tanto, no debe invocarse si una operación de codificación ya está en curso (que es lo que está sucediendo en el código de ZenBlender, utilizando el codificador / decodificador estático en un entorno de múltiples hilos).

Personalmente, me gusta usar métodos de conveniencia (sobre los métodos más generales de codificación / decodificación) ya que eliminan la carga al realizar todos los pasos debajo de las cubiertas.

ZenBlender y Adamski ya han sugerido varias maneras de hacer esto de manera segura en sus comentarios. Listado de todos aquí:

  • Cree un nuevo codificador / objeto decodificador cuando sea necesario para cada operación (no eficiente ya que podría conducir a una gran cantidad de objetos). O,
  • Use un ThreadLocal para evitar crear un nuevo codificador / decodificador para cada operación. O,
  • Sincronice toda la operación de codificación / decodificación (esto puede no ser preferible a menos que sacrificar algo de concurrencia sea correcto para su programa)

PD

referencias de documentos java:

  1. Método de codificación (comodidad): http://docs.oracle.com/javase/6/docs/api/java/nio/charset/CharsetEncoder.html#encode%28java.nio.CharBuffer%29
  2. Método de codificación general: http://docs.oracle.com/javase/6/docs/api/java/nio/charset/CharsetEncoder.html#encode%28java.nio.CharBuffer,%20java.nio.ByteBuffer,%20boolean%29

I am getting the same exception "java.lang.Illegalstate.exception when i run the below code protected static SAMStringResult execScript(ConfParams params, String routineName, String[] enquiryInParams) { SAMStringResult res = new SAMStringResult(); res.setSuccess(false, null); res.message = "T24Tools.ExecScript: failed for unknown reason"; res.setResult(""); try { DefaultJConnectionFactory jcf = new DefaultJConnectionFactory(); jcf.setHost(params.Host); jcf.setPort(params.Port); JConnection jc = jcf.getConnection(params.User, params.Password); JSubroutineParameters rtnParams = new JSubroutineParameters(); JDynArray shellNameParam = new JDynArray(routineName); rtnParams.add(shellNameParam); JDynArray outputParam = new JDynArray(routineName); rtnParams.add(outputParam); JSubroutineParameters rtnOutParams = jc.call("SAM.EXEC.SHELL", rtnParams); res.setSuccess(true, null); res.message = "T24Tools.ExecScript: job executed"; JDynArray resParam = rtnOutParams.get(1); String resStr = ""; System.out.println("Parameterssize :" + resParam.getNumberOfAttributes()); if (resParam != null) { for (int i = 0; i < 90145; i++) { if (i > 0) { resStr += "/n"; } resStr += resParam.get(i + 1); } } String fixedResStr = removeInvalidXmlCharacters(resStr); res.setResult(fixedResStr); jc.close(); } catch (Exception ex) { System.out.println("Exception in execScript :"+ex.getMessage()); res.setSuccess(false, ex); res.message = "T24Tools.ExecScript: unexpected error ocured"; res.setResult(""); } return res; } When i try to loop the for loop in my code 10,000 times. Code is working fine. But the actual number of times it has to run is 90,145 times. In between the iteration this exception araises. I am unable to find the reason behind this exception. can anyone help me in this?