2012-04-27 15 views
31

मैं चाहता हूँ:कैसे छंटनी (पढ़ना-लिखना) खोलना या छंटनी के साथ फाइल बनाना है?

  • पढ़ने-लिखने की विधा में एक फ़ाइल खोलने यदि वह मौजूद है;
  • यदि यह अस्तित्व में नहीं है तो इसे बनाएं;
  • इसे कभी भी कहीं भी छीनने में सक्षम हो।

संपादित: truncate मैं एक स्थिति तक लिख सकते हैं और फ़ाइल के शेष भाग को निरस्त मतलब के साथ, अगर वर्तमान

सभी इस atomically (एक open() कॉल या एक ही open() कॉल अनुकरण के साथ)

कोई भी खुला साधन लागू करने के लिए लगता है:

  • r: स्पष्ट रूप से काम नहीं करता है;
  • आर +: विफल रहता है अगर फ़ाइल मौजूद नहीं है;
  • डब्ल्यू: अगर यह मौजूद है तो फाइल को फिर से बनाएं;
  • डब्ल्यू +: अगर यह मौजूद है तो फाइल को फिर से बनाएं;
  • ए: पढ़ नहीं सकता;
  • ए +: छोटा नहीं कर सकता।

कुछ संयोजन मैंने कोशिश की (आरडब्ल्यू, आरडब्ल्यू +, आर + डब्ल्यू, इत्यादि) या तो काम नहीं कर रहे हैं। क्या यह संभव है?

कुछ doc रूबी से (भी अजगर पर लागू होता है):

r 
Read-only mode. The file pointer is placed at the beginning of the file. 
This is the default mode. 

r+ 
Read-write mode. The file pointer will be at the beginning of the file. 

w 
Write-only mode. Overwrites the file if the file exists. If the file 
does not exist, creates a new file for writing. 

w+ 
Read-write mode. Overwrites the existing file if the file exists. If the 
file does not exist, creates a new file for reading and writing. 

a 
Write-only mode. The file pointer is at the end of the file if the file 
exists. That is, the file is in the append mode. If the file does not exist, 
it creates a new file for writing. 

a+ 
Read and write mode. The file pointer is at the end of the file if the file 
exists. The file opens in the append mode. If the file does not exist, it 
creates a new file for reading and writing. 
+0

तो तुम अनिवार्य रूप से एक अधिलेखित करना चाहते हैं फ़ाइल करें और सुनिश्चित करें कि पिछली सामग्री उस बिंदु से नीचे नहीं रहती है जिसे आपने लिखना बंद कर दिया है? –

+0

हां। 'file.truncate() 'इस उद्देश्य के लिए काम करता है और यह तब काम करता है जब फ़ाइल" आर + "," डब्ल्यू "," डब्ल्यू + "होती है। लेकिन उनमें से सभी को ऊपर सूचीबद्ध दोष हैं। – ceztko

उत्तर

28

OpenGroup के अनुसार:

O_TRUNC

फ़ाइल मौजूद है और एक नियमित रूप से फ़ाइल है, और फ़ाइल सफलतापूर्वक O_RDWR या O_WRONLY खोला है, तो इसकी लंबाई 0 तक छोटा कर दिया जाता है और मोड और मालिक अपरिवर्तित हैं। इसका फीफो विशेष फाइल या टर्मिनल डिवाइस फ़ाइलों पर कोई प्रभाव नहीं पड़ेगा। अन्य फ़ाइल प्रकारों पर इसका प्रभाव कार्यान्वयन-निर्भर है। O_RDONLY के साथ O_TRUNC का उपयोग करने का परिणाम अपरिभाषित है।

तो, "w" या "w +" के साथ फ़ाइल खोलते समय O_TRUNC शायद पारित हो गया है। यह "छेड़छाड़" को एक अलग अर्थ देता है, जो मैं चाहता हूं।

पायथन के साथ समाधान os.open() फ़ंक्शन के साथ निम्न-स्तर I/O पर फ़ाइल खोलने लगता है।

निम्नलिखित अजगर समारोह:

def touchopen(filename, *args, **kwargs): 
    # Open the file in R/W and create if it doesn't exist. *Don't* pass O_TRUNC 
    fd = os.open(filename, os.O_RDWR | os.O_CREAT) 

    # Encapsulate the low-level file descriptor in a python file object 
    return os.fdopen(fd, *args, **kwargs) 

व्यवहार मैं चाहा। आप इसे इस तरह उपयोग कर सकते हैं (यह वास्तव में अपने प्रयोग मामला है):

# Open an existing file or create if it doesn't exist 
with touchopen("./tool.run", "r+") as doing_fd: 

    # Acquire a non-blocking exclusive lock 
    fcntl.lockf(doing_fd, fcntl.LOCK_EX) 

    # Read a previous value if present 
    previous_value = doing_fd.read() 
    print previous_value 

    # Write the new value and truncate 
    doing_fd.seek(0) 
    doing_fd.write("new value") 
    doing_fd.truncate() 
+0

os.O_RDWR के साथ खोलने से इसे मेरे साथ केवल पढ़ने के मोड में लिनक्स – rutherford

+1

