কিভাবে একটি পাঠ্য ফাইল পরিবর্তন করতে?


175

আমি পাইথন ব্যবহার করছি, এবং ফাইলটি মোছা বা অনুলিপি না করে কোনও পাঠ্য ফাইলে একটি স্ট্রিং toোকাতে চাই। আমি এটা কিভাবে করবো?


1
আপনি এই উত্তরটি অ্যালেক্স মার্তেলির দ্বারা উল্লেখ করতে পারেন ।
অলোক



@Ani অন্যান্য পোস্ট হয় সদৃশ একটি টেক্সট ফাইল এর নির্দিষ্ট অবস্থানে থাকা ঢোকাতে লাইন যাহাই হউক না কেন এবং অবশ্যই সেখানে স্পষ্ট ক্ষান্ত উত্তর এখানে আছেন, কেন নয় অন্যান্য উপায় পরিবর্তে এখানে আপনার উত্তর যোগ করতে চান? গ্রহণযোগ্য উত্তর একটি ভাল প্রশ্নের প্রয়োজন হয় না
ভার্গব রাও

পুনঃটুইট করেছেন যদিও আমার সেই নকলটি পাওয়া উচিত ছিল!
আনি মেনন

উত্তর:


134

দুর্ভাগ্যক্রমে কোনও ফাইল পুনরায় না লিখে ofোকানোর কোনও উপায় নেই। পূর্ববর্তী পোস্টারগুলি যেমন ইঙ্গিত করেছে, আপনি কোনও ফাইলের সাথে সংযোজন করতে পারেন বা এর অংশটি ওভাররাইট করে সিক ব্যবহার করে করতে পারেন তবে আপনি যদি শুরুতে বা মাঝখানে স্টাফ যুক্ত করতে চান তবে আপনাকে এটি আবার লিখতে হবে।

এটি একটি অপারেটিং সিস্টেম জিনিস, পাইথন জিনিস নয়। সমস্ত ভাষায় এটি একই রকম।

আমি সাধারণত যা করি তা ফাইল থেকে পড়া, পরিবর্তনগুলি করা এবং এটি মাইফাইল.txt.tmp নামে একটি নতুন ফাইলে লিখুন বা এর মতো কিছু। পুরো ফাইলটি মেমোরিতে পড়ার চেয়ে এটি ভাল কারণ ফাইলটি এর জন্য খুব বড় হতে পারে। অস্থায়ী ফাইলটি শেষ হয়ে গেলে, আমি এটিকে মূল ফাইলের মতোই নতুন নামকরণ করি।

এটি করার একটি দুর্দান্ত, নিরাপদ উপায় কারণ যদি ফাইলটি লেখার কারণে কোনও কারণে ক্র্যাশ হয় বা বন্ধ হয় তবে আপনার কাছে এখনও আপনার অচ্ছুত মূল ফাইলটি রয়েছে।


3
ইউএনএক্স / এসডের মতো ইউনিক্স সরঞ্জামগুলি কি তাদের কোডে কিছু একই কাজ করে?
মনীশ গিল

এটি সত্য নয় যে সমস্ত ভাষায় এটি একই। অ্যাকশনস্ক্রিপ্টে: fileStream.openAsync (ফাইলের নাম, ফাইলমোড.আপডেট); তারপরে আমি যে ফাইলটি চাই সেখানে যেকোন জায়গায় যেতে এবং যেকোন কিছু পরিবর্তন করতে পারি।
অ্যান্ড্রুবেনজামিন

2
@ অ্যান্ড্রুবেনজামিন আপনি কি জানেন কী সিস্টেম কল করে অ্যাকশনস্ক্রিপ্ট তৈরি করছে? ওপেনসিঙ্ক ফাইলটি পড়ে এবং কল করার পরে একটি নতুন লেখার কোনও সম্ভাবনা আছে কি?
অ্যালেক্সLordThorsen

