자바 : 문자열과 ByteBuffer 간 변환 및 관련 문제
소켓 연결에 Java NIO를 사용하고 있으며 프로토콜은 텍스트 기반이므로 SocketChannel에 쓰기 전에 문자열을 ByteBuffer로 변환하고 들어오는 ByteBuffer를 다시 문자열로 변환 할 수 있어야합니다. 현재 다음 코드를 사용하고 있습니다.
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()
던져 것입니다 java.lang.IllegalStateException: Current state = FLUSHED, new state = CODING_END
나는 새의 ByteBuffer 객체에게 변환이 수행 될 때마다 사용하고 경우에도 예외 또는 유사한. 이러한 방법을 동기화해야합니까? 문자열과 ByteBuffer 사이를 변환하는 더 좋은 방법이 있습니까? 감사!
CharsetEncoder
및 CharsetDecoder
API 설명을 확인하십시오 .이 문제를 방지 하려면 특정 메서드 호출 순서를 따라야합니다 . 예를 들면 다음과 CharsetEncoder
같습니다.
reset
이전에 사용하지 않은 경우 방법을 통해 인코더를 재설정하십시오 .encode
추가 입력을 사용할 수있는 한 메서드를 0 번 이상 호출하고false
endOfInput 인수를 전달 하고 입력 버퍼를 채우고 호출 사이에 출력 버퍼를 비 웁니다.encode
마지막으로 메서드를 호출하고true
endOfInput 인수를 전달합니다. 그리고flush
인코더가 내부 상태를 출력 버퍼로 플러시 할 수 있도록 메서드를 호출합니다 .
그건 그렇고, 내 동료 중 일부는 ASCII 만 사용한다는 지식에서 각 문자를 바이트로 직접 변환하지만 NIO에 사용하는 것과 동일한 접근 방식입니다.
상황이 바뀌지 않는 한
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 ()는 사용 사례에 따라 항상 true 또는 false입니다. 실제로 어떤 상황에서도 실제로 작동하기를 원하지 않는 한 필요하지 않은 브랜치를 최적화하는 것이 안전합니다.
Adamski의 답변은 좋은 답변이며 일반 인코딩 방법을 사용할 때 인코딩 작업의 단계를 설명합니다 (입력 중 하나로 바이트 버퍼 사용).
However, the method in question (in this discussion) is a variant of encode - encode(CharBuffer in). This is a convenience method that implements the entire encoding operation. (Please see java docs reference in P.S.)
As per the docs, This method should therefore not be invoked if an encoding operation is already in progress (which is what is happening in ZenBlender's code -- using static encoder/decoder in a multi threaded environment).
Personally, I like to use convenience methods (over the more general encode/decode methods) as they take away the burden by performing all the steps under the covers.
ZenBlender and Adamski have already suggested multiple ways options to safely do this in their comments. Listing them all here:
- Create a new encoder/decoder object when needed for each operation (not efficient as it could lead to a large number of objects). OR,
- Use a ThreadLocal to avoid creating new encoder/decoder for each operation. OR,
- Synchronize the entire encoding/decoding operation (this might not be preferred unless sacrificing some concurrency is ok for your program)
P.S.
java docs references:
- Encode (convenience) method: http://docs.oracle.com/javase/6/docs/api/java/nio/charset/CharsetEncoder.html#encode%28java.nio.CharBuffer%29
- General encode method: http://docs.oracle.com/javase/6/docs/api/java/nio/charset/CharsetEncoder.html#encode%28java.nio.CharBuffer,%20java.nio.ByteBuffer,%20boolean%29
'Program Tip' 카테고리의 다른 글
Qt LGPL 라이선스를 사용하고 어떤 제한없이 내 애플리케이션을 판매 할 수 있습니까? (0) | 2020.10.10 |
---|---|
노드 작업 대기열에서 콜백 목록을 얻으려면 어떻게해야합니까? (0) | 2020.10.10 |
Entity Framework의 POCO는 무엇입니까? (0) | 2020.10.10 |
varchar (max) 어디에서나? (0) | 2020.10.10 |
빈 jQuery 선택 결과 테스트 (0) | 2020.10.10 |