Page List

Search on the blog

2016年11月3日木曜日

デフォルト文字コードを変えてavroのserialize結果を確認した

 ちょっと気になったので実験してみた。
Javaでは、Charset.defaultCharset().name()とやると、JVMのデフォルトの文字コードを取得できる。この文字コードはOSのロケールや文字コードに依存して決まるらしい。
EclipseだとProject-Propertiesから文字コードを変更できるので、このへんをいろいろ変えてどうなるか見てみた。

実験コード

package com.kenjih.sample;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;

import org.apache.avro.Schema;
import org.apache.avro.SchemaBuilder;
import org.apache.avro.generic.GenericData;
import org.apache.avro.generic.GenericDatumWriter;
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.io.DatumWriter;
import org.apache.avro.io.EncoderFactory;
import org.apache.avro.io.JsonEncoder;

public class Main {

    public void run() throws IOException {
        // set default encoding
        System.out.println("default encoding=" + Charset.defaultCharset().name());

        // create avro record
        Schema schema = SchemaBuilder.record("test").namespace("hoge.fuga")
                .fields()
                .name("keyword").type().stringType().noDefault().endRecord();

        String keyword = "あいうえお";
        GenericRecord record = new GenericData.Record(schema);
        record.put("keyword", keyword);

        // serialize with json encoder
        DatumWriter<GenericRecord> writer = new GenericDatumWriter<GenericRecord>(schema);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        JsonEncoder encoder = EncoderFactory.get().jsonEncoder(schema, out);
        writer.write(record, encoder);
        encoder.flush();
        
        // see bytes of keyword
        byte[] bytes = keyword.getBytes();
        for (int i = 0; i < bytes.length; i++) {
            System.out.print(bytes[i] + ",");
        }
        System.out.println();
        
        // see bytes of serialize message
        bytes = out.toByteArray();
        for (int i = 0; i < bytes.length; i++) {
            System.out.print(bytes[i] + ",");
        }
        System.out.println();
        
        // bytes are encoded with UTF-8
        System.out.println(out.toString("UTF-8"));        
    }

    public static void main(String[] args) throws IOException {
        new Main().run();
    }

}

結果
以下のようにavroのserializerは、JVMのデフォルト文字コードが何であれ、UTF-8エンコーディングで結果を返すらしい。ということでシリアライズ結果を文字列に格納したい場合は、toString("UTF-8")しておけばOKっぽい。

UTF-8のとき
default encoding=UTF-8
-29,-127,-126,-29,-127,-124,-29,-127,-122,-29,-127,-120,-29,-127,-118,
123,34,107,101,121,119,111,114,100,34,58,34,-29,-127,-126,-29,-127,-124,-29,-127,-122,-29,-127,-120,-29,-127,-118,34,125,

{"keyword":"あいうえお"}

UTF-16のとき
default encoding=UTF-16
-2,-1,48,66,48,68,48,70,48,72,48,74,
123,34,107,101,121,119,111,114,100,34,58,34,-29,-127,-126,-29,-127,-124,-29,-127,-122,-29,-127,-120,-29,-127,-118,34,125,

{"keyword":"あいうえお"}

Shift_jisのとき
default encoding=Shift_JIS
-126,-96,-126,-94,-126,-92,-126,-90,-126,-88,
123,34,107,101,121,119,111,114,100,34,58,34,-29,-127,-126,-29,-127,-124,-29,-127,-122,-29,-127,-120,-29,-127,-118,34,125,

{"keyword":"あいうえお"}

0 件のコメント:

コメントを投稿