Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

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

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

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

http://golang.org/pkg/bufio/#ScanLines

改行が 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にも対応しておきたいし。

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

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away