テキストファイルを読み取り、それをセクションに分割するように処理するプログラムがあります。
したがって、問題は、プログラムを変更して、ストリームリーダーを使用してファイルを読み取るときに、プログラムがファイルの最初の5行の読み取りをスキップできるようにすることです。
誰かがコードについてアドバイスしてくれませんか?ありがとう!
コード:
class Program
{
static void Main(string[] args)
{
TextReader tr = new StreamReader(@"C:\Test\new.txt");
String SplitBy = "----------------------------------------";
// Skip first 5 lines of the text file?
String fullLog = tr.ReadToEnd();
String[] sections = fullLog.Split(new string[] { SplitBy }, StringSplitOptions.None);
//String[] lines = sections.Skip(5).ToArray();
foreach (String r in sections)
{
Console.WriteLine(r);
Console.WriteLine("============================================================");
}
}
}
以下をお試しください
// Skip 5 lines
for(var i = 0; i < 5; i++) {
tr.ReadLine();
}
// Read the rest
string remainingText = tr.ReadToEnd();
行が固定されている場合、最も効率的な方法は次のとおりです。
using( Stream stream = File.Open(fileName, FileMode.Open) )
{
stream.Seek(bytesPerLine * (myLine - 1), SeekOrigin.Begin);
using( StreamReader reader = new StreamReader(stream) )
{
string line = reader.ReadLine();
}
}
また、行の長さが異なる場合は、次のように一度に1行ずつ読み取る必要があります。
using (var sr = new StreamReader("file"))
{
for (int i = 1; i <= 5; ++i)
sr.ReadLine();
}
プログラムでそれをより多く使用したい場合は、StreamReaderから継承されたカスタムクラスに、行をスキップする機能を持たせることをお勧めします。
このようなことができる:
class SkippableStreamReader : StreamReader
{
public SkippableStreamReader(string path) : base(path) { }
public void SkipLines(int linecount)
{
for (int i = 0; i < linecount; i++)
{
this.ReadLine();
}
}
}
この後、SkippableStreamReaderの関数を使用して行をスキップできます。例:
SkippableStreamReader exampleReader = new SkippableStreamReader("file_to_read");
//do stuff
//and when needed
exampleReader.SkipLines(number_of_lines_to_skip);
リストにさらに2つの提案を追加します。
常にファイルがあり、あなたが読むだけの場合は、これをお勧めします:
var lines = File.ReadLines(@"C:\Test\new.txt").Skip(5).ToArray();
File.ReadLinesは他のユーザーからのファイルをブロックせず、必要な行をメモリにロードするだけです。
ストリームが他のソースからのものである可能性がある場合は、このアプローチをお勧めします。
class Program
{
static void Main(string[] args)
{
//it's up to you to get your stream
var stream = GetStream();
//Here is where you'll read your lines.
//Any Linq statement can be used here.
var lines = ReadLines(stream).Skip(5).ToArray();
//Go on and do whatever you want to do with your lines...
}
}
public IEnumerable<string> ReadLines(Stream stream)
{
using (var reader = new StreamReader(stream))
{
while (!reader.EndOfStream)
{
yield return reader.ReadLine();
}
}
}
Iteratorブロックは、使い終わったら自動的にクリーンアップします。 ここ は、Jon Skeetによる記事で、それがどのように機能するかを詳しく説明しています(「そして最後に...」セクションまでスクロールしてください)。
それは次のように簡単だと思います:
static void Main(string[] args)
{
var tr = new StreamReader(@"C:\new.txt");
var SplitBy = "----------------------------------------";
// Skip first 5 lines of the text file?
foreach (var i in Enumerable.Range(1, 5)) tr.ReadLine();
var fullLog = tr.ReadToEnd();
String[] sections = fullLog.Split(new string[] { SplitBy }, StringSplitOptions.None);
//String[] lines = sections.Skip(5).ToArray();
foreach (String r in sections)
{
Console.WriteLine(r);
Console.WriteLine("============================================================");
}
}
StreamReader
with ReadLine
またはReadToEnd
は実際にバイトをメモリに読み込んで、これらの行を処理していない場合でも読み込まれます。大きなファイルの場合のアプリのパフォーマンス(10 MB以上)。
特定の行数をスキップする場合は、移動するファイルの位置を知る必要があります。これにより、2つのオプションが提供されます。
var linesToSkip = 10;
using(var reader = new StreamReader(fileName) )
{
reader.BaseStream.Seek(lineLength * (linesToSkip - 1), SeekOrigin.Begin);
var myNextLine = reader.ReadLine();
// TODO: process the line
}
var linesToSkip = 10;
using (var reader = new StreamReader(fileName))
{
for (int i = 1; i <= linesToSkip; ++i)
reader.ReadLine();
var myNextLine = reader.ReadLine();
// TODO: process the line
}
そして、すべてをスキップする必要がある場合は、すべてのコンテンツをメモリに読み込まずに実行する必要があります。
using(var reader = new StreamReader(fileName) )
{
reader.BaseStream.Seek(0, SeekOrigin.End);
// You can wait here for other processes to write into this file and then the ReadLine will provide you with that content
var myNextLine = reader.ReadLine();
// TODO: process the line
}