@ রাউরগুল্মমফিনস তবে, আমি জানি যে এটি পুরো ফাইলটি মেমরির মধ্যে পড়ছে না, কারণ আমি এটি বেশ কয়েকটি জিবি ফাইলস হ্যান্ডেল করতে ব্যবহার করেছি। আমি সন্দেহ করি এটি সি # স্ট্রাইমাইটারের সাথে লেখার মতোই। আমি পাইথনকে বড় আকারের বিকাশ এবং ফাইলের কারসাজির চেয়ে দ্রুত ছোট ছোট কাজগুলি করার সরঞ্জাম হিসাবে দেখি।
অ্যান্ড্রুবেনজামিন 21 '45

4
@ অ্যান্ড্রুবেনজামিন, ব্যবহারকারী ফাইলটি অনুসন্ধান এবং এটি পরিবর্তন করার বিষয়ে জিজ্ঞাসা করছেন না (আমি জানি প্রতিটি ভাষা এটি করতে পারে); তিনি পাঠ্য সন্নিবেশ করানোর বিষয়ে জিজ্ঞাসা করছেন যা ফাইলটিতে ইতিমধ্যে যা রয়েছে তা কেবল পরিবর্তন / ওভাররাইটিংয়ের চেয়ে আলাদা। হতে পারে ব্যবহারিক প্রয়োগে এটি ভিন্ন, তবে অ্যাকশনস্ক্রিপ্ট এপিআইতে আমার যে কিছুই খুঁজে পাওয়া যায় না তা ইঙ্গিত করে যে এটি অন্য যে কোনও ভাষা থেকে এই বিষয়ে আলাদা আচরণ করে।
ইস্তেরদা

104

আপনি যা করতে চান তার উপর নির্ভর করে। সংযোজন করতে আপনি এটি "এ" দিয়ে খুলতে পারেন:

 with open("foo.txt", "a") as f:
     f.write("new line\n")

আপনি যদি কিছু প্রিপ্রেন্ড করতে চান তবে আপনাকে প্রথমে ফাইলটি পড়তে হবে:

with open("foo.txt", "r+") as f:
     old = f.read() # read everything in the file
     f.seek(0) # rewind
     f.write("new line\n" + old) # write the new line before

9
withপাইথন 2.5 তে স্টেটমেন্টটি ব্যবহার করার জন্য আপনাকে সামান্য সংযোজন করতে হবে " ভবিষ্যতের আমদানি সহ_স্টেটমেন্ট" থেকে add এর বাইরে, withবিবৃতি দিয়ে ফাইলগুলি খোলার বিষয়টি ম্যানুয়াল বন্ধ হওয়ার চেয়ে অবশ্যই বেশি পঠনযোগ্য এবং কম ত্রুটি-প্রবণ one
আলেকজান্ডার কোজেভনিকিকভ

2
আরগটি fileinputব্যবহার করার সময় আপনি inline=Trueনালাগুলি খোলা / পড়া / পরিবর্তন / লেখার / প্রতিস্থাপনের রুটিনটি হ্যান্ডলগুলি সহ সহায়ক সহায়ক বিবেচনা করতে পারেন । এখানে উদাহরণ: stackoverflow.com/a/2363893/47390
mikegreenberg

3
শুধু ফাইলটি বন্ধ করতে ভুলবেন না f.Close()
ডি রোসাদো

5
এটি আমি ব্যবহার করি এমন স্টাইল নয়, ডি রোসাদো, তবে স্টাইলটি ব্যবহার করার সময়, আপনাকে নিজেই বন্ধ করার দরকার নেই বলে মনে করি। এটি তৈরির সংস্থানটির সাথে রাখে।
ক্রিস

