2009-12-10 78 views
22

Làm cách nào để xóa dòng cuối cùng của tệp bằng python?Xóa dòng cuối cùng trong tệp bằng python

Input dụ File:

hello 
world 
foo 
bar 

Output File ví dụ:

hello 
world 
foo 

tôi đã tạo ra các mã sau đây để tìm số dòng trong file - nhưng tôi không biết làm thế nào để xóa số dòng cụ thể. Tôi mới làm quen với python - vì vậy nếu có một cách dễ dàng hơn - hãy cho tôi biết.

try: 
     file = open("file") 
    except IOError: 
     print "Failed to read file." 
    countLines = len(file.readlines()) 

EDIT:

I figured it out sử dụng nhiều câu trả lời: Chủ yếu là một cái gì đó của Strawberry và tôi thấy trong các trang web (xin lỗi, tôi không thể tìm thấy liên kết).

#!/usr/bin/env python 

import os, sys 

readFile = open("file") 

lines = readFile.readlines() 

readFile.close() 
w = open("file",'w') 

w.writelines([item for item in lines[:-1]]) 

w.close() 
+1

bạn đang cố gắng để thực sự loại bỏ các dòng từ tập tin, trên đĩa? Nếu vậy, hãy đảm bảo bạn hiểu rằng các tệp không có "dòng" từ quan điểm của hệ thống tệp. Các dòng là một quy ước của các lập trình viên và các chương trình. Những gì bạn thấy là một "dòng" là một chuỗi các byte ở đâu đó ở giữa nhiều byte khác. Để xóa "dòng" cuối cùng, bạn có thể cắt bớt tệp tại byte tương ứng với ký tự đầu tiên trong dòng. Đó không phải là khó khăn (bạn chỉ cần phải tìm nó), nhưng không có nhiều điểm nếu các tập tin có liên quan không có nhiều megabyte trong kích thước. –

+0

Điều gì sẽ xảy ra nếu dòng cuối cùng là dòng trống? – FogleBird

+0

Dòng cuối cùng không được để trống. Tôi xóa tất cả các dòng trống bằng đoạn mã python khác (từ google). – torger

Trả lời

8

Bạn có thể sử dụng đoạn mã trên và sau đó: -

lines = file.readlines() 
lines = lines[:-1] 

Điều này sẽ cung cấp cho bạn một loạt các dòng có chứa tất cả các dòng nhưng người cuối cùng.

+2

Điều này có hoạt động tốt cho các tệp lớn không? Ví dụ. hàng ngàn dòng? – torger

+0

@Nazarius, yêu cầu bạn phải đọc toàn bộ tệp. –

+3

Nó có thể không hoạt động tốt cho các tệp lớn hơn một megabyte hoặc hai. Phụ thuộc vào định nghĩa của bạn về "tốt". Nó sẽ được hoàn toàn tốt đẹp cho bất kỳ máy tính để bàn sử dụng cho một vài nghìn dòng. –

6

Điều này không sử dụng python, nhưng python là công cụ sai cho công việc nếu đây là nhiệm vụ duy nhất bạn muốn. Bạn có thể sử dụng các tiêu chuẩn * nix tiện ích head, và chạy

head -n-1 filename > newfile 

mà sẽ sao chép tất cả nhưng dòng cuối cùng của tên tập tin để newFile.

+0

Tôi muốn giữ nó trên nền tảng - do đó thông qua trăn trong câu hỏi. – torger

+4

Điều này không hoạt động trên Mac OSX: đầu: số dòng bất hợp pháp - -1 –

3

Trên hệ thống nơi file.truncate() công trình, bạn có thể làm một cái gì đó như thế này:

file = open('file.txt', 'rb') 
pos = next = 0 
for line in file: 
    pos = next # position of beginning of this line 
    next += len(line) # compute position of beginning of next line 
file = open('file.txt', 'ab') 
file.truncate(pos) 

Theo thử nghiệm của tôi, file.tell() không hoạt động khi đọc theo dòng, có lẽ do bộ đệm gây nhầm lẫn nó. Đó là lý do tại sao điều này làm tăng thêm độ dài của các dòng để tìm ra các vị trí. Lưu ý rằng điều này chỉ hoạt động trên các hệ thống mà dấu phân cách kết thúc bằng '\ n'.

+0

Rất nguy hiểm trên nền tảng sử dụng nhiều ký tự cho "kết thúc dòng" ... như trong Windows. –

+0

Điểm tốt. (Đó là lý do tại sao tôi ban đầu sẽ sử dụng tell(), nhưng nó không hoạt động.) Trong trường hợp này, mở tệp ở chế độ nhị phân sẽ hoạt động. –

+0

Tôi cũng sẽ đi với cắt ngắn, đặc biệt là cho các tập tin lớn. – alexis

4

Giả sử bạn đã làm điều này trong Python và rằng bạn có đủ lớn tập tin rằng danh sách cắt là không đủ, bạn có thể làm điều đó trong một pass duy nhất so với file:

last_line = None 
for line in file: 
    if last_line: 
     print last_line # or write to a file, call a function, etc. 
    last_line = line 

Không phải là nhất mã trang nhã trên thế giới nhưng nó hoàn thành công việc.

Về cơ bản nó đệm mỗi dòng trong một tệp thông qua biến last_line, mỗi lần lặp lại sẽ xuất ra dòng lặp lại trước đó.