में खुलता है, मैं वास्तव में फ़ाइलों के लिए लागू "truncate" शब्द के उपयोग से उत्तेजित हूं। Truncate हमेशा "क्लिप छोटा" जैसे कुछ (मेरे लिए) मतलब है। यह अर्थात् "ओवरराइट" से अर्थ में अलग है (फिर से, मेरे लिए)। –

+0

@StevenLu, मैं पूरी तरह से आपसे सहमत हूं। वैसे भी, महत्वपूर्ण बात यह है कि वांछित व्यवहार बहुत अधिक प्रयास किए बिना उपलब्ध है। एक संदर्भ के साथ एक सर्वर ताला लिखने के लिए, Ivo के समान, इस कोड की आवश्यकता थी। अब याद नहीं है, लेकिन मुझे एक अलग फ़ाइल में संदर्भ/जानकारी स्टोर करने के लिए वांछनीय नहीं मिला। हो सकता है कि मैं सिर्फ /var/run/foo.pid फ़ाइलों के व्यवहार की नकल करना चाहता हूं, जिन्हें अक्सर ताले के रूप में उपयोग किया जाता है और वर्तमान में चल रहे डिमन के पिड को स्टोर करता है। – ceztko

0

मैं रूबी में वास्तव में यह करने के लिए किसी भी सुरुचिपूर्ण रास्ते से पता नहीं है। मेरा समाधान शायद एक अस्थायी फ़ाइल बनाना, सामग्री को लिखना होगा, और उसके बाद इसे उस फ़ाइल नाम पर पुनर्नामित करना चाहिए जिसे मैं वास्तव में चाहता था। यदि यह मौजूद है, तो यह पिछली फ़ाइल को ओवरराइट करेगा, या अगर फ़ाइल नहीं है तो फाइल बनाएं। कुछ इस तरह:

orig_filename = './whatever_file.log' 
temp_filename = './.tempfile' 
temp_file = File.new(temp_filename, 'w') 

// Write contents to file 

temp_file.close 
File.rename(temp_filename, orig_filename) 

नाम बदलने SystemCallError बढ़ा देंगे अगर यह किसी भी कारण से विफल रहता है।

13

ठीक है, केवल इन मोड हैं, और उनमें से सभी को आपके द्वारा सूचीबद्ध "दोष" हैं।

आपका एकमात्र विकल्प open() को लपेटना है। ऐसा कुछ क्यों नहीं? (अजगर)

def touchopen(filename, *args, **kwargs): 
    open(filename, "a").close() # "touch" file 
    return open(filename, *args, **kwargs) 

यह सिर्फ खुला तरह बर्ताव करता है, तो आप भी इसे खोलने के लिए rebind सकता है() यदि आप वास्तव में चाहते हैं।

खुला की सभी सुविधाओं का संरक्षित कर रहे हैं, तो आप भी कर सकते हैं:

with touchopen("testfile", "r+") as testfile: 
    do_stuff() 

आप निश्चित रूप से एक contextmanager जो एक + मोड में फ़ाइल को खोलता है बना सकते हैं, स्मृति में पढ़ता है, और अवरोध लिखते हैं ताकि आप काट-छांट को संभालने जादुई रूप से डब्ल्यू मोड में एक अस्थायी फ़ाइल बनाकर, और जब आप इसे बंद करते हैं तो आपकी मूल फ़ाइल में tempfile का नाम बदलता है, लेकिन यह अनुमान लगाया जाएगा कि यह अधिक होगा।

+1

+1 क्योंकि आपने कुछ महत्वपूर्ण संकेत जोड़े हैं। मुझे लगता है कि मुझे एक बेहतर उत्तर मिला है (संभवतः) कम दौड़ की स्थिति के अधीन है। यह जल्द ही आ रहा है। – ceztko

+0

मेरा जवाब जोड़ा गया। – ceztko

+0

आह, मैं देखता हूं। मैंने ऐसा कुछ खोजा, लेकिन उसे नहीं मिला। अच्छा लगता है, अगर वह वास्तव में काम करता है, बहुत अच्छा! – ch3ka

2

आप पढ़ने, लिखने और "एक +" (रूबी) के साथ काट-छांट कर सकते हैं:

File.open("test.txt", "a+") do |f| 
    f.print "abc\ndefgh" 
    f.rewind 
    p f.read 
    f.truncate(5) 
end 
puts File.size("test.txt") #=> 5 
+0

मैं अजगर का उपयोग कर रहा हूं, लेकिन व्यवहार रूबी की तुलना में समान लगता है। हालांकि यह सच है कि 'truncate (आकार) 'काम करता है, बिना तर्क के' truncate()' एक समान तरीके से काम नहीं करता है (कम से कम लिनक्स में)। मेरा समाधान मैं चाहता था कि सही व्यवहार प्राप्त करें। – ceztko

+0

रूबी 'ट्रंकेट' में एक तर्क होना चाहिए। 'f.truncate (f.pos) 'कुछ ऐसा करेगा जैसा" यहां छेड़छाड़ करें! "। – steenslag

+0

अच्छा, सच :) एक और छोटा गड़बड़ यह है कि परिशिष्ट मोड में प्रारंभिक स्थिति फ़ाइल का अंत है, न कि शुरुआत। – ceztko

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^