2010-02-02 20 views
11

Tôi có một tệp văn bản rất dài mà tôi đang cố gắng xử lý bằng cách sử dụng Python.Python cho rằng tệp văn bản 3000 dòng là một dòng dài?

Tuy nhiên, đoạn mã sau:

for line in open('textbase.txt', 'r'): 
    print 'hello world' 

chỉ sản xuất đầu ra sau đây:

hello world 

Nó như thể Python cho rằng tập tin là chỉ có một dòng dài, mặc dù nó là nhiều ngàn dòng dài, khi được xem trong trình soạn thảo văn bản. Kiểm tra nó trên dòng lệnh bằng cách sử dụng tập tin lệnh cho:

$ file textbase.txt 
textbase.txt: Big-endian UTF-16 Unicode English text, with CR line terminators 

Có điều gì sai? Tôi có cần phải thay đổi các dòng terminator không?

+0

OS gì là bạn không? –

+0

@OP, tệp textbase.txt đến từ đâu? các cửa sổ? hãy thử làm một dos2unix trên tập tin và xem nó là giải quyết vấn đề – ghostdog74

+0

@ jldupont: Tôi nghĩ AP257 dự kiến ​​sẽ in ra "hello world" cho mỗi dòng của tập tin đầu vào, giống như mã nói :-) – paxdiablo

Trả lời

6

Có thể bạn sẽ tìm thấy đó là "với các thuật ngữ dòng CR" cung cấp cho trò chơi. Nếu bạn đang làm việc trên nền tảng sử dụng dòng mới làm công cụ tạo dòng, thì sẽ xem tệp của bạn là một dòng chú giải lớn.

Thay đổi tệp đầu vào của bạn để tệp sử dụng đúng thuật ngữ dòng. Trình soạn thảo của bạn có lẽ sẽ được tha thứ nhiều hơn so với việc triển khai Python của bạn.

Kết thúc dòng CR là điều Mac theo như tôi biết và bạn có thể sử dụng công cụ sửa đổi chế độ U thành open để tự động phát hiện dựa trên đầu mối dòng đầu tiên được tìm thấy.

+0

'Nail + head' combo tôi nghĩ. +1. –

+0

Cảm ơn. Bất kỳ ý tưởng những gì tôi cần phải thay đổi chúng? – AP257

+0

Tôi sẽ nói '\ n'. –

-1

open() trả về đối tượng tệp. Bạn cần sử dụng:

for line in open('textbase.txt', 'r').readlines(): 
    print line 
+2

Điều này là không cần thiết, vì đối tượng tệp mở hoạt động như một trình lặp. –

+0

Không tạo sự khác biệt, xin lỗi ... – AP257

+0

Ah ... điểm tốt. Đã không đánh giá cao điều đó. – Paul

25

Theo documentation for open(), bạn nên thêm một U sang chế độ:

open('textbase.txt', 'Ur') 

Điều này cho phép "universal newlines", mà bình thường hóa chúng để \n trong chuỗi nó mang lại cho bạn .

Tuy nhiên, điều đúng cần làm là giải mã UTF-16BE thành các đối tượng Unicode trước tiên, trước khi dịch dòng mới. Nếu không, một byte cơ hội 0x0d có thể bị sai lầm biến thành một 0x0a, dẫn đến

UnicodeDecodeError: 'utf16' codec can't decode byte 0x0a in position 12: truncated data.

Python của codecs module cung cấp một chức năng open có thể giải mã Unicode và xử lý dòng mới cùng một lúc:

import codecs 
for line in codecs.open('textbase.txt', 'Ur', 'utf-16be'): 
    ... 

Nếu tập tin có một dấu thứ tự byte (BOM) và bạn chỉ định 'utf-16', sau đó nó phát hiện endianness và ẩn BOM cho bạn. Nếu nó không (vì BOM là tùy chọn), thì bộ giải mã đó sẽ tiếp tục và sử dụng tính cuối cùng của hệ thống của bạn, điều này có thể sẽ không tốt.

Xác định endianness mình (với 'utf-16be') sẽ không giấu BOM, vì vậy bạn có thể muốn sử dụng hack này:

import codecs 
firstline = True 
for line in codecs.open('textbase.txt', 'Ur', 'utf-16be'): 
    if firstline: 
     firstline = False 
     line = line.lstrip(u'\ufeff') 

Xem thêm: Python Unicode HOWTO

+0

+1 cho giải pháp thay vì chỉ phân tích (như trong câu trả lời của tôi) - bạn đã quá nhanh cho tôi :-) – paxdiablo

+0

Giải quyết vấn đề, python bây giờ thấy tất cả các dòng. Cảm ơn bạn rất nhiều: Tôi yêu trang web này :) – AP257

+1

@ AP257: họ cũng giải mã đúng không? Nếu nó thực sự là UTF-16BE, sẽ có 0 byte ở phía trước của mỗi dòng, vì đối tượng tệp của Python không mã hóa và chỉ tách các ký tự dòng mới. IMHO, bạn sẽ phải giải mã tệp (bằng cách sử dụng mô-đun codec) đúng cách trước khi tách thành các dòng là có thể. –

Các vấn đề liên quan