4 * License : The MIT License
5 * Copyright(c) 2011 MikuToga Partners
8 package jp.sourceforge.mikutoga.binio;
10 import java.io.ByteArrayOutputStream;
11 import java.io.IOException;
12 import java.io.OutputStream;
13 import java.nio.ByteBuffer;
14 import java.nio.CharBuffer;
15 import java.nio.charset.CharacterCodingException;
16 import java.nio.charset.Charset;
17 import java.nio.charset.CharsetEncoder;
18 import java.nio.charset.CoderResult;
19 import java.nio.charset.CodingErrorAction;
22 * 任意のエンコーダによるテキストデータのバイナリ出力を行う。
24 public class TextExporter {
26 /** デフォルトの入力バッファサイズ(単位:char)。 */
27 public static final int DEFBUFSZ_CHAR = 128;
28 /** デフォルトの出力バッファサイズ(単位:byte)。 */
29 public static final int DEFBUFSZ_BYTE = 128;
32 private final CharsetEncoder encoder;
33 private CharBuffer cbuf = CharBuffer.allocate(DEFBUFSZ_CHAR);
34 private byte[] barray = new byte[DEFBUFSZ_BYTE];
35 private ByteBuffer bbuf = ByteBuffer.wrap(barray);
37 private CharSequence textData;
38 private int textLength;
44 * @param encoder エンコーダ
45 * @throws NullPointerException 引数がnull
47 public TextExporter(CharsetEncoder encoder) throws NullPointerException{
50 if(encoder == null) throw new NullPointerException();
51 this.encoder = encoder;
52 this.encoder.onMalformedInput(CodingErrorAction.REPORT);
53 this.encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
62 public TextExporter(Charset cs){
63 this(cs.newEncoder());
71 public CharsetEncoder getEncoder(){
77 * @param newSize バッファサイズ。(単位:char)
78 * @throws IllegalArgumentException サイズ指定が正で無かった。
80 public void setCharBufSize(int newSize)
81 throws IllegalArgumentException {
82 if(newSize <= 0) throw new IllegalArgumentException();
83 this.cbuf = CharBuffer.allocate(newSize);
90 * @param newSize バッファサイズ。(単位:byte)
91 * @throws IllegalArgumentException サイズ指定が正で無かった。
93 public void setByteBufSize(int newSize)
94 throws IllegalArgumentException {
95 if(newSize <= 0) throw new IllegalArgumentException();
96 this.barray = new byte[newSize];
97 this.bbuf = ByteBuffer.wrap(barray);
103 * 与えられた文字列をエンコードしてストリームに出力する。
107 * @throws IOException 出力エラー
108 * @throws CharacterCodingException エンコードエラー
110 public int dumpText(OutputStream os, CharSequence text)
111 throws IOException, CharacterCodingException {
112 this.textData = text;
116 total = dumpTextImpl(os);
118 this.textData = null;
125 * 文字列をエンコードしてストリームに出力する。
128 * @throws IOException 出力エラー
129 * @throws CharacterCodingException エンコードエラー
131 private int dumpTextImpl(OutputStream os)
132 throws IOException, CharacterCodingException {
139 CoderResult result = encode();
140 if(result.isUnderflow()){
145 total += sweepByteBuffer(os);
147 }else if(result.isOverflow()){
148 total += sweepByteBuffer(os);
151 }else if(result.isError()){
152 result.throwException();
164 private void reset(){
168 this.encoder.reset();
170 this.textLength = this.textData.length();
177 * 入力バッファにまだ入力していない文字があるか判定する。
178 * @return 入力バッファにまだ入力していない文字があればtrue
180 private boolean hasMoreInput(){
181 if(this.inPos < this.textLength) return true;
187 * <p>入力バッファが一杯になるか入力文字列がなくなるまでバッファが埋められる。
189 private void loadCharBuffer(){
190 while(this.cbuf.hasRemaining() && hasMoreInput()){
191 char ch = this.textData.charAt(this.inPos++);
202 private CoderResult encode(){
204 if(hasMoreInput()) endOfInput = false;
205 else endOfInput = true;
208 result = this.encoder.encode(this.cbuf, this.bbuf, endOfInput);
216 * @throws IOException 出力エラー
218 private int sweepByteBuffer(OutputStream os) throws IOException{
221 int total = this.bbuf.remaining();
222 os.write(this.barray, 0, total);
233 * @throws IOException 出力エラー
234 * @throws CharacterCodingException エンコーディングエラー
236 private int flush(OutputStream os)
237 throws IOException, CharacterCodingException {
241 CoderResult result = this.encoder.flush(this.bbuf);
242 if(result.isError()) result.throwException();
244 total += sweepByteBuffer(os);
246 if(result.isUnderflow()) break;
253 * 与えられた文字列のエンコード結果を格納先バイトストリームへ格納する。
254 * <p>エンコード結果は格納先ストリームに追記される。
256 * @param bos 格納先ストリーム
257 * @return エンコードしたバイト数。
258 * @throws CharacterCodingException エンコードエラー
260 @SuppressWarnings("PMD.AvoidRethrowingException")
261 public int encodeToByteStream(CharSequence text,
262 ByteArrayOutputStream bos )
263 throws CharacterCodingException {
266 result = dumpText(bos, text);
267 }catch(CharacterCodingException e){
269 }catch(IOException e){
272 throw new AssertionError(e);