きどたかのブログ

いつか誰かがこのブログからトラブルを解決しますように。

ファイルの中身全体をJavaの正規表現でマッチングしたいんだが

PatternやMatcherを使う想定。


まず、Pattern#compileして、Patternを作る。
複数行にしたいならフラグも考える。


PatternができたらMatcherを作りたい。
そのとき必要なのはCharSequence。
そこはファイルの内容全部を渡したいが、
Javaヒープ使いたくないな。
FileChannelからmapして、MappedByteBufferを作って、CharsetからCharsetDecoder作って、単純なdecodeではなく、引数にCharBufferもあるdecodeを呼びたい。
単純なdecodeだと恐らく単純なCharBufferが作成されてしまい、きっとヒープに展開されるだろう。それは勘弁してもらいたい。
そのCharBufferは、ByteBuffer#allocateDirectしたByteBufferのasCharBuffer()にできないだろうか。CodeResultの扱い方は今度書きながら考える、昔書いたときはどうやってたんだろう。。。


目論見としては、ほとんど全部ヒープ外になってくれることを考えている。MappedByteBufferは、デコード後にとっとといなくなってほしい。GC起きないと厳しいだろうな。


allocateDirectするサイズがうまく見積もれない。デコーダから、averageCharsPerByteを取り、見積もるのが妥当なんだろう。
MappedByteBufferのlimitに、平均charsをかけて、charのバイト数の2をかけるのか?
そんでもって、どこかメモリ確保しやすい適当なところで繰り上げるか。
本当にlimitでええんやろか?
mapするときにチャネルのsizeを渡すつもりで、そのサイズと同じ値がlimitにくるはず。


瞬間的にヒープ外にかなり負担がかかりそう。
JVMオプションで拡げる必要がでてくるかもしれない。
GC起きないといけないし、何度も同じことやるとNative OOMコースになる可能性があるやも。それに寿命が短いバッファになる想定なんで、使い方としてはあまり納得がいくものではない。


むむぅ、小さいファイルなら非ダイレクトにしたほうが安全かもしれないしホント難しい。


ファイルの中身をCharBufferとして持てることで、正規表現の幅は広がる。
簡単な正規表現でしかないのなら、readLineして正規表現すればほとんどのことができるんだけど、複数行をやりたくなると、CharBufferを使いたくなる。


複数のPatternを用意して、初めに作成したMatcherに対して、usePattern呼び出しで、パターンの切り替えもできると思う。
DOTALLやMULTILINEをどんな感じに使うかはいろいろあるだろう。


あとは、DOTALL、否定先読み、前方参照/後方参照、最短一致あたりをコネコネ使えば、出現順不同なログの複数アサーションができるようになるんじゃねーのかな。
出現行の順序だけでなく、1行内のデータの出現順序まで順不同だった場合に、正規表現であわわあわわするんだろうけど、グループがネストした場合の参照番号の規則もちゃんと説明があるので、ゆっくりじっくり書けばなんとかなりそうだ。