2017-06-08 17 views
0

状況:mmapを使用してRAMにロードされたCVD(ClamAV Virus Database)ファイルがあります。 CVDファイルの各行の形式は、CSVファイル( ':'で区切られたファイル)の形式と同じです。以下のコードの抜粋です:RAMからCSVファイルを読み取る

def mapping(): 
    with open("main.cvd", 'rt') as f: 
     global mapper 
     mapper = mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ) 
     csv.register_dialect('delimit', delimiter=':', quoting=csv.QUOTE_NONE) 

def compare(hashed): 
    for row in csv.reader(mapper, dialect='delimit'): 
     if row[1] == hashed: 
      print('Found!') 

問題:どのように私はテキストとしてCSVファイルを読み取るか、メモリにロードされています:実行すると、それは誤り_csv.Error: iterator should return strings, not bytes (did you open the file in text mode?)

質問を返しますか?

追加情報1:私はそれがエラーをスローし、StringIOを使用してみましたがTypeError: initial_value must be str or None, not mmap.mmap

追加情報2:私は、ファイルへのアクセスを高速化するために、RAMにあるように、ファイルを必要と私はそれをラインを読んで時間を犠牲にすることはできませんラインによってcsv.readerコンストラクタへのそのようなreadline()

+0

代わりに(( "main.cvd"、 'b')をf:))として試してみましたか? – amrit

+0

どちらも動作しません。 –

+0

あなたは何をしようとしていますか? 'csv.reader' *は、' readline'を使って行ごとに読むのと同じように動作するイテレータを返します。* –

答えて

1

などの機能を使用してcsvfile引数は「イテレータプロトコルをサポートし、各時間は、そのnext()メソッドが呼び出された文字列を返す任意のオブジェクトとすることができます」。

これは、「オブジェクト」がジェネレータ関数またはジェネレータ式であることを意味します。以下のコードでは、mmap_file_reader()というジェネレータ関数を実装しています。この関数は、メモリマップのバイトを文字列に変換し、yieldが検出した出力の各行を変換します。

私はmmap.mmapコンストラクタコールを条件付きで呼び出し、Windowsでも動作するようにしました。これはprot=キーワードの代わりにaccess=キーワードを使用した場合は必要ありませんが、テストすることはできませんでした。

import csv 
import mmap 
import sys 

def mapping(): 
    with open("main.cvd", 'rt') as f: 
     global mapper 
     if sys.platform.startswith('win32'): 
      mmf = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) # windows 
     else: 
      mmf = mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ) # unix 
     mapper = mmap_file_reader(mmf) 
     csv.register_dialect('delimit', delimiter=':', quoting=csv.QUOTE_NONE) 

def mmap_file_reader(mmf): 
    '''Yield successive lines of the given memory-mapped file as strings. 

    Generator function which reads and converts the bytes of the given mmapped file 
    to strings and yields them one line at a time. 
    ''' 
    while True: 
     line = mmf.readline() 
     if not line: # EOF? 
      return 
     yield str(line, encoding='utf-8') # convert bytes of lineread into a string 

def compare(hashed): 
    for row in csv.reader(mapper, dialect='delimit'): 
     if row[1] == hashed: 
      print('Found!') 
+1

しかし私は、ファイルをメモリに読み込んで 'splitlines'を使うよりも速くなるのでしょうか? –

+1

@ juanpa.arrivillaga:おそらくそれより速くないでしょう。ファイルのサイズ、アクセスパターン、ファイルI/Oの速度、およびOSによって異なります。私は通常、ファイルが巨大なときにメモリマップされたものを使用します。一度に全部をメモリに読み込んだり、後で高速ランダムアクセスをしたいと思ったりしません。ファイルを順番に読むためには、おそらく良い選択ではないでしょう。 OPは、メモリマップされたファイルがRAMベースのファイルと同じものだと考えているようですが、もちろんそうではありません。 – martineau

+0

@martineauこれまで私が理解していたことから、メモリにファイルをロードする際に 'mmap 'を使用することを誤解しています。しかし、私はいくつかのテストを実行し、mmapを使用しない通常の 'open'と' for ... in ... 'がより高速であることを発見しました。しかし、あなたの方法は動作し、私の質問に答えるので、答えとしてマークします。ありがとうございました –

関連する問題