2016-04-24 9 views
6

मैं एक 30MB .txt फ़ाइल है पढ़ना, डेटा की एक लाइन (30 लाख अंकों की संख्या)
दुर्भाग्य से, हर विधि मैं कोशिश की है (mmap.read(), readline() साथ, लूप के लिए 1 जीबी रैम आवंटित) फ़ाइल को पूरी तरह से पढ़ने के लिए 45+ मिनट लगते हैं। इंटरनेट पर मिली हर विधि इस तथ्य पर काम करती है कि प्रत्येक पंक्ति छोटी है, इसलिए स्मृति खपत फ़ाइल में सबसे बड़ी रेखा जितनी बड़ी है। यहां वह कोड है जिसका मैं उपयोग कर रहा हूं।बहुत बड़ा एक लाइनर पाठ फ़ाइल

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 

संख्या को एक पंक्ति से विभिन्न पंक्तियों में विभाजित करने के अलावा; जो मैं नहीं करना चाहता, क्या वहां एक क्लीनर विधि है जिसके लिए एक घंटे के बेहतर हिस्से की आवश्यकता नहीं होगी?

वैसे, मुझे जरूरी नहीं कि टेक्स्ट फ़ाइलों का उपयोग करना पड़े।

मेरे पास है: विंडोज 8.1 64-बिट, 16GB राम, पायथन 3.5.1

+1

एक 30 एमबी फ़ाइल पढ़ना त्वरित है। यह 'int (filecontent)' है जो धीमा है। –

+0

क्या आप जानते हैं कि इसे परिवर्तित करने से आपके द्वारा चुने गए प्रकार के आधार पर कम या ज्यादा अनुमान होगा? आप इसके सभी गजलियन अंक नहीं रखेंगे। – Roberto

+0

... मेरा मतलब है, निश्चित रूप से आप उस नंबर पर काम करने में सक्षम हो सकते हैं, लेकिन मानक प्रकारों में एक संख्या में 30 मिलियन महत्वपूर्ण अंक नहीं होंगे। वे अनुमान लगाएंगे। आपको या तो ऐसा करने का एक तरीका खोजना होगा, या कार्यान्वित करना होगा। – Roberto

उत्तर

1

मैंने स्ट्रिंग को एक संख्या में बदलने के लिए gmpy2 मॉड्यूल का उपयोग किया।

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 

यह 3 सेकंड में काम करता था, बहुत धीमा, लेकिन कम से कम यह मुझे एक पूर्णांक मूल्य देता था।

आपके अमूल्य जवाबों के लिए धन्यवाद, हालांकि मैं इसे जल्द से जल्द चिह्नित करने जा रहा हूं।

3

एक 30MB पाठ फ़ाइल बहुत पढ़ने के लिए समय नहीं लगेगा, आधुनिक हार्ड ड्राइव एक सेकंड से भी कम समय में यह करने के लिए सक्षम होना चाहिए

मानक अजगर फ़ाइल आईओ का उपयोग करते हुए इस मामले में ठीक काम करना चाहिए (उपयोग समय की गिनती नहीं):

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

अपने लैपटॉप पर इस का उपयोग करते हुए एक दूसरे से बहुत कम बार अर्जित करता है।

हालांकि, उन 30 एमबी को एक पूर्णांक में परिवर्तित करना आपकी बाधा, है क्योंकि पाइथन long डेटाटाइप के साथ इसका प्रतिनिधित्व नहीं कर सकता है।

आप दशमलव मॉड्यूल के साथ प्रयास कर सकते हैं, हालांकि यह मुख्य रूप से फ़्लोटिंग पॉइंट अंकगणितीय के लिए डिज़ाइन किया गया है।

इसके अलावा, निश्चित रूप से गड़बड़ है, जो तेजी से हो सकता है (और चूंकि आप संभवतः बाद में संख्या के साथ कुछ काम करना चाहते हैं, इसलिए ऐसी लाइब्रेरी का उपयोग करना समझदारी होगी)।

+0

हालांकि अम्पी को एक ही समस्या नहीं होगी? वे दोनों एक बहुत बड़ी स्ट्रिंग को एक संख्या में बदलने की कोशिश कर रहे हैं। –

11

फ़ाइल को पढ़ने त्वरित (< 1s) है: यदि आप कच्चे रूप में संग्रहीत हैं

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

:, कि धीमी है

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

एक पूर्णांक के लिए 30 लाख अंकों स्ट्रिंग परिवर्तित बड़े- या छोटे-एंडियन बाइनरी डेटा, फिर int.from_bytes(data,'big') बहुत तेज़ है।

अगर मैं अपने गणित सही (नोट _ का अर्थ है "अंतिम पंक्ति के जवाब" अजगर के इंटरैक्टिव दुभाषिया में) किया:

>>> 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 

संपादित: FYI करें, मेरी गणित ठीक नहीं था, लेकिन मैं इसे तय की। बिना ध्यान दिए 10 अपवॉट्स के लिए धन्यवाद: ^)

+0

यदि मैं int.from_bytes (डेटा, 'बड़ा') का उपयोग करने का प्रयास करता हूं, तो मुझे "टाइप एरर: यूनिकोड ऑब्जेक्ट बाइट्स में बाइट्स नहीं बदल सकता" –

+1

@ मास्टर-चिप इसे बाइनरी डेटा प्राप्त करने के लिए 'आरबी' के साथ पढ़ें। –

+0

ओह, वह शर्मनाक था। यह बहुत अच्छा काम करता है, इसे 0.3 9 सेकेंड में पढ़ा जाता है, धन्यवाद। –

संबंधित मुद्दे