2013-12-11 75 views
0

我正在寫Spring Batch程序,它讀取每行上具有固定長度數據的文件並將值寫入數據庫。問題是這個文件的編碼是US-ASCII,但是它有scandinavic字母,最終爲##或其他奇怪的字符。 Scandinavic字符編碼爲0x5B =Ä,0x5C =Ö,0x5D =Å。否則它是大寫的US-ASCII文本。如何從使用java的US-ASCII文本中讀取斯堪的納維亞字符

閱讀此文件的最佳方法是什麼?我目前使用Spring批處理提供的FlatFileItemReader。

回答

2

我有一個類似的問題,其中文本應該被編碼爲ASCII,但有國際字符被使用。對我來說,解決方案是使用Windows-1252編碼讀取字節。

Javadoc我看到FlatFileItemReader有一個setEncoding方法。請嘗試以下操作:

reader.setEncoding("Windows-1252"); 

並查看它是否會給出更好的結果。

1

我猜字符集是ISO646-SE/-FI(7位),如http://www.aivosto.com/vbtips/charsets-7bit.html中所述。 Java似乎並不支持它。您可以實施自定義Charset。我不知道Spring,但是從JavaDoc看來,您可能需要在您的FlatFileItemReader上設置BufferedReaderFactory

下面的代碼可能是一個起點:

public static void main(String[] args) { 
    try { 
     InputStream is = new ByteArrayInputStream(new byte[]{ 0x5B, 0x5C, 0x5D }); 
     BufferedReader br = new BufferedReader(new InputStreamReader(is, new ISO646SECharset())); 
     // Spring: set custom BufferedReaderFactory returning BufferedReader like above line? 
     System.out.println(br.readLine()); 
     br.close(); 
    } catch (Exception ex) { 
     ex.printStackTrace(System.err); 
    } 
} 

/** ISO646-SE/-FI 7-bit character set. */ 
public static class ISO646SECharset extends Charset { 

    private static final char[] b2c = new char[0x80]; 
    private static final Map<Character, Byte> c2b = new HashMap<>(0x80); 
    static { 
     for (int i = 0; i < b2c.length; i++) { b2c[i] = (char) i; } 
     // see http://www.aivosto.com/vbtips/charsets-7bit.html 
     // see http://www.utf8-zeichentabelle.de/ 
     b2c[0x24] = '\u00A4'; 
     b2c[0x5B] = '\u00C4'; 
     b2c[0x5C] = '\u00D6'; 
     b2c[0x5D] = '\u00C5'; 
     b2c[0x7B] = '\u00E4'; 
     b2c[0x7C] = '\u00F6'; 
     b2c[0x7D] = '\u00E5'; 
     b2c[0x7E] = '\u00AF'; 
     for (int i = 0; i < b2c.length; i++) { c2b.put(b2c[i], (byte) i); } 
    } 

    protected ISO646SECharset() { 
     super("ISO646-SE", new String[]{ "ISO646-FI" }); 
    } 

    @Override 
    public boolean contains(Charset cs) { 
     return false; 
    } 

    @Override 
    public CharsetDecoder newDecoder() { 
     return new CharsetDecoder(ISO646SECharset.this, 1.0f, 1.0f) { 
      @Override 
      protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) { 
       while (true) { // TODO optimize, see US_ASCII class of OpenJDK 
        if (in.remaining() <= 0) return CoderResult.UNDERFLOW; 
        if (out.remaining() <= 0) return CoderResult.OVERFLOW; 
        byte b = in.get(); 
        if ((b & 0x80) != 0) b = (byte) '?'; 
        out.put(b2c[b & 0x7F]); 
       } 
      } 
     }; 
    } 

    @Override 
    public CharsetEncoder newEncoder() { 
     return new CharsetEncoder(ISO646SECharset.this, 1.0f, 1.0f) { 
      @Override 
      protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) { 
       while (true) { 
        if (in.remaining() <= 0) return CoderResult.UNDERFLOW; 
        if (out.remaining() <= 0) return CoderResult.OVERFLOW; 
        Byte b = c2b.get(in.get()); 
        out.put(b != null ? b : (byte) '?'); 
       } 
      } 
     }; 
    } 
} 

編輯:How to define a new Charset in Java/Android?,他們提到如何通過定義一個CharsetProvider應該允許setEncoding('ISO646-SE')使用註冊Charset

相關問題