Python - удалить самый последний символ в файле
Посмотрев весь интернет, я пришел к этому.
Допустим, я уже сделал текстовый файл, который гласит:Hello World
Ну, я хочу удалить самый последний символ (в этом случае d
) из этого текстового файла.
Теперь текстовый файл должен выглядеть так: Hello Worl
Но я понятия не имею, как это сделать.
Все, что я хочу, более или менее, - это одна функция возврата на экран для текстовых файлов на моем жестком диске.
Это должно работать на Linux, поскольку это то, что я использую.
8 ответов
Использование file.seek()
искать 1 позицию с конца, затем использовать file.truncate()
чтобы удалить оставшуюся часть файла:
with open(filename, 'rb+') as filehandle:
filehandle.seek(-1, os.SEEK_END)
filehandle.truncate()
Принятый ответ Martijn прост и отчасти работает, но не учитывает текстовые файлы с:
- Кодировка UTF-8, содержащая неанглийские символы (которая является кодировкой по умолчанию для текстовых файлов в Python 3)
- один символ новой строки в конце файла (по умолчанию в редакторах Linux, таких как
vim
или жеgedit
)
Если текстовый файл содержит неанглийские символы, ни один из предоставленных ответов не будет работать.
Ниже приведен пример, который решает обе проблемы, что также позволяет удалить более одного символа из конца файла:
import os
def truncate_utf8_chars(filename, count, ignore_newlines=True):
"""
Truncates last `count` characters of a text file encoded in UTF-8.
:param filename: The path to the text file to read
:param count: Number of UTF-8 characters to remove from the end of the file
:param ignore_newlines: Set to true, if the newline character at the end of the file should be ignored
"""
with open(filename, 'rb+') as f:
last_char = None
size = os.fstat(f.fileno()).st_size
offset = 1
chars = 0
while offset <= size:
f.seek(-offset, os.SEEK_END)
b = ord(f.read(1))
if ignore_newlines:
if b == 0x0D or b == 0x0A:
offset += 1
continue
if b & 0b10000000 == 0 or b & 0b11000000 == 0b11000000:
# This is the first byte of a UTF8 character
chars += 1
if chars == count:
# When `count` number of characters have been found, move current position back
# with one byte (to include the byte just checked) and truncate the file
f.seek(-1, os.SEEK_CUR)
f.truncate()
return
offset += 1
Как это устроено:
- Читает только последние несколько байтов текстового файла в кодировке UTF-8 в двоичном режиме
- Итерирует байты в обратном направлении, ища начало символа UTF-8
- Как только будет найден символ (отличный от новой строки), верните его как последний символ в текстовом файле.
Образец текстового файла - bg.txt
:
Здравей свят
Как пользоваться:
filename = 'bg.txt'
print('Before truncate:', open(filename).read())
truncate_utf8_chars(filename, 1)
print('After truncate:', open(filename).read())
Выходы:
Before truncate: Здравей свят
After truncate: Здравей свя
Это работает с файлами в кодировке UTF-8 и ASCII.
Если вы не читаете файл в двоичном режиме, где у вас есть только права доступа "w", я могу предложить следующее.
f.seek(f.tell() - 1, os.SEEK_SET)
f.write('')
В этом коде выше, f.seek()
будет принимать только f.tell()
б / у у вас нет доступа 'б'. тогда вы можете установить курсор на начало последнего элемента. Затем вы можете удалить последний элемент пустой строкой.
with open(urfile, 'rb+') as f:
f.seek(0,2) # end of file
size=f.tell() # the size...
f.truncate(size-1) # truncate at that size - how ever many characters
Обязательно используйте двоичный режим в Windows, так как конец строки файла Unix многие возвращают неверный или неправильный счетчик символов.
with open('file.txt', 'w') as f:
f.seek(0, 2) # seek to end of file; f.seek(0, os.SEEK_END) is legal
f.seek(f.tell() - 2, 0) # seek to the second last char of file; f.seek(f.tell()-2, os.SEEK_SET) is legal
f.truncate()
в зависимости от того, какой последний символ в файле, может быть новая строка (\n) или что-то еще.
Это может быть неоптимально, но если вышеперечисленные подходы не сработают, вы можете сделать:
with open('myfile.txt', 'r') as file:
data = file.read()[:-1]
with open('myfile.txt', 'w') as file:
file.write(data)
Код сначала открывает файл, а затем копирует его содержимое (за исключением последнего символа) в строку. После этого файл обрезается до нулевой длины (т.е. очищается), а содержимое
В системе Linux или (Cygwin в Windows). Вы можете использовать стандартную команду усечения. Вы можете уменьшить или увеличить размер вашего файла с помощью этой команды.
Чтобы уменьшить файл на 1 ГБ, команда будет truncate -s 1G filename
. В следующем примере я уменьшаю файл с именемupdate.iso
пользователя 1G.
Обратите внимание, что эта операция заняла менее пяти секунд.
chris@SR-ENG-P18 /cygdrive/c/Projects
$ stat update.iso
File: update.iso
Size: 30802968576 Blocks: 30081024 IO Block: 65536 regular file
Device: ee6ddbceh/4000177102d Inode: 19421773395035112 Links: 1
Access: (0664/-rw-rw-r--) Uid: (1052727/ chris) Gid: (1049089/Domain Users)
Access: 2020-06-12 07:39:00.572940600 -0400
Modify: 2020-06-12 07:39:00.572940600 -0400
Change: 2020-06-12 07:39:00.572940600 -0400
Birth: 2020-06-11 13:31:21.170568000 -0400
chris@SR-ENG-P18 /cygdrive/c/Projects
$ truncate -s -1G update.iso
chris@SR-ENG-P18 /cygdrive/c/Projects
$ stat update.iso
File: update.iso
Size: 29729226752 Blocks: 29032448 IO Block: 65536 regular file
Device: ee6ddbceh/4000177102d Inode: 19421773395035112 Links: 1
Access: (0664/-rw-rw-r--) Uid: (1052727/ chris) Gid: (1049089/Domain Users)
Access: 2020-06-12 07:42:38.335782800 -0400
Modify: 2020-06-12 07:42:38.335782800 -0400
Change: 2020-06-12 07:42:38.335782800 -0400
Birth: 2020-06-11 13:31:21.170568000 -0400
В stat
Команда сообщает вам много информации о файле, включая его размер.
Вот грязный способ (стереть и воссоздать)... я не советую использовать это, но, возможно, сделать так...
x = open("file").read()
os.remove("file")
open("file").write(x[:-1])