0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

お題は不問!Qiita Engineer Festa 2024で記事投稿!
Qiita Engineer Festa20242024年7月17日まで開催中!

Go の Scanner で CSV インポートファイルを読み込む際の改行コードの扱いについて

Last updated at Posted at 2024-06-27

問題

Go の Scanner の挙動の違いにより、CSV インポート時のカウントにズレが生じました。

例えば CSV ファイルの中身が「A \n B のように 1 行の中に改行コードを含む場合。
改行コードも含めて 1 行と見なしたいケースを想定します。

下記①の場合ですと、改行コードで分割されて 2 行、
②の場合だと改行コードも含めて 1 行でカウントされます。

今回は②の挙動を期待していたのに、①の処理がなされていたために、想定するカウントとズレが発生した、という問題についてです。

①.bufio.NewScannerにおけるScanメソッドの挙動

処理

scanner := bufio.NewScanner(csv)
num := 0
for scanner.Scan() {
    num++
}
fmt.Println(num)

出力結果

2

説明

公式によると、The split function defaults to ScanLines.とあります。

そして、The end-of-line marker is one optional carriage return followed by one mandatory newline.とあります。

つまり、デフォルトでは改行コード(\r?\n)を見つけると、行末だと判断して 1 行分のデータを返す、ということになります。

補足

bufioパッケージは、「バッファリング(一時保存機構)付き I/O」を提供してくれます。
参考:https://pkg.go.dev/bufio

②.csv.NewReaderにおけるReadメソッドの挙動

処理

scanner := csv.NewReader(csv)
num := 0
for {
    _, err := scanner.Read()
    if err == io.EOF { // ファイル終わりに到達した場合は、ループを抜ける
        break 
    } else if err != nil {
        return err
    }
    num++
}
fmt.Println(num)

出力結果

1

説明

上記 csv パッケージの説明に記載されていますが、Carriage returns before newline characters are silently removed.とあります。

つまり、改行コードで改行されることはなく、改行コードも含めた行末までを 1 行として返す、ということになります。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?