Re:Go 운영 csv의 기본 사항

15579 단어 Gocsvtech

개시하다


https://zenn.dev/syo_yamamoto/articles/1fb502ef862490
Print 표준을 통해 내보내면 다음과 같이 표시됩니다.(SHIFT-JIS 형식이기 때문에 맥에서 봤을 때 난사이즈예요. 잠시 틀어놓을게요.)
일본에서 CSV 파일은 일반적으로 ShiftJIS에서 자주 인코딩됩니다.Go 언어의 내부 인코딩은 UTF-8이므로 ShiftJIS의 CSV 파일을 읽으면 코드가 흐려집니다.

저기 편한 건요.


인코딩의 변환golang.org/x/text/transform이 편리합니다.이 포장과golang.org/x/text/encoding/japanese를 사용하면 os.Open에서 열린 파일도 UTF-8처럼 처리할 수 있다.

어떻게 처리합니까

japanese 포장에 변수japanese.ShiftJIS, 변수japanese.EUCJP와 변수japanese.ISO2022JP를 발표했다.이 인터페이스들은 실현되었다encoding.Encoding.
// Encoding is a character set encoding that can be transformed to and from
// UTF-8.
type Encoding interface {
	// NewDecoder returns a Decoder.
	NewDecoder() *Decoder

	// NewEncoder returns an Encoder.
	NewEncoder() *Encoder
}
Enceoder와Decorder는 바이트열을 바꾸는 방법EncodeDecode이 있다.
func (d *Decoder) Bytes(b []byte) ([]byte, error) {
	b, _, err := transform.Bytes(d, b)
	if err != nil {
		return nil, err
	}
	return b, nil
}
func (e *Encoder) Bytes(b []byte) ([]byte, error) {
	b, _, err := transform.Bytes(e, b)
	if err != nil {
		return nil, err
	}
	return b, nil
}
가 이 디코더를 사용하여 생성io.Reader한 것은transform.NewReader이다.구체적으로 다음과 같이 ShiftJIS 전용io.Reader을 제작할 수 있다.
transform.NewReader(f, japanese.ShiftJIS.NewDecoder())
원문의 CSV를 읽은 경우 다음과 같이 실시할 수 있다.
package main

import (
	"encoding/csv"
	"fmt"
	"log"
	"os"

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

func main() {
	f, err := os.Open("28HYOGO.CSV")
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	r := csv.NewReader(transform.NewReader(f, japanese.ShiftJIS.NewDecoder()))
	for {
		records, err := r.Read()
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(records)
	}
}
간단하네요.

저는 Go의 흐름 방향을 좋아해요.


내가 처음에 Go에 흥미를 느낀 것은 Go가 흐름을 방향으로 하기 때문이다.파일에서 모든 내용을 읽고 바이트열에 전달하여 CSV를 제거하는 프로그램 라이브러리도 볼 수 있지만 메모리가 낭비됩니다.Go는 흐름을 향하기 때문에 io.Reader를 사용하여 입력을 효과적으로 처리할 수 있다.
예를 들어, 위의 소스 코드인 경우 CSV 파일의 행 수가 아무리 길어도 메모리가 부족하지 않습니다.
이것이 바로 내가 Go를 좋아하는 이유다.encoding/json 마찬가지로 입력이 io.Reader라는 것을 주목하는 사람도 있을 수 있다.

그래도 zip을 읽으면 되지 않을까요?


네.Go에는 archive/zip가 있으므로 zip 파일이 확장되지 않고 CSV를 읽을 수 있습니다.
package main

import (
	"archive/zip"
	"encoding/csv"
	"fmt"
	"log"
	"path/filepath"
	"strings"

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

func readCSV(file *zip.File) error {
	r, err := file.Open()
	if err != nil {
		return err
	}
	defer r.Close()

	cr := csv.NewReader(transform.NewReader(r, japanese.ShiftJIS.NewDecoder()))
	for {
		records, err := cr.Read()
		if err != nil {
			return err
		}
		fmt.Println(records)
	}
}

func main() {
	zf, err := zip.OpenReader("28hyogo.zip")
	if err != nil {
		log.Fatal(err)
	}
	defer zf.Close()

	for _, file := range zf.File {
		if strings.ToLower(filepath.Ext(file.Name)) != ".csv" {
			continue
		}

		err := readCSV(file)
		if err != nil {
			log.Fatal(err)
		}
	}
}

끝말


이런 깊은 밤에 Go가 흐르는 지점을 전달하려고 써봤기 때문이다.메모리 효율이 좋은 처리를 반드시 실현해야 한다.

좋은 웹페이지 즐겨찾기