문제

소켓 연결에 java nio를 사용하고 있으며 프로토콜은 텍스트 기반이므로 문자열을 바이트 버퍼로 변환하기 전에 Socketchannel로 쓰고 들어오는 바이트 버퍼를 문자열로 다시 변환 할 수 있어야합니다. 현재이 코드를 사용하고 있습니다.

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

이것은 대부분의 시간에 작동하지만, 이것이이 변환의 각 방향을 수행하는 선호하는 (또는 가장 간단한) 방법인지 또는 시도 할 다른 방법이 있는지에 대해 의문을 제기합니다. 때때로, 그리고 겉보기에는 무작위로 전화를합니다 encode() 그리고 decode() ajava.lang.IllegalStateException: Current state = FLUSHED, new state = CODING_END 전환이 완료 될 때마다 새로운 바이 테 버퍼 객체를 사용하는 경우에도 예외 또는 이와 유사합니다. 이 방법을 동기화해야합니까? 문자열과 바이트 버퍼 사이를 변환하는 더 좋은 방법은 무엇입니까? 감사!

도움이 되었습니까?

해결책

확인하십시오 CharsetEncoder 그리고 CharsetDecoder API 설명 - 따라야합니다 특정 메소드 호출 순서 이 문제를 피하기 위해. 예를 들어 CharsetEncoder:

  1. 인코더를 다시 재설정하십시오 reset 이전에 사용되지 않은 경우 방법;
  2. 호출 encode 추가 입력을 사용할 수있는 한 메소드 0 이상 false endofinput 인수 및 입력 버퍼를 채우고 호출 사이의 출력 버퍼를 플러싱하는 경우;
  3. 호출 encode 메소드 마지막 시간, 통과 true endofinput 인수를 위해; 그리고
  4. 호출 flush 인코더가 내부 상태를 출력 버퍼로 플러시 할 수 있도록 방법.

그건 그렇고, 이것은 내가 NIO에 사용하는 것과 동일한 접근법이지만, 일부 동료들은 각 Char를 ASCII 만 사용하고 있다는 지식의 바이트로 직접 변환하고 있지만 아마도 더 빠를 수 있습니다.

다른 팁

상황이 바뀌지 않으면 더 나은 것이 더 좋습니다

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

일반적으로 buffer.hasarray ()는 사용 사례에 따라 항상 사실이거나 항상 거짓입니다. 실제로, 어떤 상황에서도 실제로 일하기를 원하지 않는 한 필요하지 않은 지점을 최적화하는 것이 안전합니다.

Adamski의 답변은 좋은 것이며 일반 인코딩 메소드를 사용할 때 인코딩 작업의 단계를 설명합니다 (바이트 버퍼를 입력 중 하나로 가져옵니다).

그러나 문제의 방법 (이 토론에서)은 인코딩의 변형입니다. Encode (charbuffer in). 이것은 전체 인코딩 작업을 구현하는 편의 방법. (PS의 Java Docs Reference 참조)

문서에 따라 따라서 인코딩 작업이 이미 진행중인 경우이 방법을 호출하지 않아야합니다. (Zenblender 코드에서 일어나는 일 - 다중 스레드 환경에서 정적 인코더/디코더를 사용하여).

개인적으로, 나는 사용하는 것을 좋아합니다 편의 표지 아래의 모든 단계를 수행하여 부담을 제거 할 때 방법 (보다 일반적인 인코딩/디코딩 메소드).

Zenblender와 Adamski는 이미 의견에서 안전하게이를 수행하는 여러 가지 방법을 제안했습니다. 여기에 모두 나열 :

  • 각 작업에 필요할 때 새 인코더/디코더 객체를 만듭니다 (많은 수의 객체로 이어질 수 있으므로 효율적이지 않음). 또는,
  • 각 작업에 대한 새로운 인코더/디코더를 생성하지 않으려면 ThreadLocal을 사용하십시오. 또는,
  • 전체 인코딩/디코딩 작업 동기화 (프로그램에 동시성을 희생하지 않는 한 선호되지 않을 수 있음)

추신

자바 문서 참조 :

  1. 인코딩 (편의성) 메소드 : http://docs.oracle.com/javase/6/docs/api/java/nio/charset/charchetencoder.html#encode%28java.nio.charbuffer%29
  2. 일반 인코딩 방법 : http://docs.oracle.com/javase/6/docs/api/java/nio/charset/charsetencoder.html#encode%28java.nio.charbuffer,%20java.nio.bytebuffer,%20Boolean%29
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top