OSDN Git Service

<rawdata>出力変更
authorOlyutorskii <olyutorskii@users.osdn.me>
Wed, 29 Jun 2016 10:02:35 +0000 (19:02 +0900)
committerOlyutorskii <olyutorskii@users.osdn.me>
Wed, 29 Jun 2016 10:02:35 +0000 (19:02 +0900)
src/main/java/jp/sourceforge/jindolf/archiver/DumpXmlTask.java
src/main/java/jp/sourceforge/jindolf/archiver/JinArchiver.java
src/main/java/jp/sourceforge/jindolf/archiver/XmlOut.java
src/test/java/jp/sourceforge/jindolf/archiver/XmlOutTest.java

index a5c59d6..3859be0 100644 (file)
@@ -8,7 +8,6 @@
 package jp.sourceforge.jindolf.archiver;
 
 import java.io.IOException;
-import java.io.Writer;
 import java.util.concurrent.Callable;
 
 /**
@@ -29,10 +28,10 @@ public class DumpXmlTask implements Callable<Void> {
      * @param villageData 村情報
      * @param writer 出力先
      */
-    public DumpXmlTask(VillageData villageData, Writer writer){
+    public DumpXmlTask(VillageData villageData, XmlOut writer){
         super();
         this.villageData = villageData;
-        this.writer = new XmlOut(writer);
+        this.writer = writer;
         return;
     }
 
index 09442dc..ddeaced 100644 (file)
@@ -18,6 +18,7 @@ import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.Reader;
 import java.io.Writer;
+import java.nio.charset.Charset;
 import java.text.MessageFormat;
 import java.util.List;
 import java.util.Properties;
@@ -158,24 +159,10 @@ public final class JinArchiver{
      * @param optInfo オプション情報
      */
     private static void dumpOut(OptInfo optInfo){
-
         String outdir   = optInfo.getOutdir();
         LandDef landDef = optInfo.getLandDef();
         int vid         = optInfo.getVid();
 
-        Writer writer;
-        if(outdir != null){
-            writer = getFileWriter(outdir, landDef, vid);
-        }else{
-            writer = getStdOutWriter();
-        }
-
-        SnifWriter snifWriter = new SnifWriter(writer);
-        Reader reader = snifWriter.getSnifReader();
-
-        writer = new BufferedWriter(snifWriter);
-        reader = new BufferedReader(reader);
-
         Validator validator;
         try{
             validator = XmlUtils.createValidator();
@@ -184,6 +171,13 @@ public final class JinArchiver{
             return;
         }
 
+        Writer writer;
+        if(outdir != null){
+            writer = getFileWriter(outdir, landDef, vid);
+        }else{
+            writer = getStdOutWriter();
+        }
+
         VillageData villageData;
         try{
             villageData = load(landDef, vid);
@@ -198,8 +192,18 @@ public final class JinArchiver{
             return;
         }
 
+        SnifWriter snifWriter = new SnifWriter(writer);
+        Reader reader = snifWriter.getSnifReader();
+
+        writer = new BufferedWriter(snifWriter);
+        reader = new BufferedReader(reader);
+
+        XmlOut xmlOut = new XmlOut(writer);
+        Charset cs = landDef.getEncoding();
+        xmlOut.setSourceCharset(cs);
+
         ValidateTask valTask = new ValidateTask(reader, validator);
-        DumpXmlTask dumpTask = new DumpXmlTask(villageData, writer);
+        DumpXmlTask dumpTask = new DumpXmlTask(villageData, xmlOut);
 
         ProdCons taskman = new ProdCons(dumpTask, valTask);
         try{
index dee7607..04d1e91 100644 (file)
@@ -11,6 +11,7 @@ import java.io.Closeable;
 import java.io.Flushable;
 import java.io.IOException;
 import java.io.Writer;
+import java.nio.charset.Charset;
 import java.text.MessageFormat;
 import java.util.Calendar;
 import java.util.GregorianCalendar;
@@ -54,9 +55,19 @@ public class XmlOut implements Appendable, Flushable, Closeable{
     private static final TimeZone TZ_TOKYO =
             TimeZone.getTimeZone("Asia/Tokyo");
 
+    private static final Charset CS_DEF = Charset.forName("Shift_JIS");
+
+    private static final char[] HEX_TABLE = {
+        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+        'a', 'b', 'c', 'd', 'e', 'f',
+    };
+
 
     private final Writer writer;
 
+    private String charsetName;
+    private boolean isShiftJis;
+
 
     /**
      * コンストラクタ。
@@ -64,7 +75,11 @@ public class XmlOut implements Appendable, Flushable, Closeable{
      */
     XmlOut(Writer writer){
         super();
+
         this.writer = writer;
+
+        setSourceCharsetImpl(CS_DEF);
+
         return;
     }
 
@@ -93,6 +108,8 @@ public class XmlOut implements Appendable, Flushable, Closeable{
      *
      * <p>サロゲートペアのシーケンスまでは調べない。
      *
+     * <p>XML規格2.2 Char 定義を参照せよ。
+     *
      * @param chVal 文字
      * @return 出現可能ならtrue
      */
@@ -112,7 +129,7 @@ public class XmlOut implements Appendable, Flushable, Closeable{
      *
      * <p>ControlPicturesが利用できない場合はU+FFFDを用いる。
      *
-     * <p>UnicodeのControl Picturesブロックを参照せよ。
+     * <p>Unicode規格のControl Picturesブロックを参照せよ。
      *
      * @param chVal 対象文字
      * @return 代替キャラクタ
@@ -131,6 +148,99 @@ public class XmlOut implements Appendable, Flushable, Closeable{
         return result;
     }
 
+    /**
+     * byte値を2桁の16進文字列表記に変換する。
+     * @param bVal byte値
+     * @return 16進文字列
+     */
+    public static String toHex(byte bVal){
+        int hexVal = bVal & 0xff;
+
+        char ch1 = HEX_TABLE[hexVal & 0x0f];
+        hexVal >>= 4;
+        char ch0 = HEX_TABLE[hexVal & 0x0f];
+
+        StringBuilder txt = new StringBuilder();
+        txt.append(ch0);
+        txt.append(ch1);
+
+        return txt.toString();
+    }
+
+    /**
+     * char値を2桁または4桁の16進文字列表記に変換する。
+     *
+     * <p>U+00FFより大きな値は4桁出力となる。
+     *
+     * @param cVal char値
+     * @return 16進文字列
+     */
+    public static String toHex(char cVal){
+        int hexVal = cVal & 0xffff;
+
+        char ch3 = HEX_TABLE[hexVal & 0x0f];
+        hexVal >>= 4;
+        char ch2 = HEX_TABLE[hexVal & 0x0f];
+        hexVal >>= 4;
+        char ch1 = HEX_TABLE[hexVal & 0x0f];
+        hexVal >>= 4;
+        char ch0 = HEX_TABLE[hexVal & 0x0f];
+
+        StringBuilder txt = new StringBuilder();
+        if(cVal > '\u00ff'){
+            txt.append(ch0);
+            txt.append(ch1);
+        }
+        txt.append(ch2);
+        txt.append(ch3);
+
+        return txt.toString();
+    }
+
+    /**
+     * short値を4桁の16進文字列表記に変換する。
+     * @param sVal short値
+     * @return 16進文字列
+     */
+    public static String toHex(short sVal){
+        int hexVal = sVal & 0xffff;
+
+        char ch3 = HEX_TABLE[hexVal & 0x0f];
+        hexVal >>= 4;
+        char ch2 = HEX_TABLE[hexVal & 0x0f];
+        hexVal >>= 4;
+        char ch1 = HEX_TABLE[hexVal & 0x0f];
+        hexVal >>= 4;
+        char ch0 = HEX_TABLE[hexVal & 0x0f];
+
+        StringBuilder txt = new StringBuilder();
+        txt.append(ch0);
+        txt.append(ch1);
+        txt.append(ch2);
+        txt.append(ch3);
+
+        return txt.toString();
+    }
+
+
+    /**
+     * パース元の文字コードを設定する。
+     * @param cs Charset
+     */
+    public void setSourceCharset(Charset cs){
+        setSourceCharsetImpl(cs);
+        return;
+    }
+
+    /**
+     * パース元の文字コードを設定する。
+     * @param cs Charset
+     */
+    private void setSourceCharsetImpl(Charset cs){
+        this.charsetName = cs.name();
+        this.isShiftJis = "Shift_JIS".equals(this.charsetName);
+        return;
+    }
 
     /**
      * {@inheritDoc}
@@ -229,9 +339,7 @@ public class XmlOut implements Appendable, Flushable, Closeable{
      */
     public void charRefOut(char chVal)
             throws IOException{
-        int ival = 0xffff & ((int) chVal);
-        String hex = Integer.toHexString(ival);
-        if(hex.length() % 2 != 0) hex = "0" + hex;
+        String hex = toHex(chVal);
 
         append("&#x");
         append(hex);
@@ -436,25 +544,57 @@ public class XmlOut implements Appendable, Flushable, Closeable{
      */
     public void dumpErrorInfo(DecodeErrorInfo errorInfo)
             throws IOException{
-        int hexVal;
-        hexVal = errorInfo.getRawByte1st() & 0xff;
-        if(errorInfo.has2nd()){
-            hexVal <<= 8;
-            hexVal |= errorInfo.getRawByte2nd() & 0xff;
+        if(this.isShiftJis && errorInfo.has2nd()){
+            byte bVal1 = errorInfo.getRawByte1st();
+            byte bVal2 = errorInfo.getRawByte2nd();
+            dumpSjisMapError(bVal1, bVal2);
+        }else{
+            byte bVal1 = errorInfo.getRawByte1st();
+            dumpDecodeError(bVal1);
+            if(errorInfo.has2nd()){
+                byte bVal2 = errorInfo.getRawByte2nd();
+                dumpDecodeError(bVal2);
+            }
         }
 
-        String hexBin = Integer.toHexString(hexVal);
-        if(hexBin.length() % 2 != 0) hexBin = "0" + hexBin;
 
-        char replaceChar = Win31j.getWin31jChar(errorInfo);
+        return;
+    }
+
+    /**
+     * シフトJISマッピングに関するエラー情報をrawdataタグで出力する。
+     * @param bVal1  エラーデータ1
+     * @param bVal2  エラーデータ2
+     * @throws IOException 出力エラー
+     */
+    public void dumpSjisMapError(byte bVal1, byte bVal2) throws IOException{
+        short hexVal;
+        hexVal = (short) (bVal1 & 0xff);
+        hexVal <<= 8;
+        hexVal |= (short) (bVal2 & 0xff);
+
+        String hexBin = toHex(hexVal);
 
+        char replaceChar = Win31j.getWin31jChar(bVal1, bVal2);
         rawDataOut(hexBin, replaceChar);
 
         return;
     }
 
     /**
-     * 生データ出力
+     * デコードエラー情報をrawdataタグで出力する。
+     * @param bVal エラーデータ
+     * @throws IOException 出力エラー
+     */
+    public void dumpDecodeError(byte bVal) throws IOException{
+        String hexBin = toHex(bVal);
+        char replaceChar = replaceChar((char) (bVal & 0xff));
+        rawDataOut(hexBin, replaceChar);
+        return;
+    }
+
+    /**
+     * 生データ出力。
      * @param hex 16進文字列
      * @param replace 代替キャラクタ
      * @throws IOException 出力エラー
@@ -462,8 +602,9 @@ public class XmlOut implements Appendable, Flushable, Closeable{
     private void rawDataOut(String hex, char replace) throws IOException{
         append("<rawdata");
 
+        String encName = this.charsetName;
         sp();
-        attrOut("encoding", "Shift_JIS");
+        attrOut("encoding", encName);
 
         sp();
         attrOut("hexBin", hex);
@@ -554,15 +695,9 @@ public class XmlOut implements Appendable, Flushable, Closeable{
      */
     public void dumpRawData(char chVal)
             throws IOException{
-        int hexVal;
-        hexVal = chVal & 0xff;
-        String hexBin = Integer.toHexString(hexVal);
-        if(hexBin.length() % 2 != 0) hexBin = "0" + hexBin;
-
+        String hexBin = toHex(chVal);
         char replaceChar = replaceChar(chVal);
-
         rawDataOut(hexBin, replaceChar);
-
         return;
     }
 
index b2786d8..d84322a 100644 (file)
@@ -277,7 +277,7 @@ public class XmlOutTest {
         xmlOut = new XmlOut(writer);
         xmlOut.dumpRawData('\u0100');
         xmlOut.close();
-        assertEquals("<rawdata encoding=\"Shift_JIS\" hexBin=\"00\" >\ufffd</rawdata>", writer.toString());
+        assertEquals("<rawdata encoding=\"Shift_JIS\" hexBin=\"0100\" >\ufffd</rawdata>", writer.toString());
 
         return;
     }
@@ -515,11 +515,11 @@ public class XmlOutTest {
     }
 
     /**
-     * Test of dumpErrorInfo method, of class XmlUtils.
+     * Test of dumpSjisMapError method, of class XmlUtils.
      * @throws java.lang.Exception
      */
     @Test
-    public void testDumpErrorInfo() throws Exception {
+    public void testDumpDecodeError() throws Exception {
         System.out.println("dumpErrorInfo");
 
         Writer writer;
@@ -531,21 +531,21 @@ public class XmlOutTest {
         errorInfo = new DecodeErrorInfo(0, (byte) 0x00);
         xmlOut.dumpErrorInfo(errorInfo);
         xmlOut.close();
-        assertEquals("<rawdata encoding=\"Shift_JIS\" hexBin=\"00\" >\ufffd</rawdata>", writer.toString());
+        assertEquals("<rawdata encoding=\"Shift_JIS\" hexBin=\"00\" >\u2400</rawdata>", writer.toString());
 
         writer = new StringWriter();
         xmlOut = new XmlOut(writer);
         errorInfo = new DecodeErrorInfo(0, (byte) 0x0f);
         xmlOut.dumpErrorInfo(errorInfo);
         xmlOut.close();
-        assertEquals("<rawdata encoding=\"Shift_JIS\" hexBin=\"0f\" >\ufffd</rawdata>", writer.toString());
+        assertEquals("<rawdata encoding=\"Shift_JIS\" hexBin=\"0f\" >\u240f</rawdata>", writer.toString());
 
         writer = new StringWriter();
         xmlOut = new XmlOut(writer);
         errorInfo = new DecodeErrorInfo(0, (byte) 0x10);
         xmlOut.dumpErrorInfo(errorInfo);
         xmlOut.close();
-        assertEquals("<rawdata encoding=\"Shift_JIS\" hexBin=\"10\" >\ufffd</rawdata>", writer.toString());
+        assertEquals("<rawdata encoding=\"Shift_JIS\" hexBin=\"10\" >\u2410</rawdata>", writer.toString());
 
         writer = new StringWriter();
         xmlOut = new XmlOut(writer);
@@ -591,7 +591,7 @@ public class XmlOutTest {
         content.append("CD");
         xmlOut.dumpDecodedContent(content);
         xmlOut.close();
-        assertEquals("AB<rawdata encoding=\"Shift_JIS\" hexBin=\"08\" >\ufffd</rawdata>CD", writer.toString());
+        assertEquals("AB<rawdata encoding=\"Shift_JIS\" hexBin=\"08\" >\u2408</rawdata>CD", writer.toString());
 
         writer = new StringWriter();
         xmlOut = new XmlOut(writer);
@@ -600,7 +600,7 @@ public class XmlOutTest {
         content.addDecodeError((byte)0x08);
         xmlOut.dumpDecodedContent(content);
         xmlOut.close();
-        assertEquals("AB<rawdata encoding=\"Shift_JIS\" hexBin=\"08\" >\ufffd</rawdata>", writer.toString());
+        assertEquals("AB<rawdata encoding=\"Shift_JIS\" hexBin=\"08\" >\u2408</rawdata>", writer.toString());
 
         writer = new StringWriter();
         xmlOut = new XmlOut(writer);
@@ -609,7 +609,171 @@ public class XmlOutTest {
         content.append("CD");
         xmlOut.dumpDecodedContent(content);
         xmlOut.close();
-        assertEquals("<rawdata encoding=\"Shift_JIS\" hexBin=\"08\" >\ufffd</rawdata>CD", writer.toString());
+        assertEquals("<rawdata encoding=\"Shift_JIS\" hexBin=\"08\" >\u2408</rawdata>CD", writer.toString());
+
+        return;
+    }
+
+    /**
+     * Test of isXmlChar method, of class XmlOut.
+     */
+    @Test
+    public void testIsXmlChar() {
+        System.out.println("isXmlChar");
+
+        assertFalse(XmlOut.isXmlChar('\u0000'));
+        assertFalse(XmlOut.isXmlChar('\u001f'));
+
+        assertTrue(XmlOut.isXmlChar('\n'));
+        assertTrue(XmlOut.isXmlChar('\r'));
+        assertTrue(XmlOut.isXmlChar('\t'));
+
+        assertTrue(XmlOut.isXmlChar('\u0020'));
+        assertTrue(XmlOut.isXmlChar('A'));
+        assertTrue(XmlOut.isXmlChar('\ud7ff'));
+
+        assertTrue(XmlOut.isXmlChar('\ud800'));
+        assertTrue(XmlOut.isXmlChar('\udbff'));
+
+        assertTrue(XmlOut.isXmlChar('\udc00'));
+        assertTrue(XmlOut.isXmlChar('\udfff'));
+
+        assertTrue(XmlOut.isXmlChar('\ue000'));
+        assertTrue(XmlOut.isXmlChar('\ufffd'));
+
+        assertFalse(XmlOut.isXmlChar('\ufffe'));
+        assertFalse(XmlOut.isXmlChar('\uffff'));
+
+        return;
+    }
+
+    /**
+     * Test of replaceChar method, of class XmlOut.
+     */
+    @Test
+    public void testReplaceChar() {
+        System.out.println("replaceChar");
+
+        char result;
+
+        result = XmlOut.replaceChar('\u0000');
+        assertEquals('\u2400', result);
+
+        result = XmlOut.replaceChar('\u001f');
+        assertEquals('\u241f', result);
+
+        result = XmlOut.replaceChar('\u007f');
+        assertEquals('\u2421', result);
+
+        result = XmlOut.replaceChar('A');
+        assertEquals('\ufffd', result);
+
+        return;
+    }
+
+    /**
+     * Test of toHex method, of class XmlOut.
+     */
+    @Test
+    public void testToHex_byte() {
+        System.out.println("toHex");
+
+        byte bVal;
+        String result;
+
+        bVal = 0x00;
+        result = XmlOut.toHex(bVal);
+        assertEquals("00", result);
+
+        bVal = 0x0a;
+        result = XmlOut.toHex(bVal);
+        assertEquals("0a", result);
+
+        bVal = 0x7f;
+        result = XmlOut.toHex(bVal);
+        assertEquals("7f", result);
+
+        bVal = (byte) 0x80;
+        result = XmlOut.toHex(bVal);
+        assertEquals("80", result);
+
+        bVal = (byte) 0xff;
+        result = XmlOut.toHex(bVal);
+        assertEquals("ff", result);
+
+        return;
+    }
+
+    /**
+     * Test of toHex method, of class XmlOut.
+     */
+    @Test
+    public void testToHex_char() {
+        System.out.println("toHex");
+
+        char cVal;
+        String result;
+
+        cVal = '\u0000';
+        result = XmlOut.toHex(cVal);
+        assertEquals("00", result);
+
+        cVal = '\u000b';
+        result = XmlOut.toHex(cVal);
+        assertEquals("0b", result);
+
+        cVal = '\u00ff';
+        result = XmlOut.toHex(cVal);
+        assertEquals("ff", result);
+
+        cVal = '\u0100';
+        result = XmlOut.toHex(cVal);
+        assertEquals("0100", result);
+
+        cVal = '\u7fff';
+        result = XmlOut.toHex(cVal);
+        assertEquals("7fff", result);
+
+        cVal = '\u8000';
+        result = XmlOut.toHex(cVal);
+        assertEquals("8000", result);
+
+        cVal = '\uffff';
+        result = XmlOut.toHex(cVal);
+        assertEquals("ffff", result);
+
+        return;
+    }
+
+    /**
+     * Test of toHex method, of class XmlOut.
+     */
+    @Test
+    public void testToHex_short() {
+        System.out.println("toHex");
+
+        short sVal;
+        String result;
+
+        sVal = 0x0000;
+        result = XmlOut.toHex(sVal);
+        assertEquals("0000", result);
+
+        sVal = 0x00ff;
+        result = XmlOut.toHex(sVal);
+        assertEquals("00ff", result);
+
+        sVal = 0x7fff;
+        result = XmlOut.toHex(sVal);
+        assertEquals("7fff", result);
+
+        sVal = (short) 0x8000;
+        result = XmlOut.toHex(sVal);
+        assertEquals("8000", result);
+
+        sVal = (short) 0xffff;
+        result = XmlOut.toHex(sVal);
+        assertEquals("ffff", result);
 
         return;
     }