dqcuq4138 2014-04-29 10:54
浏览 241
已采纳

在Go中使用ioutil.ReadFile()读取1200多个文件时出错

I'm trying to read all the files (+10.000) in a directory, but when i've processed about 1400 files I get a 'too many open files' error. I've added an explicit call to the garbage collector, but that doesn't seem to do much for my problem. I checked the source for ioutil package and ReadFile uses defer file.Close() internally (as expected). So what is going wrong here?

    const TEMPLATE = `{ "source_db" : "CDARCHIEF", "doc_type" : "%s", "referentie" : "%s", "bestandsnaam" : "%s", "tekst" : "%s" }`
const MAPPING = `{ ... }`

var DIR, DOCTYPE, URL string

func init() {
    flag.StringVar(&DIR, "d", "./", "de directory met de ge-ocrde bestanden")
    flag.StringVar(&DOCTYPE, "t", "AG", "document type [ AG, CO, NN ]")
    flag.StringVar(&URL, "url", "...", "url voor de juiste index")
}

func main() {
    flag.Parse()
    fmt.Println("CD Archive Importer")
    importDocuments()
}

func importDocuments() {
    logfile, _ := os.Create("./importer.log")
    defer logfile.Close()

    files, _ := ioutil.ReadDir(DIR)
    error_counter := 0

    for i, file := range files {
        if math.Mod(float64(i), 400.0) == 0.0 {
            runtime.GC()
            fmt.Println("Running garbage collector")
        }

        fmt.Printf("Importing ( %d / %d ) [ errors: %d ]", i+1, len(files), error_counter)

        contents, err := ioutil.ReadFile(DIR + "/" + file.Name())
        if err != nil {
            error_counter = error_counter + 1
            logfile.WriteString(fmt.Sprintf("[ERROR/IO] : %s | %s
", file.Name(), err))
            continue
        }

        contents_string := strings.Replace(string(contents), "
", " ", -1)
        contents_string = strings.Replace(contents_string, "\"", " ", -1)
        contents_string = strings.Replace(contents_string, "\\", " ", -1)

        referentie := strings.Trim(file.Name(), ".txt")
        message := strings.NewReader(fmt.Sprintf(TEMPLATE, DOCTYPE, referentie, file.Name(), contents_string))

        resp, error := http.Post(URL, "application/json", message)
        if error != nil {
            error_counter = error_counter + 1
            logfile.WriteString(fmt.Sprintf("[ERROR/NET] : %s | %s | %s
", file.Name(), resp.Status, error))
            continue
        }
            defer resp.Body.Close()

        if resp.StatusCode != 201 {
            body, _ := ioutil.ReadAll(resp.Body)
            error_counter = error_counter + 1
            logfile.WriteString(fmt.Sprintf("[ERROR/ES] : %s | %s | %s
", file.Name(), resp.Status, string(body)))
        }

    }

    fmt.Println("
Done!")
}

I know that there is a somewhat similar question from about 2 years ago, but that didn't have a useful answer for my issue.

  • 写回答

1条回答 默认 最新

  • doudi5291 2014-04-29 11:40
    关注

    You may want to consider using filepath.Walk. I have successfully used it on 10k+ files without trouble. Alternatively you could dig into the source and see if they do anything different with regards to resource management.

    Also the for loop seems a bit baroque, you can just use integers and the % operator.

    for i := 0; i < 1000000; i += 1 {
        if i % 5000 == 0 {
            fmt.Println(i)
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 基于卷积神经网络的声纹识别
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 stm32开发clion时遇到的编译问题