我要创建约220'000个图像文件(.png)。尝试创建1'081th文件时遇到此错误消息:
恐慌:打开Scanner in = new Scanner(System.in);
String input;
//define arraylist outside of loop :-)
ArrayList<String> arraylist1 = new ArrayList<>();
ArrayList<String> arraylist2 = new ArrayList<>();
(while in.hasNext()){
//store entire line
input= in.nextLine();
//Splits input string with , stores each string in an index position in data[]
String[] data = input.split(",");
arraylist1.add(data[0]);
arraylist2.add(data[1]);
//etc....
}
我添加了defer w.Close()行,但它没有更改错误。
/media/Snaps/pics/image1081_0.png: too many open files
当然可以解决这个限制吗?也许我没有正确关闭文件?
答案 0 :(得分:1)
The Go Programming Language Specification
“ defer”语句调用一个函数,该函数的执行被推迟到 周围函数返回的那一刻,要么是因为 周围的函数执行了一个return语句,到达了结尾 其功能主体,或者因为对应的goroutine是 惊慌失措。
DeferStmt = "defer" Expression .
表达式必须是函数或方法调用;它不可能是 括起来。内置函数的调用受到限制 表达式语句。
每次执行“ defer”语句时,函数值和 与往常一样评估该呼叫的参数并重新保存,但 实际功能未调用。相反,延迟函数是 在周围的函数返回之前立即调用 相反的顺序,他们被推迟了。如果延迟功能值 计算为nil,则在调用函数时执行恐慌,而不是 当执行“ defer”语句时。
换句话说,如果要循环处理文件,请将单个文件的处理放在单独的函数中,以将Open
与defer Close()
配对。这样可以避免出现“打开文件过多”错误。
例如,使用这样的文件处理结构来确保每个文件在使用后立即关闭。
package main
import (
"fmt"
"io/ioutil"
"os"
)
// process single file
func processFile(name string) error {
f, err := os.Open(name)
if err != nil {
return err
}
defer f.Close()
fi, err := f.Stat()
if err != nil {
return err
}
fmt.Println(fi.Name(), fi.Size())
return nil
}
func main() {
wd, err := os.Getwd()
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
fis, err := ioutil.ReadDir(wd)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
// process all files
for _, fi := range fis {
processFile(fi.Name())
if err != nil {
fmt.Fprintln(os.Stderr, err)
}
}
}
游乐场:https://play.golang.org/p/FrBWqlMOzaS
输出:
dev 1644
etc 1644
tmp 548
usr 822
答案 1 :(得分:0)
直到周围的函数返回时才执行延迟语句,这就是为什么文件在for循环之后才保持打开状态的原因。
要解决此问题,您只需在循环内插入一个匿名函数调用:
for ... {
func() {
w, err := os.Create(testFile)
if err != nil {
panic(err)
}
defer w.Close()
...
}()
}
这样,在循环的每次迭代之后,当前文件都将关闭。
答案 2 :(得分:-3)
好的,我明白了,将defer w.Close()
更改为w.Close()
并在
png := vgimg.PngCanvas{Canvas: img}
if _, err := png.WriteTo(w); err != nil {
panic(err)
}
我现在已经超过1万张图片并且正在运行...