गो की मानक लाइब्रेरी में पूरी तरह से यह जाँचने का इरादा नहीं है कि कोई फाइल मौजूद है या नहीं (जैसे कि पायथन की os.path.exists
)। इसे करने का मुहावरेदार तरीका क्या है?
गो की मानक लाइब्रेरी में पूरी तरह से यह जाँचने का इरादा नहीं है कि कोई फाइल मौजूद है या नहीं (जैसे कि पायथन की os.path.exists
)। इसे करने का मुहावरेदार तरीका क्या है?
जवाबों:
यह जाँचने के लिए कि क्या कोई फ़ाइल मौजूद नहीं है, पायथन के समकक्ष if not os.path.exists(filename)
:
if _, err := os.Stat("/path/to/whatever"); os.IsNotExist(err) {
// path/to/whatever does not exist
}
यह जाँचने के लिए कि क्या कोई फ़ाइल मौजूद है, पायथन के समकक्ष if os.path.exists(filename)
:
संपादित: हाल की टिप्पणियों के अनुसार
if _, err := os.Stat("/path/to/whatever"); err == nil {
// path/to/whatever exists
} else if os.IsNotExist(err) {
// path/to/whatever does *not* exist
} else {
// Schrodinger: file may or may not exist. See err for details.
// Therefore, do *NOT* use !os.IsNotExist(err) to test for file existence
}
NOTEXIST
, उदाहरण के लिए, यदि /etc/bashrc
मौजूद है, तो /etc/bashrc/foobar
वापस आ जाएगाENOTDIR
!os.IsNotExist(err)
। यह संभव है कि फ़ाइल मौजूद है, लेकिन os.Stat
अन्य कारणों (जैसे अनुमति, विफल डिस्क) के लिए विफल रहता है। err == nil
इस स्थिति का गलत तरीके से उपयोग करने से ऐसी विफलताएं "फ़ाइल मौजूद नहीं हैं" के रूप में वर्गीकृत होती हैं।
Caleb स्पेयर द्वारा उत्तर गोनट्स मेलिंग सूची में पोस्ट किया गया ।
[...] यह वास्तव में बहुत बार की जरूरत नहीं है और [...]
os.Stat
उन मामलों के लिए काफी आसान है जहां इसकी आवश्यकता होती है।[...] उदाहरण के लिए: यदि आप फ़ाइल खोलने जा रहे हैं, तो यह जाँचने का कोई कारण नहीं है कि यह पहले मौजूद है या नहीं। फ़ाइल जाँचने और खोलने के बीच गायब हो सकती है, और वैसे भी आपको
os.Open
त्रुटि की जाँच करने की आवश्यकता होगी । इसलिए आपos.IsNotExist(err)
फ़ाइल को खोलने का प्रयास करने के बाद बस कॉल करते हैं, और वहां उसके गैर-अस्तित्व से निपटते हैं (यदि इसके लिए विशेष हैंडलिंग की आवश्यकता होती है)।[...] आपको उन रास्तों के लिए जाँच करने की आवश्यकता नहीं है जो (और आपको नहीं करना चाहिए)।
os.MkdirAll
काम करता है या नहीं पथ पहले से मौजूद हैं। (इसके अलावा आपको उस कॉल से त्रुटि की जांच करने की आवश्यकता है)उपयोग करने के बजाय
os.Create
, आपको उपयोग करना चाहिएos.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
। यदि फ़ाइल पहले से मौजूद है, तो आपको एक त्रुटि मिलेगी। इसके अलावा आपके पास अपने संस्करण के विपरीत फ़ाइल बनाने के साथ एक दौड़ की स्थिति नहीं है, जो पहले से मौजूद है।
इससे लिया गया: https://groups.google.com/forum/#-msg/golang-nuts/Ayx-BMNdMFo/4rL8FFHr8v4J
आपको निम्नलिखित उदाहरण के रूप में कार्यों os.Stat()
और os.IsNotExist()
कार्यों का उपयोग करना चाहिए :
// Exists reports whether the named file or directory exists.
func Exists(name string) bool {
if _, err := os.Stat(name); err != nil {
if os.IsNotExist(err) {
return false
}
}
return true
}
User11617 द्वारा उदाहरण गलत है; यह रिपोर्ट करेगा कि फ़ाइल उन मामलों में भी मौजूद है जहां यह नहीं है, लेकिन किसी अन्य प्रकार की त्रुटि थी।
हस्ताक्षर एक्ज़िस्ट (स्ट्रिंग) (बूल, त्रुटि) होना चाहिए। और फिर, जैसा कि होता है, कॉल साइट्स बेहतर नहीं हैं।
उन्होंने जो कोड लिखा वह बेहतर होगा:
func Exists(name string) bool {
_, err := os.Stat(name)
return !os.IsNotExist(err)
}
लेकिन मैं इसके बजाय यह सुझाव देता हूं:
func Exists(name string) (bool, error) {
_, err := os.Stat(name)
if os.IsNotExist(err) {
return false, nil
}
return err != nil, err
}
err != nil
बदले err == nil
? यदि कोई त्रुटि है, तो फ़ाइल शायद मौजूद नहीं है?
अन्य उत्तर क्या छूट गए, यह है कि फ़ंक्शन को दिया गया पथ वास्तव में एक निर्देशिका हो सकता है। निम्नलिखित फ़ंक्शन सुनिश्चित करता है, कि पथ वास्तव में एक फ़ाइल है।
func fileExists(filename string) bool {
info, err := os.Stat(filename)
if os.IsNotExist(err) {
return false
}
return !info.IsDir()
}
इंगित करने के लिए एक और बात: यह कोड अभी भी एक दौड़ की स्थिति का कारण बन सकता है, जहां एक और धागा या प्रक्रिया निर्दिष्ट फ़ाइल को हटा देती है या बना देती है, जबकि fileExists फ़ंक्शन चल रहा है।
यदि आप इसके बारे में चिंतित हैं, तो अपने थ्रेड्स में एक लॉक का उपयोग करें, इस फ़ंक्शन तक पहुंच को अनुक्रमित करें या यदि एक से अधिक एप्लिकेशन शामिल हैं तो इंटर-प्रोसेस सेमाफोर का उपयोग करें। यदि अन्य एप्लिकेशन शामिल हैं, तो आपके नियंत्रण से बाहर, आप भाग्य से बाहर हैं, मुझे लगता है।
समारोह उदाहरण:
func file_is_exists(f string) bool {
_, err := os.Stat(f)
if os.IsNotExist(err) {
return false
}
return err == nil
}
आइए पहले कुछ पहलुओं पर गौर करें, os
पैकेज के द्वारा प्रदान किए गए दोनों फ़ंक्शन golang
उपयोगिताओं नहीं हैं, लेकिन त्रुटि चेकर्स, मेरा क्या मतलब है कि वे क्रॉस प्लेटफॉर्म पर त्रुटियों को संभालने के लिए सिर्फ एक आवरण हैं।
तो मूल रूप से अगर os.Stat
यह फ़ंक्शन कोई त्रुटि नहीं देता है, तो इसका मतलब है कि फ़ाइल मौजूद है यदि आपको यह जाँचने की आवश्यकता है कि यह किस प्रकार की त्रुटि है, तो इन दो फ़ंक्शन का उपयोग आता है os.IsNotExist
और os.IsExist
।
इसे Stat
फाइल थ्रोइंग एरर के रूप में समझा जा सकता है क्योंकि यह मौजूद नहीं है या यह एरर फेंक रहा है क्योंकि यह मौजूद है और इसके साथ कुछ समस्या है।
इन कार्यों को लेने वाला पैरामीटर प्रकार का होता है error
, हालांकि आप nil
इसे पारित करने में सक्षम हो सकते हैं, लेकिन यह समझ में नहीं आएगा।
यह इस तथ्य की ओर भी इशारा करता है कि IsExist is not same as !IsNotExist
, वे दो अलग-अलग चीजें हैं।
तो अब अगर आप जानना चाहते हैं कि क्या किसी दिए गए फ़ाइल में मौजूद है, मैं सबसे अच्छा तरीका है पसंद करेंगे:
if _, err := os.Stat(path/to/file); !os.IsNotExist(err){
//TODO
}
जैसा कि अन्य उत्तरों में उल्लेख किया गया है, विभिन्न झंडों का उपयोग करने से आवश्यक व्यवहार / त्रुटियों का निर्माण करना संभव है os.OpenFile
। वास्तव में, os.Create
ऐसा करने के लिए सिर्फ एक समझदार-चूक शॉर्टहैंड है:
// Create creates or truncates the named file. If the file already exists,
// it is truncated. If the file does not exist, it is created with mode 0666
// (before umask). If successful, methods on the returned File can
// be used for I/O; the associated file descriptor has mode O_RDWR.
// If there is an error, it will be of type *PathError.
func Create(name string) (*File, error) {
return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
}
आप जिस व्यवहार में रुचि रखते हैं उसे प्राप्त करने के लिए आपको इन झंडों को खुद से जोड़ना चाहिए:
// Flags to OpenFile wrapping those of the underlying system. Not all
// flags may be implemented on a given system.
const (
// Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified.
O_RDONLY int = syscall.O_RDONLY // open the file read-only.
O_WRONLY int = syscall.O_WRONLY // open the file write-only.
O_RDWR int = syscall.O_RDWR // open the file read-write.
// The remaining values may be or'ed in to control behavior.
O_APPEND int = syscall.O_APPEND // append data to the file when writing.
O_CREATE int = syscall.O_CREAT // create a new file if none exists.
O_EXCL int = syscall.O_EXCL // used with O_CREATE, file must not exist.
O_SYNC int = syscall.O_SYNC // open for synchronous I/O.
O_TRUNC int = syscall.O_TRUNC // truncate regular writable file when opened.
)
आप जो चुनते हैं, उसके आधार पर आपको अलग-अलग त्रुटियां मिलेंगी।
यहां एक उदाहरण है जहां मैं लिखने के लिए एक फ़ाइल खोलना चाहता हूं, लेकिन मैं केवल एक मौजूदा फ़ाइल को काट दूंगा यदि उपयोगकर्ता ने कहा है कि ठीक है:
var f *os.File
if truncateWhenExists {
// O_TRUNC - truncate regular writable file when opened.
if f, err = os.OpenFile(filepath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644); err != nil {
log.Fatalln("failed to force-open file, err:", err)
}
} else {
// O_EXCL - used with O_CREATE, file must not exist
if f, err = os.OpenFile(filepath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0644); err != nil {
log.Fatalln("failed to open file, err:", err)
}
}