2016-10-02 3 views
2

현재 사용자가 16 진수 편집기 인터페이스를 통해 ByteBuffer를 편집 할 수 있고 JTextPane을 통해 해당 텍스트를 편집 할 수있는 응용 프로그램을 개발 중입니다. 현재 문제는 JTextPane에 String이 필요하기 때문입니다. 값을 표시하기 전에 ByteBuffer를 String으로 변환해야합니다. 그러나 변환 중에는 유효하지 않은 문자가 charsets 기본 대체 문자로 대체됩니다. 이 잘못된 값을 스쿼시하므로 바이트 버퍼로 다시 변환 할 때 잘못된 문자 값이 기본 대체 문자의 바이트 값으로 대체됩니다. 문자열에 유효하지 않은 문자의 바이트 값을 유지하는 쉬운 방법이 있습니까? 나는 다음과 같은 stackoverflow 게시물을 읽었지만 사람들은 보통 인쇄 할 수없는 문자를 바꾸고 싶다. 나는 그들을 보존해야한다.Java에서 ByteBuffer와 String 간의 변환 문제

Java ByteBuffer to String

Java: Converting String to and from ByteBuffer and associated problems

이 작업을 수행하거나 내가 텍스트 편집기에서 일어날과의 ByteBuffer에 적용 할 모든 변경 사항을 추적 할 필요가 할 수있는 쉬운 방법이 있나요 ?

다음은 문제를 나타내는 코드입니다. 코드는 ByteBuffer 대신 byte []를 사용하지만 문제는 동일합니다.

 byte[] temp = new byte[16]; 
     // 0x99 isn't a valid UTF-8 Character 
     Arrays.fill(temp,(byte)0x99); 

     System.out.println(Arrays.toString(temp)); 
     // Prints [-103, -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, -103] 
     // -103 == 0x99 

     System.out.println(new String(temp)); 
     // Prints ���������������� 
     // � is the default char replacement string 

     // This takes the byte[], converts it to a string, converts it back to a byte[] 
     System.out.println(Arrays.toString(new String(temp).getBytes())); 
     // I need this to print [-103, -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, -103] 
     // However, it prints 
     //[-17, -65, -67, -17, -65, -67, -17, -65, -67, -17, -65, -67, -17, -65, -67, -17, -65, -67, -17, -65, -67, -17, -65, -67, -17, -65, -67, -17, -65, -67, -17, -65, -67, -17, -65, -67, -17, -65, -67, -17, -65, -67, -17, -65, -67, -17, -65, -67] 
     // The printed byte is the byte representation of � 
+0

이 코드가 필요하다고 생각합니다. 버그 같은데. 또한 개념적 오류 일 수 있습니다 : 바이트로 변환하는 데 문제가있는 정확한 텍스트 시퀀스는 무엇입니까? – markspace

+0

문제를 나타내는 코드를 포함하도록 질문을 업데이트했습니다. 이것은 내 코드의 버그가 아니며 기본적으로이 방법으로 작동해야합니다. –

답변

0

는 특히 UTF-8 잘못

byte[] bytes = {'a', (byte) 0xfd, 'b', (byte) 0xe5, 'c'}; 
    String s = new String(bytes, StandardCharsets.UTF_8); 
    System.out.println("s: " + s); 

하나는 CharsetDecoder을 필요로 이동합니다. 거기에서 문제의 바이트를 무시 (= 삭제)하거나 옮겨 놓을 수 있습니다. 디폴트로는 예외를 발생시킵니다.

JTextPane의 경우 HTML을 사용하므로 <span>에 문제가되는 바이트의 16 진수 코드를 적색 배경으로 쓸 수 있습니다.

이 코드는 매우 훌륭한 API를 반영하지는 않지만 그 코드와 함께 사용하십시오.

+0

그건 내가 생각조차하지 못했던 정말 좋은 생각입니다. 필자가 볼 수있는 유일한 문제는 String에서 byte []로 다시 변환 할 때 JTextPane의 텍스트에있는 추가 마크 업이 될 것입니다. 그 문제를 해결하는 방법에 대한 아이디어가 있습니까? –

+0

'ReplaceAll ("<[^> * *", "")'또는 더 나은 패턴 매처를 가진 루프. –

+0

JTextPane가도 스타일 텍스트 (인 StyledDocument) 및 사용을 사용하는 텍스트의 별도의 속성 수,하지만 그건 당신이 편집을 허용 할 경우 특히 복잡합니다. 그러나'byteBuffer.position()'을 사용하여 그 바이트들을 표시 할 수있다. –

0

new String(temp).getBytes()은 어떤 점을 생각합니까?

나는 그것이 나쁜 것이라고 말 할 수 있습니다.

  1. 그것은 아마 잘못 기본 인코딩을 사용하여 Stringtemp을 변환하고, 정보가 유실 될 수 있습니다.
  2. 기본 인코딩을 사용하여 결과를 다시 바이트 배열로 변환합니다.

은 항상 String 생성자에 Charset를 통과해야하는 Stringbyte[]을 설정, 또는 다른 직접 디코더를 사용하십시오. 버퍼로 작업하기 때문에, 디코더 API가 적절한 지 알 수 있습니다.

Stringbyte[]으로 바꾸려면 올바른 문자 세트를 사용하고 있음을 알 수 있도록 항상 getBytes(Charset)으로 전화해야합니다.

의견을 바탕으로, 여기에 귀하의 UI가 바이트에서 16 진수로 변환하기 위해 다음과 같은 코드를 작성할 필요가 있다고 생각합니다. (다음 일이 돌아 오기에 해당.)

String getHexString(byte[] bytes) { 
    StringBuilder builder = new StringBuilder(); 
    for (byte b : bytes) { 
     int nibble = b >> 4; 
     builder.append('0' + nibble); 
     nibble = b & 0xff; 
     builder.append('0' + nibble); 
    } 
    return builder.toString(); 
} 
+0

모범 사례에서는 getBytes와 String 생성자 모두 Charset을 사용해야한다고 주장합니다. Charset을 String 생성자에 전달하면 여전히 문제가 발생합니다. 'byte []'에 맵 불가 문자가 포함되어 있기 때문에 새로운 String (temp, "UTF-8")'은 UnsupportedEncodingException 예외를 던집니다. 그 대답은 CharsetDecoder API를 사용해야 할 것이라고 생각하지만 비슷한 것을 사용하는 예제는 보지 못했습니다. –

+0

비 UTF-8이 포함 된 경우 모든 정보를 유지하려면 문자열로 변환 할 수 없습니다. 각각의'byte '를 2 자리의 16 진수로 변환해야합니다. 사용중인 API를 사용하여이를 수행 할 수있는 방법이 없습니다. – bmargulies

+0

우리가 개념적 오류/버그를 발견 한 지금 JustinA.Moore 그래서, @ 무엇 * 정확히 맵 불가 문자로 싶지 않습니다. 당신이 그건 그들을 위해 어떤 계획을 가지고해야 * 그들은이며, 정의에 의해, 맵 불가, 그래서 'Charset'의 perview 외부. – markspace