LoginSignup
9
7

More than 5 years have passed since last update.

bufio.Scannerのend-of-line判断を変更してみる

Last updated at Posted at 2015-07-31

テキストファイルから1行ずつ取得して処理したい場合、
bufio.Scanner を使いますね。

bufio.Scanner には、Splitというメソッドがあり、
行末の判断基準を変更することができるようです。

デフォルトでは、LF(\n)または、CRLF(\r\n)を見つけると行末(end-of-line)だと判断して、
1行分のデータを返してくれます。
(CRLFが除かれたデータを取得できます)

改行が CR(\r) だけの場合には、正しく動作してくれません。

ということで、Scannerがデフォルトで使用している ScanLines を元にして、
チョイ足しで、改行が CR(\r)だけの場合に対応してみました。

まずは、type SplitFunc を実装する必要があります。
bufio の ScanLines を基にして、
3ステップ追加しただけですが、、、

func CustomScan(data []byte, atEOF bool) (advance int, token []byte, err error) {
    if atEOF && len(data) == 0 {
        return 0, nil, nil
    }
    var i int
    if i = bytes.IndexByte(data, '\n'); i >= 0 {
        // We have a full newline-terminated line.
        return i + 1, dropCR(data[0:i]), nil
    }
    if i = bytes.IndexByte(data, '\r'); i >= 0 {
        // ここを追加した。(CR があったら、そこまでのデータを返そう)
        return i + 1, data[0:i], nil
    }
    // If we're at EOF, we have a final, non-terminated line. Return it.
    if atEOF {
        return len(data), dropCR(data), nil
    }
    // Request more data.
    return 0, nil, nil
}

// dropCR drops a terminal \r from the data.
func dropCR(data []byte) []byte {
    if len(data) > 0 && data[len(data)-1] == '\r' {
        return data[0 : len(data)-1]
    }
    return data
}

このようなコードを自分のプログラムに追加して、
Splitメソッドに渡します。

func main() {
  var fp *os.File
  fp, _ = os.Open("./test.tsv")
  defer fp.Close()
  scanner := bufio.NewScanner(fp)
  scanner.Split(CustomScan)
  for scanner.Scan() {
    // 1行ずつ処理する
    ....
  }
}

それがどうした?って感じですが、
Atomエディタを使って、テキストファイルを作成したときに
改行が CR(\r) になってしまう現象に悩まされています。
Excel上のデータをコピーして、Atomにペースト(タブ区切り(TSV)の状態)すると発生します。
(解決策をご存知の方、教えてください。。。)

Atomエディタ側での解決策が見つからなかったので、bufioで何とかならんかとやってみた次第です。

もしかしたら、ReadString('\r') で対応してしまえばいいのかもしれませんが、
やっぱりCR,CRLFにも対応しておきたいし。

たいしたことはしていないですが、うまく動いたので良しです。

9
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
7