4
আপনি না নিজে ঘনিষ্ঠ ফাইল করতে হবে। এটি এখানে "সহ" ব্যবহারের সম্পূর্ণ পয়েন্ট। (আচ্ছা, আসলে, পাইথন ফাইল বস্তু আবর্জনা সংগ্রহ করার সাথে সাথে এটি সম্পাদন করে, যা সিপাইনের সাথে আবদ্ধ নামটি যখন সুযোগের বাইরে চলে যায় ... তবে অন্যান্য বাস্তবায়ন হয় না, এবং সিপিথন কোনও দিন এটি করা বন্ধ করে দিতে পারে) , তাই "সহ" বাঞ্ছনীয়)
জারজেন এ। এরার্ড

71

fileinputপাইথন মান লাইব্রেরির মডিউল একটি ফাইল inplace পুনর্লিখন আপনি inplace = 1 পরামিতি ব্যবহার করব:

import sys
import fileinput

# replace all occurrences of 'sit' with 'SIT' and insert a line after the 5th
for i, line in enumerate(fileinput.input('lorem_ipsum.txt', inplace=1)):
    sys.stdout.write(line.replace('sit', 'SIT'))  # replace 'sit' and write
    if i == 4: sys.stdout.write('\n')  # write a blank line after the 5th line

1
এটি কীভাবে পাইথন 3 এ কাজ করবে? আমি কেবলমাত্র একটি অ্যাপ্লিকেশন পোর্ট করেছি যেটির পাইথন থেকে পাইথন 3 পর্যন্ত এর মতো কিছু কোড রয়েছে এবং আমি ঠিক এটি কাজ করতে পারি না। 'লাইন' ভেরিয়েবলটি একটি বাইট প্রকারের, আমি এটিকে ইউনিকোডে ডিকোড করার চেষ্টা করেছি এবং তারপরে এটি পরিবর্তন করে আবার এটিকে এনকোড করে বাইটে ফিরিয়েছি তবে এটি ঠিক কাজ করবে না। এটি কিছু ব্যতিক্রম উত্থাপন করে আমি আমার মাথার শীর্ষটি মনে করতে পারি না। লোকেরা পাইথন 3 এ ফাইলপিন্ট ইনপ্লেস = 1 ব্যবহার করে কোন সাফল্যের সাথে?
রব্রু

1
@ রব্রু: এখানে পাইথন 3 কোড
jfs

13
তবে কোনও সমস্যা নেই কারণ আপনি প্রথমে একটি গুরুত্বহীন ফাইলটিতে এটি পরীক্ষা করে ফেলেছেন?
পলা লিভিংস্টোন

33

জায়গায় জায়গায় কোনও ফাইল পুনরায় লেখার কাজটি প্রায়শই পুরানো অনুলিপি পরিবর্তিত নামের সাথে সংরক্ষণ করে করা হয়। ইউনিক্স লোকেরা পুরানোটিকে ~চিহ্নিত করতে একটি যুক্ত করে। উইন্ডোজ লোকেরা সব ধরণের কাজ করে - .bak বা .old - অথবা সম্পূর্ণরূপে ফাইলটির নাম পরিবর্তন করে বা the নামের সামনে রাখে।

import shutil
shutil.move( afile, afile+"~" )

destination= open( aFile, "w" )
source= open( aFile+"~", "r" )
for line in source:
    destination.write( line )
    if <some condition>:
        destination.write( >some additional line> + "\n" )
source.close()
destination.close()

পরিবর্তে shutil, আপনি নিম্নলিখিত ব্যবহার করতে পারেন।

import os
os.rename( aFile, aFile+"~" )

1
ভাল লাগছে। ভাবছি যদি .readlines () উত্সটি পুনরাবৃত্তি করার চেয়ে ভাল?
বোজডোজ

2
@ বোজডোজ: রিডলাইনগুলি পুরো ফাইলটি পড়ার কারণে পুনরাবৃত্তি আরও ভাল। বড় ফাইলগুলির জন্য ভাল নয়। অবশ্যই, এটি অনুমান করে যে আপনি আপনার স্থানীয় পরিবর্তনগুলি এমন একটি স্থানীয় উপায়ে করতে পারেন। কখনও কখনও আপনি পারবেন না, বা আপনার কোডটি আরও জটিল হয়ে উঠবে।
জর্জেন এ। এয়ারহার্ড

