2016-04-24 23 views
6

Tôi có một tập tin .txt 30MB, với một dòng dữ liệu (30 Triệu chữ số)
Thật không may, mọi phương pháp tôi đã cố gắng (mmap.read(), readline(), phân bổ RAM 1GB, cho vòng lặp) mất 45 + phút để đọc toàn bộ tệp. Mọi phương pháp tôi tìm thấy trên internet dường như hoạt động trên thực tế là mỗi dòng là nhỏ, do đó mức tiêu thụ bộ nhớ chỉ lớn như dòng lớn nhất trong tệp. Đây là mã tôi đang sử dụng.Reading Very Large Một Liner Text File

start = time.clock() 
z = open('Number.txt','r+') 
m = mmap.mmap(z.fileno(), 0) 
global a 
a = int(m.read()) 
z.close() 
end = time.clock() 
secs = (end - start) 
print("Number read in","%s" % (secs),"seconds.", file=f) 
print("Number read in","%s" % (secs),"seconds.") 
f.flush() 
del end,start,secs,z,m 

Khác với việc tách số từ một dòng sang các dòng khác nhau; mà tôi không muốn làm, là có một phương pháp sạch hơn mà sẽ không đòi hỏi một phần tốt hơn của một giờ?

Nhân tiện, tôi không nhất thiết phải sử dụng tệp văn bản.

tôi có: Windows 8.1 64-Bit, RAM 16 GB, Python 3.5.1

+1

Đọc một tệp 30MB nhanh chóng. Đó là 'int (filecontent)' là chậm. –

+0

Bạn có biết rằng việc chuyển đổi nó sẽ gây ra một xấp xỉ về nó, nhiều hay ít tùy thuộc vào loại bạn chọn? Bạn sẽ không giữ tất cả các chữ số gazillion của nó. – Roberto

+0

... Ý tôi là, tất nhiên bạn có thể làm việc với con số đó, nhưng các loại tiêu chuẩn sẽ không chứa 30 triệu chữ số có nghĩa trong một số. Chúng sẽ gần đúng. Bạn sẽ phải tìm kiếm, hoặc thực hiện, một cách để làm điều đó. – Roberto

Trả lời

1

Tôi đã sử dụng mô-đun gmpy2 để chuyển đổi chuỗi thành một số.

start = time.clock() 
z=open('Number.txt','r+') 
data=z.read() 
global a 
a=gmpy2.mpz(data) 
end = time.clock() 
secs = (end - start) 
print("Number read in","%s" % (secs),"seconds.", file=f) 
print("Number read in","%s" % (secs),"seconds.") 
f.flush() 
del end,secs,start,z,data 

Nó hoạt động sau 3 giây, chậm hơn nhiều, nhưng ít nhất nó đã cho tôi một giá trị số nguyên.

Cảm ơn tất cả vì những câu trả lời vô giá của bạn, tuy nhiên tôi sẽ đánh dấu câu trả lời này càng sớm càng tốt.

3

Một tập tin văn bản 30MB không nên mất nhiều thời gian để đọc, ổ đĩa cứng hiện đại sẽ có thể làm được điều này trong vòng chưa đầy một giây (không kể thời gian truy cập)

Sử dụng file python chuẩn IO nên hoạt động tốt trong trường hợp này:

with open('my_file', 'r') as handle: 
    content = handle.read() 

Sử dụng này trên máy tính xách tay của tôi mang lại thời gian ít hơn nhiều hơn một giây.

Tuy nhiên, việc chuyển đổi 30 MB thành số nguyên là nút cổ chai của bạn, vì python không thể đại diện cho điều này với kiểu dữ liệu long.

Bạn có thể thử với mô-đun thập phân, tuy nhiên nó được thiết kế chủ yếu cho số học dấu phẩy động. Ngoài ra, tất nhiên, có một số khóa học có thể nhanh hơn (và vì bạn có thể muốn thực hiện một số công việc với số sau này, nên sử dụng thư viện như vậy).

+0

Chẳng phải Numpy cũng có vấn đề tương tự? Cả hai đều cố gắng chuyển đổi một chuỗi rất lớn thành một số. –

11

File đọc rất nhanh (< 1s):

with open('number.txt') as f: 
    data = f.read() 

Chuyển đổi một chuỗi 30 triệu chữ số với một số nguyên, đó là chậm:

z=int(data) # still waiting... 

Nếu bạn lưu trữ số như thô dữ liệu nhị phân lớn hoặc nhỏ, sau đó int.from_bytes(data,'big') nhanh hơn nhiều.

Nếu tôi đã làm đúng tôi toán (Lưu ý _ có nghĩa là "câu trả lời dòng cuối cùng" trong thông dịch viên tương tác của Python):

>>> import math 
>>> math.log(10)/math.log(2) # Number of bits to represent a base 10 digit. 
3.3219280948873626 
>>> 30000000*_    # Number of bits to represent 30M-digit #. 
99657842.84662087 
>>> _/8      # Number of bytes to represent 30M-digit #. 
12457230.35582761    # Only ~12MB so file will be smaller :^) 
>>> import os 
>>> data=os.urandom(12457231) # Generate some random bytes 
>>> z=int.from_bytes(data,'big') # Convert to integer (<1s) 
99657848 
>>> math.log10(z) # number of base-10 digits in number. 
30000001.50818886 

EDIT: FYI, toán của tôi là không đúng, nhưng tôi cố định nó. Cảm ơn bạn đã 10 phiếu bầu không có thông báo: ^)

+0

Nếu tôi cố gắng sử dụng int.from_bytes (dữ liệu, 'lớn'), thì tôi nhận được một "TypeError: không thể chuyển đổi đối tượng unicode thành byte" –

+1

@ Master-chip Đọc nó bằng 'rb' để lấy dữ liệu nhị phân. –

+0

Rất tiếc, điều đó thật đáng xấu hổ. Nó hoạt động tuyệt vời, nó đọc nó trong 0,39 giây, cảm ơn bạn. –