2012-12-18 2 views
1

UTF-16 파일로 인코딩 된 (일본어) 파일을 읽으려고합니다. 나는의 캐릭터와 함께하는 InputStreamReader를 사용하여 읽을 때Java Charset InputStreamReader, 파일 채널 차이점

'UTF-16 "파일을 제대로 읽어 : 나는 바이트 배열에서 파일 채널을 사용하고 읽을 때

try { 
     InputStreamReader read = new InputStreamReader(new FileInputStream("JapanTest.txt"), "UTF-16"); 
     BufferedReader in = new BufferedReader(read); 
     String str; 
     while((str=in.readLine())!=null){   
      System.out.println(str); 
    } 
    in.close(); 
}catch (Exception e){ 
    System.out.println(e); 
} 

그러나, 문자열은 때로 믿을 수' t 항상 올바르게 변환 :

File f = new File("JapanTest.txt"); 
    fis = new FileInputStream(f); 
    channel = fis.getChannel(); 
    MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0L, channel.size()); 
    buffer.position(0); 
    int get = Math.min(buffer.remaining(), 1024); 
    byte[] barray = new byte[1024]; 
    buffer.get(barray, 0, get); 
    CharSet charSet = Charset.forName("UTF-16"); 
    //endOfLinePos is a calculated value and defines the number of bytes to read 
    rowString = new String(barray, 0, endOfLinePos, charSet);    
    System.out.println(rowString); 

나는 MappedByteBuffer 위치 0에있는 경우 나는 MappedByteBuffer의 위치를 ​​증가하는 경우에만 문자를 올바르게 읽은 다음에 바이트 수를 읽을 수있는 내가 찾은 문제는 바이트 배열. charset UTF-16을 사용하면 바이트가 올바르게 변환되지 않습니다. 파일이 UTF-8로 인코딩 된 경우이 문제가 발생하지 않았으므로이 문제는 UTF-16에서만 발생합니다.

자세한 내용 : 파일 채널의 모든 행을 읽을 수 있어야하므로이 행 끝 바이트 위치 목록을 작성한 다음 해당 위치를 사용하여 지정된 바이트 수를 얻을 수 있습니다 줄로 변환 한 다음 문자열로 변환하십시오.

+1

아마도 'endOfLinePos'가 잘못 계산됩니다. 홀수 인 경우 UTF-16에서 짝수 바이트가 필요하기 때문에 문제가됩니다. – irreputable

+0

1024 자 그룹이 "가운데"에서 UTF-16 문자를 분할하고있는 것으로 의심됩니다. –

답변

1

UTF-16의 코드 단위는 UTF-8과 같은 바이트가 아닌 2 바이트입니다. 패턴 및 단일 바이트 코드 단위 길이는 UTF-8을 자체 동기화합니다. 어느 지점에서나 올바르게 읽을 수 있으며 연속 바이트 인 경우 하나의 문자 만 되돌리거나 잃을 수 있습니다.

UTF-16을 사용하면 항상 바이트 쌍으로 작업해야합니다. 홀수 바이트에서 읽기를 시작하거나 홀수 바이트에서 읽기를 시작할 수 없습니다. 은 BOM이 없기 때문에은 endianess를 알고 있어야하며 파일 시작 부분에서 읽을 때 UTF-16LE 또는 UTF-16BE를 사용해야합니다.

파일을 UTF-8로 인코딩 할 수도 있습니다.

1

아마도 은 일부 변환을 수행하지만 보통 new String(...)은 변환하지 않습니다. 해결 방법으로 (그리고이 가정을 확인하기 위해) new InputStreamReader(new ByteArrayInputStream(barray))과 같이 채널에서 읽은 데이터를 래핑하려고 할 수 있습니다.

편집 : 잊어 버려요 :) - Channels.newReader() 가야 할 길입니다.

+0

파일 채널에서 어떤 라인을 읽을 수 있어야합니다. 이렇게하려면 라인 끝 바이트 위치리스트를 만든 다음 그 위치를 사용하여 주어진 라인의 바이트를 가져 와서 끈. – joechip

+0

라인 단위 처리를 위해 ['LineNumberReader'] (http://download.java.net/jdk7/archive/b123/docs/api/java/io/LineNumberReader.html)가 사용됩니다. – JimmyB

+0

참 -하지만 파일이 커질 수 있으므로 많은 메모리를 절약 할 수 있으므로 파일 채널을 사용하고 싶습니다. – joechip