解析する非常に大きなテキスト ファイルがあります。主なパターンは次のとおりです。
step 1
[n1 lines of headers]
3 3 2
0.25 0.43 12.62 1.22 8.97
12.89 89.72 34.87 55.45 17.62
4.25 16.78 98.01 1.16 32.26
0.90 0.78 11.87
step 2
[n2 != n1 lines of headers]
3 3 2
0.25 0.43 12.62 1.22 8.97
12.89 89.72 34.87 55.45 17.62
4.25 16.78 98.01 1.16 32.26
0.90 0.78 11.87
step 3
[(n3 != n1) and (n3 !=n2) lines of headers]
3 3 2
0.25 0.43 12.62 1.22 8.97
12.89 89.72 34.87 55.45 17.62
4.25 16.78 98.01 1.16 32.26
0.90 0.78 11.87
言い換えると:
セパレーター: ステップ #
既知の長さのヘッダー (バイトではなく行番号)
データ 3 次元形状: nz、ny、nx
データ: Fortran フォーマット、元のデータセットで ~10 個の浮動小数点数/行
データを抽出し、浮動小数点数に変換し、numpy 配列に入れ、指定された形状に ndarray.reshape したいだけです。
私はすでに少しプログラミングを行っています...主なアイデアは
- 最初に各セパレーターのオフセットを取得する (「ステップ X」)
- データに到達するために nX (n1, n2...) 行 + 1 をスキップします
- そこから次のセパレーターまでバイトを読み取ります。
これらは物事を大きく遅くするので、最初は正規表現を避けたかったのです。最初のステップ (ファイルを参照して各パーツのオフセットを取得する) を完了するだけでも、すでに 3 ~ 4 分かかります。
問題は、基本的にfile.tell()
メソッドを使用してセパレーターの位置を取得していることです。
[file.tell() - len(sep) for line in file if sep in line]
問題は 2 つあります。
- 小さいファイルの場合
file.tell()
、正しい区切り位置が与えられますが、長いファイルの場合はそうではありません。明示的または暗黙的を使用せfile.tell()
ずにループで使用しないでください(両方を試しました)。わかりませんが、結果はそこにあります。大きなファイルでは、セパレータの直後の行の位置が体系的にわかりません。file.readline()
for line in file
[file.tell() for line in file if sep in line]
- len(sep) は、「separator」行の先頭に戻るための右オフセット補正を提供しません。
sep
ファイルの最初の行 (最初のセパレータ) を含む文字列 (バイト) です。
誰かがそれをどのように解析すべきか知っていますか?
注意: ファイル内を参照できるようにしたいので、最初にオフセットを見つけます: 10 番目のデータセットまたは 50000 番目のデータセットが必要な場合があります...
1-オフセットを見つける
sep = "step "
with open("myfile") as f_in:
offsets = [fin.tell() for line in fin if sep in line]
私が言ったように、これは単純な例では機能しますが、大きなファイルでは機能しません。
新しいテスト:
sep = "step "
offsets = []
with open("myfile") as f_in:
for line in f_in:
if sep in line:
print line
offsets.append(f_in.tell())
印刷された行はセパレーターに対応しています。間違いありません。しかし、 で得られたオフセットf_in.tell()
は次の行に対応しません。ファイルはメモリにバッファリングされていると思いますがf_in.tell()
、暗黙的なループで使用しようとすると、現在の位置ではなくバッファの末尾が取得されます。これはただの勝手な推測です。