@ এস.লোট: os.rename(aFile, aFile + "~")কোনও অনুলিপি তৈরি না করে উত্স ফাইলটির নাম পরিবর্তন করবে।
পাতাপুম

14

পাইথনের এমএমএপ মডিউল আপনাকে কোনও ফাইলের মধ্যে প্রবেশ করতে দেবে allow নিম্নলিখিত নমুনাটি ইউনিক্সে এটি কীভাবে করা যায় তা দেখায় (উইন্ডোজ এমএম্যাপটি আলাদা হতে পারে)। নোট করুন যে এটি সমস্ত ত্রুটির শর্তাদি পরিচালনা করে না এবং আপনি মূল ফাইলটি দূষিত বা হারাতে পারেন। এছাড়াও, এটি ইউনিকোড স্ট্রিংগুলি পরিচালনা করবে না।

import os
from mmap import mmap

def insert(filename, str, pos):
    if len(str) < 1:
        # nothing to insert
        return

    f = open(filename, 'r+')
    m = mmap(f.fileno(), os.path.getsize(filename))
    origSize = m.size()

    # or this could be an error
    if pos > origSize:
        pos = origSize
    elif pos < 0:
        pos = 0

    m.resize(origSize + len(str))
    m[pos+len(str):] = m[pos:origSize]
    m[pos:pos+len(str)] = str
    m.close()
    f.close()

'আর +' মোডে খোলা ফাইলগুলি এমএমএপ ছাড়াই এটি করাও সম্ভব, তবে আপনাকে সন্নিবেশনের অবস্থান থেকে ইওএফ থেকে সাময়িকভাবে ফাইলের বিষয়বস্তু পড়তে এবং সংরক্ষণ করতে হবে বলে এটি কম সুবিধাজনক এবং কম দক্ষ - যা সম্ভবত বিশাল হতে।


14

অ্যাডামের উল্লেখ অনুসারে আপনার সিস্টেমের সীমাবদ্ধতাগুলি বিবেচনায় নেওয়ার আগে আপনার কাছে মেমরির সমস্ত অংশ পড়ার মতো পর্যাপ্ত মেমরি রয়েছে কিনা এর অংশগুলি প্রতিস্থাপন করে পুনরায় লিখতে হবে কিনা তা সম্পর্কে সিদ্ধান্ত নেওয়ার আগে।

আপনি যদি একটি ছোট ফাইল নিয়ে কাজ করছেন বা মেমরির সমস্যা না থাকলে এটি সহায়তা করতে পারে:

বিকল্প 1) সম্পূর্ণ ফাইলটিকে মেমোরিতে পড়ুন, লাইনের পুরো বা অংশে একটি রেজেক্স প্রতিস্থাপন করুন এবং সেই লাইনটি অতিরিক্ত লাইন দিয়ে প্রতিস্থাপন করুন। আপনার অবশ্যই নিশ্চিত করতে হবে যে 'মিডল লাইন' ফাইলটিতে অনন্য বা আপনার যদি প্রতিটি লাইনে টাইমস্ট্যাম্প থাকে তবে এটি নির্ভরযোগ্য হওয়া উচিত।

# open file with r+b (allow write and binary mode)
f = open("file.log", 'r+b')   
# read entire content of file into memory
f_content = f.read()
# basically match middle line and replace it with itself and the extra line
f_content = re.sub(r'(middle line)', r'\1\nnew line', f_content)
# return pointer to top of file so we can re-write the content with replaced string
f.seek(0)
# clear file content 
f.truncate()
# re-write the content with the updated content
f.write(f_content)
# close file
f.close()

