1 36 package org.columba.ristretto.coder; 37 38 import java.io.FilterInputStream ; 39 import java.io.IOException ; 40 import java.io.InputStream ; 41 import java.nio.ByteBuffer ; 42 import java.nio.CharBuffer ; 43 import java.nio.charset.CharacterCodingException ; 44 import java.nio.charset.Charset ; 45 import java.nio.charset.CharsetDecoder ; 46 import java.nio.charset.CharsetEncoder ; 47 import java.nio.charset.CoderResult ; 48 import java.nio.charset.CodingErrorAction ; 49 import java.util.Hashtable ; 50 51 56 public class FallbackCharsetDecoderInputStream extends FilterInputStream { 57 58 private Charset charset; 59 private CharsetDecoder decoder; 60 private ByteBuffer inBytes; 61 private CharBuffer outChars; 62 63 private static Hashtable fallbackTable = initFallBackTable(); 64 65 71 public FallbackCharsetDecoderInputStream(InputStream arg0, Charset charset) { 72 super(arg0); 73 this.charset = charset; 74 initDecoder(); 75 76 inBytes = ByteBuffer.allocate(5); 77 outChars = CharBuffer.allocate(1); 78 } 79 80 private static Hashtable initFallBackTable() { 81 Hashtable table = new Hashtable (); 82 83 table.put(Charset.forName("iso-8859-15"), Charset.forName("windows-1252")); 84 table.put(Charset.forName("iso-8859-1"), Charset.forName("windows-1252")); 85 table.put(Charset.forName("us-ascii"), Charset.forName("windows-1252")); 86 87 return table; 88 } 89 90 96 public static void addFallback(Charset original, Charset fallback) { 97 fallbackTable.put(original, fallback); 98 } 99 100 107 private int decodeNextChar() throws IOException { 108 CoderResult result; 109 int read; 110 111 112 inBytes.clear(); 113 inBytes.limit(1); 114 115 read = in.read(); 116 if( read == -1) return -1; 117 inBytes.put( 0, (byte) read ); 118 119 outChars.clear(); 120 result = decoder.decode(inBytes, outChars, in.available() == 0); 121 122 123 if( outChars.position() == 0 ) { 125 read = in.read(); 126 if( read == -1) return -1; 127 inBytes.limit(inBytes.limit()+1); 128 inBytes.put(inBytes.limit()-1,(byte) read); 129 130 outChars.clear(); 131 result = decoder.decode(inBytes, outChars, in.available() == 0); 132 } 133 134 ByteBuffer test = charset.encode(outChars); 135 while( test.capacity() == 0 && fallback()) { 136 inBytes.rewind(); 137 outChars.clear(); 138 result = decoder.decode(inBytes, outChars, in.available() == 0); 139 test = charset.encode(outChars); 140 } 141 142 return outChars.position(); 143 } 144 145 146 private boolean fallback() { 147 if( fallbackTable.containsKey(charset)) { 148 this.charset = (Charset )fallbackTable.get(charset); 149 initDecoder(); 150 151 return true; 152 } 153 154 return false; 155 } 156 157 private void initDecoder() { 158 decoder = charset.newDecoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE); 159 } 160 161 162 165 public int read() throws IOException { 166 if( decodeNextChar() == -1) return -1; 167 168 return outChars.get(0); 169 } 170 171 174 public int read(byte[] arg0, int arg1, int arg2) throws IOException { 175 int next; 176 for( int i=0; i<arg2; i++) { 177 next = read(); 178 if( next == -1 ) { 179 if( i == 0 ) { 180 return -1; 181 } else { 182 return i; 183 } 184 } 185 arg0[arg1+i] = (byte) next; 186 } 187 return arg2; 188 } 189 190 191 } 192 | Popular Tags |