0

Mặc dù tôi chưa thử nghiệm nó (xin vui lòng, không ghét điều đó) Tôi tin rằng có một cách nhanh hơn để đi. Đó là nhiều hơn một giải pháp C, nhưng khá có thể bằng Python. Nó không phải là Pythonic. Đó là một lý thuyết, tôi muốn nói.

Trước tiên, bạn cần biết mã hóa của tệp. Đặt một biến cho số byte một ký tự trong mã hóa đó sử dụng (1 byte trong ASCII). CHARsize (tại sao không). Có lẽ sẽ là 1 byte với một tập tin ASCII.

Sau đó, lấy kích thước của tệp, đặt FILEsize cho nó.

Giả sử bạn có địa chỉ của tệp (trong bộ nhớ) trong FILEadd.

Thêm FILEsize to FILEadd.

Di chuyển lại các từ (tăng thêm -1 *** CHARsize **), kiểm tra từng CHARsize byte cho \ n (hoặc bất kỳ dòng mới nào mà hệ thống của bạn sử dụng). Khi bạn đạt đến \ n đầu tiên, bây giờ bạn có vị trí bắt đầu của dòng đầu tiên của tệp. Thay thế \ n bằng \ x1a (26, ASCII cho EOF, hoặc bất kỳ thứ gì là hệ thống của bạn/với mã hóa).

Dọn dẹp tuy nhiên bạn cần (thay đổi kích thước tệp, chạm vào tệp).

Nếu điều này làm việc như tôi nghi ngờ nó sẽ, bạn sẽ tiết kiệm rất nhiều thời gian, vì bạn không cần phải đọc toàn bộ tập tin ngay từ đầu, bạn đọc từ cuối.

+0

Lưu ý rằng toàn bộ \ x1a (hay còn gọi là^Z aka CTRL-Z aka EOF, thực sự là SUB trong ASCII) hoàn toàn là thế kỷ trước ... rất ít tệp văn bản được kết thúc bằng một ký tự SUB thực tế nữa, và thậm chí cả được giới hạn khá nhiều đối với các hệ thống Windows/DOS. Và CPM tôi nghĩ. –

+0

Ah tốt điểm - Tôi không chắc chắn nếu nó vẫn còn được sử dụng rộng rãi ... có thể cái gì khác được sử dụng để cứu vãn kỹ thuật này? – Isaac

0

đây là một cách khác, không slurping toàn bộ tập tin vào bộ nhớ

p="" 
f=open("file") 
for line in f: 
    line=line.strip() 
    print p 
    p=line 
f.close() 
0

Dưới đây là một giải pháp bộ nhớ hiệu quả tổng quát hơn cho phép các dòng 'n' cuối cùng để được bỏ qua (như lệnh head):

import collections, fileinput 
def head(filename, lines_to_delete=1): 
    queue = collections.deque() 
    lines_to_delete = max(0, lines_to_delete) 
    for line in fileinput.input(filename, inplace=True, backup='.bak'): 
     queue.append(line) 
     if lines_to_delete == 0: 
      print queue.popleft(), 
     else: 
      lines_to_delete -= 1 
    queue.clear() 
50

Vì tôi thường xuyên làm việc với nhiều tệp gigabyte, lặp lại như đã đề cập trong các câu trả lời không hiệu quả đối với tôi. Giải pháp tôi sử dụng:

file = open(sys.argv[1], "r+", encoding = "utf-8") 

#Move the pointer (similar to a cursor in a text editor) to the end of the file. 
file.seek(0, os.SEEK_END) 

#This code means the following code skips the very last character in the file - 
#i.e. in the case the last line is null we delete the last line 
#and the penultimate one 
pos = file.tell() - 1 

#Read each character in the file one at a time from the penultimate 
#character going backwards, searching for a newline character 
#If we find a new line, exit the search 
while pos > 0 and file.read(1) != "\n": 
    pos -= 1 
    file.seek(pos, os.SEEK_SET) 

#So long as we're not at the start of the file, delete all the characters ahead of this position 
if pos > 0: 
    file.seek(pos, os.SEEK_SET) 
    file.truncate() 

file.close() 
+3

đây là câu trả lời hay nhất. sử dụng câu lệnh "with" để lưu một dòng :) – cppython

+0

Rất dễ thực hiện. Rất giống C. –

+1

Tôi gặp phải một số vấn đề tương thích (sử dụng Py3) khi sử dụng phương pháp này trên các tệp đã được sử dụng trên cả mac và windows, vì nội bộ Mac sử dụng trình kết thúc dòng khác với Windows (sử dụng 2: cr và lf). Giải pháp là mở tệp ở chế độ đọc nhị phân ("rb +") và tìm kiếm ký tự dòng mới nhị phân b "\ n". – JrtPec

0

đây là giải pháp của tôi cho người dùng Linux:

import os 
file_path = 'test.txt' 
os.system('sed -i "$ d" {0}'.format(file_path)) 

không cần phải đọc và lặp qua các tập tin trong python.

1

Gây cảm hứng từ bài viết trước, tôi đưa ra này:

with open('file_name', 'r+') as f: 
    f.seek(0, os.SEEK_END) 
    while f.tell() and f.read(1) != '\n': 
    f.seek(-2, os.SEEK_CUR) 
    f.truncate() 
Các vấn đề liên quan