我正在尝试读取目录中的所有文件(+10.000),但是当我处理约1400个文件时,出现“打开的文件太多”错误。我已经向垃圾收集器添加了一个明确的调用,但这似乎并不能解决我的问题。我检查了ioutil软件包的源,并且ReadFile在defer file.Close()内部使用(按预期方式)。那么,这里出了什么问题?
defer file.Close()
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 ]\r", 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\n", file.Name(), err)) continue } contents_string := strings.Replace(string(contents), "\n", " ", -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\n", 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\n", file.Name(), resp.Status, string(body))) } } fmt.Println("\nDone!") }
我知道大约2年前有一个类似的问题,但这对我的问题没有有用的答案。
您可能要考虑使用filepath.Walk。我已经成功地在10k +文件上使用了它,没有麻烦。或者,您可以深入研究源代码,看看它们在资源管理方面是否有任何不同之处。
同样,for循环似乎有点巴洛克式,您可以只使用整数和%运算符。
%
for i := 0; i < 1000000; i += 1 { if i % 5000 == 0 { fmt.Println(i) } }