2017-07-06 5 views
0

私はCSVがRabbitMQを介して多くの異なる上流アプリケーションから配信されるアプリケーションを扱います。ほとんどの場合、それは素晴らしい作品です。しかし、これらの上流のアプリケーションのカップルは古い(12-15年)であり、それらを書いた人々は長い間行っていません。io.CSVファイルに関連する読者と改行の問題

改行のため、これらの古いアプリケーションからCSVファイルを読み取ることができません。私は、UTF-8キャリッジリターン(http://www.fileformat.info/info/unicode/char/000d/index.htm)にマップすることが分かり次第、これはちょっと変わっています。通常、アプリは古いファイルのヘッダーのみを読み込み、それ以外は読み込みません。

これらのファイルのいずれかをテキストエディタで開いて、既存のファイルを上書きするutf-8エンコーディングとして保存すると、全く問題なく動作します。

リーダー-Using:

物事私は私が仕事に期待しようとした行ずつを読み取るためにスキャナを-Using

ba := make([]byte, 262144000) 
    if _, err := file.Read(ba); err != nil { 
     return nil, err 
    } 
    ba = bytes.Trim(ba, "\x00") 
    bb := bytes.NewBuffer(ba) 
    reader := csv.NewReader(bb) 
    records, err := reader.ReadAll() 
    if err != nil { 
     return nil, err 
    } 

を(bufio.Scannerを得る:トークンが長すぎます)私は動作しないことが予想しようとした(としませんでした)

scanner := bufio.NewScanner(file) 
    var bb bytes.Buffer 
    for scanner.Scan() { 
     bb.WriteString(fmt.Sprintf("%s\n", scanner.Text())) 
    } 

    // check for errors 
    if err = scanner.Err(); err != nil { 
     return nil, err 
    } 


reader := csv.NewReader(&bb) 
records, err := reader.ReadAll() 
if err != nil { 
    return nil, err 
} 

もの:

  • ファイルの内容を新しいファイル(.txt)に書き込んだり、ファイルを読み込んだり(作成したtxtファイルに対してdos2unixを実行することを含む)
  • ファイルを標準の文字列に読み込んでいます(GoのUTF-もちろん、それは)ルーンスライスへ
  • 読書ファイルは、その後、バイトスライスを経由して文字列に変換しません

私は、実行可能なアプローチのあまりわからhttps://godoc.org/golang.org/x/text/transformパッケージの意識が、いないよ - それはのように見えますsrcエンコーディングは変換することがわかっている必要があります。

私は何か愚かに見落としていますか?これらのファイルをUTF-8に変換する方法や、ファイルのエンコードを知らずにラインの終わりを更新する方法はありますか?バイトからバイトへ行くことを伴わないオプションがありますか?私は考慮していません。 私は見落としてしまったことが本当に明白であると思っています。

謝罪 - 明白な理由でCSVファイルを共有できません。

+0

"謝罪 - 私は明白な理由のためにCSVファイルを共有することはできません。"謝罪する必要はありません。しかし、助けが必要な場合は、CSVファイルの人工的/匿名化/除外/剥奪されたサンプルが必要です。 – Volker

+0

それは問題です - 私はできません。データを編集したり、別のファイルに転送しようとすると、utf-8として保存され、動作します。私はStackOverflow上に何か「必要」があるとは思わない - 人々は一般的に非常に有用である。 – Airomega

+0

また、もし私ができたとしても、StackOverflow上にファイルを添付するとは思えません。私はいくつかの外部サイトに追加する必要があります - そして、私はインターネットの見知らぬ人がアップロードした外部サイトからランダムなファイルをダウンロードしないことを知っています。 – Airomega

答えて

1

\ r \ nまたは\ rからすべての行末を\ nに置き換えようとしましたか?

+0

あなたは宝石です - それは働いた。 s = strings.Replace(s、 "\ r"、 "\ n"、-1)。 – Airomega

2

これに遭遇し、答えがstrings.Replaceではない場合は、io.Readerをラップしてソロキャリッジリターンを置き換える方法があります。おそらくより効率的ですが、strings.Replaceベースのソリューションよりも巨大なファイルでうまく動作します。

https://gist.github.com/b5/78edaae9e6a4248ea06b45d089c277d6

// ReplaceSoloCarriageReturns wraps an io.Reader, on every call of Read it 
// for instances of lonely \r replacing them with \r\n before returning to the end customer 
// lots of files in the wild will come without "proper" line breaks, which irritates go's 
// standard csv package. This'll fix by wrapping the reader passed to csv.NewReader: 
// rdr, err := csv.NewReader(ReplaceSoloCarriageReturns(r)) 
// 
func ReplaceSoloCarriageReturns(data io.Reader) io.Reader { 
    return crlfReplaceReader{ 
     rdr: bufio.NewReader(data), 
    } 
} 

// crlfReplaceReader wraps a reader 
type crlfReplaceReader struct { 
    rdr *bufio.Reader 
} 

// Read implements io.Reader for crlfReplaceReader 
func (c crlfReplaceReader) Read(p []byte) (n int, err error) { 
    if len(p) == 0 { 
     return 
    } 

    for { 
     if n == len(p) { 
      return 
     } 

     p[n], err = c.rdr.ReadByte() 
     if err != nil { 
      return 
     } 

     // any time we encounter \r & still have space, check to see if \n follows 
     // if next char is not \n, add it in manually 
     if p[n] == '\r' && n < len(p) { 
      if pk, err := c.rdr.Peek(1); (err == nil && pk[0] != '\n') || (err != nil && err.Error() == io.EOF.Error()) { 
       n++ 
       p[n] = '\n' 
      } 
     } 

     n++ 
    } 
    return 
} 
関連する問題