我正在浏览文件列表,并将其中的xml数据解组为结构数组rArray
。我打算处理大约18000个文件。当我处理了大约1300个文件时,程序感到恐慌,并说打开了太多文件。如果我将处理的文件数量限制为1000个安全数量,则该程序不会崩溃。
如下所示,我正在ioutil.ReadFile
读取文件数据。
for _, f := range files {
func() {
data, err := ioutil.ReadFile("./" + recordDir + "/" + f.Name())
if err != nil {
fmt.Println("error reading %v", err)
return
} else {
if (strings.Contains(filepath.Ext(f.Name()), "xml")) {
//unmarshal data and put into struct array
err = xml.Unmarshal([]byte(data), &rArray[a])
if err != nil {
fmt.Println("error decoding %v: %v",f.Name(), err)
return
}
}
}
}()
}
我不确定Go使用的文件描述符过多还是没有足够快地关闭文件。
阅读https://groups.google.com/forum/#!topic/golang-nuts/7yXXjgcOikM并查看http://golang.org/src/pkg/io/ioutil/ioutil.go中的ioutil
源代码后,用于显示它用于关闭文件。返回调用函数并且是调用函数时运行。我的理解正确吗?我也尝试将代码的一部分包装在一个函数中,但这没什么区别。ioutil.ReadFile
defer
defer
ReadFile()
ioutil.ReadFile
我ulimit
的设置为无限制。
更新:我认为在我的Unzip函数期间实际上发生了太多文件的错误。
func Unzip(src, dest string) error {
r, err := zip.OpenReader(src)
if err != nil {
return err
}
for _, f := range r.File {
rc, err := f.Open()
if err != nil {
panic(err)
}
path := filepath.Join(dest, f.Name)
if f.FileInfo().IsDir() {
os.MkdirAll(path, f.Mode())
} else {
f, err := os.OpenFile(
path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
panic(err)
}
_, err = io.Copy(f, rc)
if err != nil {
panic(err)
}
f.Close()
}
rc.Close()
}
r.Close()
return nil
}
我最初是Unzip
从https://gist.github.com/hnaohiro/4572580获得该函数的,但经过进一步检查,defer
要点作者功能中的使用似乎是错误的,因为只有在该Unzip()
函数返回后才关闭文件,这太晚了因为将打开18000个文件描述符。;)
我如上所述Close
用显式替换了deferred Close()
,但是仍然遇到相同的“打开文件太多”错误。我修改后的解压缩功能是否存在问题?
更新#2糟糕,我一直在Heroku上运行此代码,并且整个过程都在将我的更改推送到错误的应用程序。获得的经验教训:在heroku工具栏中验证目标应用程序。
从解压码https://gist.github.com/hnaohiro/4572580并没有因为它没有关闭的文件,直到所有的文件处理工作。
我上面显式关闭的解压缩代码有效,@ peterSO的答案中的延迟版本也有效。
我可以将https://gist.github.com/hnaohiro/4572580的Unzip功能修改为以下内容:
package main
import (
"archive/zip"
"io"
"log"
"os"
"path/filepath"
)
func unzipFile(f *zip.File, dest string) error {
rc, err := f.Open()
if err != nil {
return err
}
defer rc.Close()
path := filepath.Join(dest, f.Name)
if f.FileInfo().IsDir() {
err := os.MkdirAll(path, f.Mode())
if err != nil {
return err
}
} else {
f, err := os.OpenFile(
path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
return err
}
defer f.Close()
_, err = io.Copy(f, rc)
if err != nil {
return err
}
}
return nil
}
func Unzip(src, dest string) error {
r, err := zip.OpenReader(src)
if err != nil {
return err
}
defer r.Close()
for _, f := range r.File {
err := unzipFile(f, dest)
if err != nil {
return err
}
}
return nil
}
func main() {
err := Unzip("./sample.zip", "./out")
if err != nil {
log.Fatal(err)
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句