বিকল্প 2) মাঝের রেখাটি চিহ্নিত করুন এবং সেই লাইনটি অতিরিক্ত লাইন দিয়ে প্রতিস্থাপন করুন।

# open file with r+b (allow write and binary mode)
f = open("file.log" , 'r+b')   
# get array of lines
f_content = f.readlines()
# get middle line
middle_line = len(f_content)/2
# overwrite middle line
f_content[middle_line] += "\nnew line"
# return pointer to top of file so we can re-write the content with replaced string
f.seek(0)
# clear file content 
f.truncate()
# re-write the content with the updated content
f.write(''.join(f_content))
# close file
f.close()

2

পরিষ্কারভাবে এটি করার জন্য একটি ছোট ক্লাস লিখেছিলেন।

import tempfile

class FileModifierError(Exception):
    pass

class FileModifier(object):

    def __init__(self, fname):
        self.__write_dict = {}
        self.__filename = fname
        self.__tempfile = tempfile.TemporaryFile()
        with open(fname, 'rb') as fp:
            for line in fp:
                self.__tempfile.write(line)
        self.__tempfile.seek(0)

    def write(self, s, line_number = 'END'):
        if line_number != 'END' and not isinstance(line_number, (int, float)):
            raise FileModifierError("Line number %s is not a valid number" % line_number)
        try:
            self.__write_dict[line_number].append(s)
        except KeyError:
            self.__write_dict[line_number] = [s]

    def writeline(self, s, line_number = 'END'):
        self.write('%s\n' % s, line_number)

    def writelines(self, s, line_number = 'END'):
        for ln in s:
            self.writeline(s, line_number)

    def __popline(self, index, fp):
        try:
            ilines = self.__write_dict.pop(index)
            for line in ilines:
                fp.write(line)
        except KeyError:
            pass

    def close(self):
        self.__exit__(None, None, None)

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        with open(self.__filename,'w') as fp:
            for index, line in enumerate(self.__tempfile.readlines()):
                self.__popline(index, fp)
                fp.write(line)
            for index in sorted(self.__write_dict):
                for line in self.__write_dict[index]:
                    fp.write(line)
        self.__tempfile.close()

তারপরে আপনি এটিকে এভাবে ব্যবহার করতে পারেন:

with FileModifier(filename) as fp:
    fp.writeline("String 1", 0)
    fp.writeline("String 2", 20)
    fp.writeline("String 3")  # To write at the end of the file

এটি ব্যক্তিগতভাবে আমার পক্ষে কাজ করে না, এটি ফাইলটিতে পাঠ্য যুক্ত করে তবে এটি প্রথমে সমস্ত কিছু সরিয়ে দেয়!
ব্রেট হকার

আসলে, এটি মোটেই কাজ করে না। লজ্জা, কারণ এটি একটি ভাল ধারণা মত মনে হয়েছিল।
মারিও ক্রুয়েলজ

0

আপনি যদি কিছু ইউনিক্স জানেন তবে আপনি নিম্নলিখিতটি চেষ্টা করতে পারেন:

নোটস: $ মানে কমান্ড প্রম্পট

বলুন যে আপনার কাছে এই জাতীয় সামগ্রীর সাথে একটি ফাইল my_data.txt রয়েছে:

$ cat my_data.txt
This is a data file
with all of my data in it.

তারপরে osমডিউলটি ব্যবহার করে আপনি সাধারণ sedকমান্ডগুলি ব্যবহার করতে পারেন

import os

# Identifiers used are:
my_data_file = "my_data.txt"
command = "sed -i 's/all/none/' my_data.txt"

# Execute the command
os.system(command)

আপনি যদি সেড সম্পর্কে সচেতন না হন তবে এটি পরীক্ষা করে দেখুন, এটি অত্যন্ত কার্যকর।


3
এটি মোটেই পাইথোনিক নয়
ডার্কসুনিইউএম
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.