Go言語(golang)でShiftJISのファイルをutf-8に変換する

2020.02.04

データアナリティクス事業本部の森脇です。

Go言語で文字コードを変換するための方法について調べました。

使用するGo言語のバージョンは1.13.6です。

パッケージのインストール

文字コード変換を行うために、準標準パッケージであるgolang.org/x/textを使用します。

$ go mod init example.com/moriwaki/iconv
go: creating new go.mod: module example.com/moriwaki/iconv
$ go get -u golang.org/x/text
go: finding golang.org/x/text v0.3.2
go: downloading golang.org/x/text v0.3.2
go: extracting golang.org/x/text v0.3.2
$ cat go.mod
module example.com/moriwaki/iconv

go 1.13

require golang.org/x/text v0.3.2 // indirect

作っていく

main.goファイルを作成し、実装していきます。

変換にはgolang.org/x/text/transformを使います。

また、ShiftJISを扱うためにgolang.org/x/text/encoding/japaneseも使います。

ShiftJISからutf-8へ変換

package main

import (
	"bufio"
	"io"
	"log"
	"os"

	"golang.org/x/text/encoding/japanese"
	"golang.org/x/text/transform"
)

func main() {
	// ShiftJISファイルを開く
	sjisFile, err := os.Open("./sjis.txt")
	if err != nil {
		log.Fatal(err)
	}
	defer sjisFile.Close()

	// ShiftJISのデコーダーを噛ませたReaderを作成する
	reader := transform.NewReader(sjisFile, japanese.ShiftJIS.NewDecoder())

	// 書き込み先ファイルを用意
	utf8File, err := os.Create("./utf-8.txt")
	if err != nil {
		log.Fatal(err)
	}
	defer utf8File.Close()

	// 書き込み
	tee := io.TeeReader(reader, utf8File)
	s := bufio.NewScanner(tee)
	for s.Scan() {
	}
	if err := s.Err(); err != nil {
		log.Fatal(err)
	}
	log.Println("done")
}

読み込み時にShiftJISをutf-8へ変換し、ファイルへ書き込みます。

実行し、結果をnkfコマンドで確認してみます。

$ nkf -g sjis.txt 
Shift_JIS
$ go run main.go 
2020/02/04 16:15:39 done
$ nkf -g utf-8.txt 
UTF-8

うまく変換できました。

utf-8からShiftJISへ変換

逆のパターンを試してみます。

package main

import (
	"bufio"
	"io"
	"log"
	"os"

	"golang.org/x/text/encoding/japanese"
	"golang.org/x/text/transform"
)

func main() {
	// utf-8ファイルを開く
	utf8File, err := os.Open("./utf-8.txt")
	if err != nil {
		log.Fatal(err)
	}
	defer utf8File.Close()

	// 書き込み先ファイルを用意
	sjisFile, err := os.Create("./out-sjis.txt")
	if err != nil {
		log.Fatal(err)
	}
	defer sjisFile.Close()

	// ShiftJISのエンコーダーを噛ませたWriterを作成する
	writer := transform.NewWriter(sjisFile, japanese.ShiftJIS.NewEncoder())

	// 書き込み
	tee := io.TeeReader(utf8File, writer)
	s := bufio.NewScanner(tee)
	for s.Scan() {
	}
	if err := s.Err(); err != nil {
		log.Fatal(err)
	}
	log.Println("done")
}

実装上も逆の処理を行います。

utf-8のファイルを読み込み、書き込み時にShiftJISに変換します。

実行してみます。

$ nkf -g utf-8.txt
UTF-8
$ go run main.go 
2020/02/04 16:19:33 done
$ nkf -g out-sjis.txt 
Shift_JIS

こちらも正常に変換できました。

まとめ

「golang.org/x/text」パッケージを使うことで、非常に簡単に文字コード変換を行うことができました。

「golang.org/x/text/encoding/japanese」パッケージでは、ShiftJISの他にもEUC-JP, ISO-2022-JPも扱えるようです。

また、「golang.org/x/text/encoding/...」には日本語の他にも、韓国語,中国語向けのパッケージも存在していたので、こちらの言語の変換処理も簡単に行えるかもしれません。

Go言語はパッケージ構成が整っており、インターフェースも綺麗なのでファイル以外の変換も簡単に行えそうでした。

参考サイト