我正在寫Spring Batch程序,它讀取每行上具有固定長度數據的文件並將值寫入數據庫。問題是這個文件的編碼是US-ASCII,但是它有scandinavic字母,最終爲##或其他奇怪的字符。 Scandinavic字符編碼爲0x5B =Ä,0x5C =Ö,0x5D =Å。否則它是大寫的US-ASCII文本。如何從使用java的US-ASCII文本中讀取斯堪的納維亞字符
閱讀此文件的最佳方法是什麼?我目前使用Spring批處理提供的FlatFileItemReader。
我正在寫Spring Batch程序,它讀取每行上具有固定長度數據的文件並將值寫入數據庫。問題是這個文件的編碼是US-ASCII,但是它有scandinavic字母,最終爲##或其他奇怪的字符。 Scandinavic字符編碼爲0x5B =Ä,0x5C =Ö,0x5D =Å。否則它是大寫的US-ASCII文本。如何從使用java的US-ASCII文本中讀取斯堪的納維亞字符
閱讀此文件的最佳方法是什麼?我目前使用Spring批處理提供的FlatFileItemReader。
我有一個類似的問題,其中文本應該被編碼爲ASCII,但有國際字符被使用。對我來說,解決方案是使用Windows-1252編碼讀取字節。
從Javadoc我看到FlatFileItemReader有一個setEncoding方法。請嘗試以下操作:
reader.setEncoding("Windows-1252");
並查看它是否會給出更好的結果。
我猜字符集是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
。