1

解析する非常に大きなテキスト ファイルがあります。主なパターンは次のとおりです。

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 したいだけです。

私はすでに少しプログラミングを行っています...主なアイデアは

  1. 最初に各セパレーターのオフセットを取得する (「ステップ X」)
  2. データに到達するために nX (n1, n2...) 行 + 1 をスキップします
  3. そこから次のセパレーターまでバイトを読み取ります。

これらは物事を大きく遅くするので、最初は正規表現を避けたかったのです。最初のステップ (ファイルを参照して各パーツのオフセットを取得する) を完了するだけでも、すでに 3 ~ 4 分かかります。

問題は、基本的にfile.tell()メソッドを使用してセパレーターの位置を取得していることです。

[file.tell() - len(sep) for line in file if sep in line]

問題は 2 つあります。

  1. 小さいファイルの場合file.tell()、正しい区切り位置が与えられますが、長いファイルの場合はそうではありません。明示的または暗黙的を使用せfile.tell()ずにループで使用しないでください(両方を試しました)。わかりませんが、結果はそこにあります。大きなファイルでは、セパレータの直後の行の位置が体系的にわかりません。file.readline()for line in file[file.tell() for line in file if sep in line]
  2. 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()、暗黙的なループで使用しようとすると、現在の位置ではなくバッファの末尾が取得されます。これはただの勝手な推測です。

4

1 に答える 1

0

私は答えを得ました:for-ファイルをループし、tell()うまくいきません。for i in file混合しfile.readline()てエラーが発生するのと同じように。

したがって、またはのみfile.tell()で使用してください。file.readline()file.read()

決して使用しないでください

for line in file:
    [do stuff]
    offset = file.tell()

これは本当に残念ですが、その通りです。

于 2013-03-25T14:59:08.017 に答える