Почему содержимое моего файла заменяется? - PullRequest
0 голосов
/ 26 июня 2019

Я новичок в Python. Я открыл файл и пытаюсь заменить старые данные им, используя класс TextReader .

Я много раз пытался отладить код на PyCharm, но не мог понять, что происходит.

Это класс TextReader.

class TextReader:
    def __init__(self, spec):
       self.file = open(spec, 'r+')
       self.text = self.file.read()
       self.lines = 0
       for _ in self.file:
           self.lines += 1

    def replace(self, old, new):
        replace = ''
        for line in self.file:
            replace += line.replace(old, new) + '\n'
        self.file.write(replace)

t = TextReader('temp.txt')
t.replace('good', 'bad')
print(t.text)
print(t.lines)

И перед запуском программы файл temp.txt содержит: -

Python is a good programming language.

Это вывод следующего кода: -

0

Я открываю файл temp.txt после запуска программы, чтобы увидеть, что он пуст. Пожалуйста, помогите!

Ответы [ 3 ]

1 голос
/ 26 июня 2019

Файлы являются итераторами в Python, поэтому вы можете прочитать дескриптор файла только один раз.Вы пытаетесь прочитать один и тот же дескриптор здесь три раза, поэтому последние два ничего не делают:

class TextReader:
    def __init__(self, spec):
       self.file = open(spec, 'r+') 
       self.text = self.file.read() # < reads the iterator -- it is now spent
       self.lines = 0
       for _ in self.file:          # < try to read again does nothing
           self.lines += 1          # < this never runs

    def replace(self, old, new):
        replace = ''
        for line in self.file:      # < try to read again; loop again doesn't run
            replace += line.replace(old, new) + '\n'
        self.file.write(replace)

Если вы хотите считать строки, а затем читать эти строки одну за другой, просто прочитайте файл в список,Тогда count будет длина списка.Что-то вроде:

class TextReader:
    def __init__(self, spec):
        self.file = open(spec, 'r+')
        # alternative to below:
        # self.lines = list(self.file)
        self.lines = []
        for line in self.file:
            self.lines.append(line)

    def replace(self, old, new):
        replace = ''
        for line in self.lines:
            replace += line.replace(old, new) + '\n'
        self.file.write(replace)
        self.file.close()       # remember to close the file!

t = TextReader('test.txt')
t.replace('good', 'bad')
print(t.lines)
print(len(t.lines))

Это приведет к созданию файла с двумя строками - исходной строкой и добавленной строкой с good, замененными на bad.Это потому, что вы открываете с r+, что означает добавление.

1 голос
/ 26 июня 2019

Другие ответы объясняют, почему ваш код не работает. Так что это правильно, что вам нужно закрыть файл после того, как вы сделали, иначе это может вызвать утечки памяти. Также я рекомендую использовать with, поскольку он автоматически открывает и закрывает файл для вас. Вот как бы я это сделал.

class TextReader:
   def __init__(self, spec):
      self.file = spec
      self.text = ''
      self.lines = 0
      with open(spec, 'r') as f:
         for line in f:
            self.text += line
            self.lines += 1

   def replace(self, old, new):
      with open(self.file, "w") as f:
         r = ''
         for line in self.text.split("\n"):
            r += line.replace(old, new) + '\n'
         f.write(r)

t = TextReader('temp.txt')
t.replace('good', 'bad')
print(t.text)
print(t.lines)

Он автоматически закроет ваш файл для вас и снова откроет текст поверх текущего текста, заменив слова, которые вы хотите, так как «r +» добавится в конец файла.

1 голос
/ 26 июня 2019

file объекты имеют внутреннее смещение файла, которое изменяется при каждом чтении / записи / поиске в файле.поэтому вы неявно читаете до конца несколько раз и никогда не seek никуда не возвращаетесь, например:

  1. ваш file.read() будет читать до конца файла
  2. Вы делаете for _ in self.file и for line in self.file, эти итерации по каждой строке

, все они оставят смещение в конце.если вы не вернетесь seek обратно к началу, вы ничего не получите обратно, поскольку все эти операции начинаются с "текущего смещения"

Я бы предложил сделать так, как предлагает @tripleee, и прочитать один раз,затем разбить его на строки и затем поработать с этим, вместо того, чтобы неоднократно пытаться перечитать одни и те же данные из разных частей файла

...