2017-07-14 36 views
1

私はmd5チェックサムに基づいてファイルの重複をチェックするプログラムを作ろうとしています。 そうでもない私は何かが足りないか、いないですか確かに、しかし、この機能はXCodeのインストーラアプリを読み込むには(それは8GBのように持っている)、私は問題をデバッグあたりとしてRAMioutil.ReadFileより高速な代替手段はありますか?

16GBの
func search() { 
    unique := make(map[string]string) 
    files, err := ioutil.ReadDir(".") 
    if err != nil { 
     log.Println(err) 
    } 

    for _, file := range files { 
     fileName := file.Name() 
     fmt.Println("CHECKING:", fileName) 
     fi, err := os.Stat(fileName) 
     if err != nil { 
      fmt.Println(err) 
      continue 
     } 
     if fi.Mode().IsRegular() { 
      data, err := ioutil.ReadFile(fileName) 
      if err != nil { 
       fmt.Println(err) 
       continue 
      } 
      sum := md5.Sum(data) 
      hexDigest := hex.EncodeToString(sum[:]) 
      if _, ok := unique[hexDigest]; ok == false { 
       unique[hexDigest] = fileName 
      } else { 
       fmt.Println("DUPLICATE:", fileName) 
      } 
     } 
    } 
} 

を使用してファイルの読み取り ではです。それを行うためのより良いアプローチがありますか? ありがとう

+0

'md5.New'と' io.Copy'を試してみてください。 [example](https://golang.org/pkg/crypto/md5/#example_New_file)を見てください。 – putu

答えて

4

Golangのドキュメントにはexampleがあり、あなたのケースをカバーしています。

package main 

import (
    "crypto/md5" 
    "fmt" 
    "io" 
    "log" 
    "os" 
) 

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

    h := md5.New() 
    if _, err := io.Copy(h, f); err != nil { 
     log.Fatal(err) 
    } 

    fmt.Printf("%x", h.Sum(nil)) 
} 

あなたの場合は、ループ内のファイルを閉じて、それらを延期しないようにしてください。または、ロジックを関数に入れます。

3

16GBのRAMのようなサウンドはあなた自身の問題であり、スピードそのものではありません。

ファイル全体をReadFileで変数に読み込まないでください。 io。ReaderがOpenからWriterに渡すと、hash/md5が提供する(md5.Newhash.Hashを返します。これにはio.Writerが埋め込まれています)。これは、すべてのファイルをRAMに取り込むのではなく、少しずつコピーするだけです。

これは、Goの多くの場所で便利なトリックです。 text/template,compress/gzip,net/httpなどのパッケージは、読者とライターの面で機能します。それらを使用すると、通常、大量の[]byteまたはstringを作成する必要はありません。 I/Oインターフェイスを相互にフックして、コンテンツの周りを渡すことができます。ガベージコレクション言語では、メモリを節約することでCPU作業も節約できます。

関連する問題