Webからデータを取得し、特定の文字を含む行の次の行に特定の文字を含む場合に、その行を取得します。
StringReaderとReadLineで実装しましたが、もう少しスマートな実装はないでしょうか。
#EXT-X-STREAM・・・640x360・・・ https:・・・abc.m3u8・・・ ←これではなく ・ #EXT-X-STREAM・・・640x360・・・ https:・・・xyz.m3u8・・・ ←これを取得したい
c#
1var m3u = wc.DownloadString(url); 2var sr = new StringReader(m3u); 3using(sr) 4{ 5 while (sr.Peek() > -1) 6 { 7 var line = sr.ReadLine();//1行ずつ取得 8 if (line.Contains("#EXT-X-STREAM") && line.Contains("640x360")) 9 { 10 var nextline = sr.ReadLine();//次の行を読み込む 11 if (nextline.Contains("xyz")) 12 { 13 (nextlineを取り出す); 14 } 15 } 16 } 17}
つまり「1行ずつ読み込みながら特定の文字列がきたときだけその次の行を取得する」というコードを書いてるわけですよね。
いいんじゃないでしょうか。シンプルで分かりやすいです。
複雑な正規表現を書くよりは不具合もないと思います。
そのとおりです。
ネストが深くなるので、簡潔なコードがあればと思いました。
というか「次の1行を取得」という操作は必ず発生するので、むしろこういうやり方がベターなんじゃないでしょうか。
以前私も出力されたテキストの解析やったことありますが、結局全て回して1文字ずつ解析しました。
情報が1行ずつDBに入ってればネストを1つ浅くできるかもしれないくらいの感じですね。
まあ私個人の感覚なので、もしかしたらもっと良い手があるかもしれませんが。
当初、ReadLinesを使ってLINQで書いていたのですが、おっしゃるとおり「次の1行を取得」する必要があるので、この方法に落ち着きました。
メモリ効率より速度を優先するなら、
一度string配列にしてZipで自己結合して全ての組み合わせを作り、
マルチスレッドで処理するのはどうでしょう?
LINQ を使うなら System.Interactive を Nuget でインストールして Buffer を使うと便利です。
var result = EnumerableEx
.Repeat(0)
.Select(_ => reader.ReadLine())
.TakeWhile(a => a != null)
.Buffer(2, 1)
.Where(a =>
{
return a.Count == 2
&& a[0].Contains("#EXT-X-STREAM")
&& a[0].Contains("640x360")
&& a[1].Contains("xyz.m3u8");
})
.FirstOrDefault();
if (result != null)
{
Console.WriteLine(result[1]);
}
Zuishinさん、回答に書かれた方が、見易くないですか?
LINQ を使うならっていう縛りを入れただけで、私は質問のもので十分だと思うんですよね。いわゆる余談です。
Zuishinさんいつもありがとうございます。
さっそく勉強してみます。
回答2件
あなたの回答
tips
プレビュー