Last active
December 29, 2015 04:28
-
-
Save gaeeyo/7614651 to your computer and use it in GitHub Desktop.
Android 4.4でSJISのエンコードで文字化けして困る件の対策。雑ですみません。 Android 4.4まではEUC-JPのエンコードとデコードでNEC拡張漢字などが化けていましたが、4.4では化けなくなっていました。 【注】Android 4.4未満ではデフォルトのencoderを使ったほうがいいです。パフォーマンスが悪いですしAndroid 4.4未満では①や㈱をEUCにエンコードするときに文字化けしてしまう(Android 4.4では文字化けしない)ためです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package jp.syoboi.utils.charset; | |
import java.nio.ByteBuffer; | |
import java.nio.CharBuffer; | |
import java.nio.charset.Charset; | |
import java.nio.charset.CharsetDecoder; | |
import java.nio.charset.CharsetEncoder; | |
import java.nio.charset.CoderResult; | |
import java.nio.charset.CodingErrorAction; | |
/** | |
* Android 4.4 で SJIS のエンコードがバグっていて文字化けする問題の対策用 | |
* エンコード時は EUC-JP => JIS => SJIS の変換を行う | |
*/ | |
public class Charset_SJIS extends Charset { | |
Charset mSJIS; | |
Charset mEUC; | |
public Charset_SJIS() { | |
super("SJIS", new String[] { "SJIS" }); | |
mSJIS = Charset.forName("SJIS"); | |
mEUC = Charset.forName("EUC-JP"); | |
} | |
@Override | |
public boolean contains(Charset charset) { | |
return false; | |
} | |
@Override | |
public CharsetDecoder newDecoder() { | |
return mSJIS.newDecoder(); | |
} | |
@Override | |
public CharsetEncoder newEncoder() { | |
return new Encoder(mEUC.newEncoder()); | |
} | |
public static class Encoder extends CharsetEncoder { | |
CharsetEncoder mEucEncoder; | |
ByteBuffer mTmp; | |
int mTmpPos; | |
protected Encoder(CharsetEncoder base) { | |
super(base.charset(), base.averageBytesPerChar(), base.maxBytesPerChar()); | |
mEucEncoder = base; | |
mEucEncoder.onUnmappableCharacter(CodingErrorAction.REPLACE); | |
mEucEncoder.onMalformedInput(CodingErrorAction.REPLACE); | |
mTmp = ByteBuffer.allocate(1024); | |
} | |
@Override | |
protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) { | |
CoderResult result = null; | |
if (mTmp.position() > 0) { | |
mTmp.flip(); | |
mTmp.rewind(); | |
result = eucToJis(mTmp, out); | |
mTmp.compact(); | |
if (result != CoderResult.OVERFLOW) { | |
return result; | |
} | |
} | |
result = mEucEncoder.encode(in, mTmp, false); | |
int pos = mTmp.position(); | |
mTmp.flip(); | |
mTmp.rewind(); | |
result = eucToJis(mTmp, out); | |
mTmp.position(pos); | |
mTmp.compact(); | |
return result; | |
} | |
CoderResult eucToJis(ByteBuffer in, ByteBuffer out) { | |
while (in.hasRemaining()) { | |
if (out.remaining() < 2) { | |
return CoderResult.OVERFLOW; | |
} | |
byte b = in.get(); | |
if ((byte) 0x00 <= b && b <= (byte) 0x7f) { | |
; // 何もしない | |
out.put(b); | |
} else if (b == (byte) 0x8e && in.hasRemaining()) { | |
// 半角カナ | |
out.put(in.get()); | |
} else if ((byte) 0xA1 <= b && b <= (byte) 0xFE | |
&& in.hasRemaining()) { | |
int c1 = (b & 0x7f); | |
int c2 = (in.get() & 0x7f); | |
if ((c1 & 1) == 1) { | |
c1 = ((c1 + 1) / 2) + 0x70; | |
c2 = c2 + 0x1f; | |
} else { | |
c1 = (c1 / 2) + 0x70; | |
c2 = c2 + 0x7d; | |
} | |
if (c1 >= 0xa0) { | |
c1 = c1 + 0x40; | |
} | |
if (c2 >= 0x7f) { | |
c2 = c2 + 1; | |
} | |
out.put((byte) (c1 & 0xff)); | |
out.put((byte) (c2 & 0xff)); | |
} else { | |
out.put(b); | |
} | |
} | |
return CoderResult.UNDERFLOW; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment