跟踪文本文件中新文本的可靠方法
Reliable approach to track new text in a text file
我正在尝试制作一个程序来跟踪文本文件列表中的更改(仅附加类型的更改)。使用 FileStream class 我遇到 ArgumentException 告诉“偏移量和长度超出数组范围或计数大于从索引到源集合末尾的元素数”。
另外,我很惊讶地发现我不能使用 long 来标记偏移量——那么我该如何读取巨型文件呢?
PS: 肯定不会有大量的新文本。
public partial class mainForm : Form
{
FileSummary initialSnap;
public mainForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
filePath_textBox.Text = openFileDialog1.FileName;
}
}
private void checkButton_Click(object sender, EventArgs e)
{
if (initialSnap == null)
{
initialSnap = new FileSummary(filePath_textBox.Text);
return;
}
FileSummary newSnap = new FileSummary(initialSnap.FullName);
var dateBefore = initialSnap.LastWriteTime;
var dateAfter = newSnap.LastWriteTime;
if (dateBefore == dateAfter) return;
var deltaLength = newSnap.Length - initialSnap.Length;
var prevLength = (int)initialSnap.Length;
using (FileStream fstream = File.OpenRead(initialSnap.FullName))
{
byte[] array = new byte[deltaLength];
fstream.Read(array, prevLength, array.Length);
string addedText = System.Text.Encoding.Default.GetString(array);
}
}
}
internal class FileSummary
{
public FileSummary(string fileFullPath)
{
FullName = fileFullPath;
FileInfo fi = new FileInfo(fileFullPath);
LastWriteTime = fi.LastWriteTime;
Length = fi.Length;
}
public string FullName { get; internal set; }
public DateTime LastWriteTime { get; internal set; }
public long Length { get; private set; }
}
您的代码中对 fstream.Read() 的调用不正确。 Read方法的第二个参数是文件内容放置的目标字节数组的偏移量,它不是你误解的文件中的起始偏移点。
这一行导致了错误,
fstream.Read(array, prevLength, array.Length);
必须改为,
fstream.Seek(prevLength , SeekOrigin.Begin);
fstream.Read(array, 0, array.Length);
所以,如果你只需要获取新写入文件的部分,你需要先seek
到之前的结束位置读取增量文件内容,然后填写你的字节大批。
请参阅 Read() 文档。这就是为什么 Read() 方法采用 int 而不是 long 作为偏移量的原因,因为偏移量是针对数组缓冲区的,而不是对于文件。
我正在尝试制作一个程序来跟踪文本文件列表中的更改(仅附加类型的更改)。使用 FileStream class 我遇到 ArgumentException 告诉“偏移量和长度超出数组范围或计数大于从索引到源集合末尾的元素数”。 另外,我很惊讶地发现我不能使用 long 来标记偏移量——那么我该如何读取巨型文件呢? PS: 肯定不会有大量的新文本。
public partial class mainForm : Form
{
FileSummary initialSnap;
public mainForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
filePath_textBox.Text = openFileDialog1.FileName;
}
}
private void checkButton_Click(object sender, EventArgs e)
{
if (initialSnap == null)
{
initialSnap = new FileSummary(filePath_textBox.Text);
return;
}
FileSummary newSnap = new FileSummary(initialSnap.FullName);
var dateBefore = initialSnap.LastWriteTime;
var dateAfter = newSnap.LastWriteTime;
if (dateBefore == dateAfter) return;
var deltaLength = newSnap.Length - initialSnap.Length;
var prevLength = (int)initialSnap.Length;
using (FileStream fstream = File.OpenRead(initialSnap.FullName))
{
byte[] array = new byte[deltaLength];
fstream.Read(array, prevLength, array.Length);
string addedText = System.Text.Encoding.Default.GetString(array);
}
}
}
internal class FileSummary
{
public FileSummary(string fileFullPath)
{
FullName = fileFullPath;
FileInfo fi = new FileInfo(fileFullPath);
LastWriteTime = fi.LastWriteTime;
Length = fi.Length;
}
public string FullName { get; internal set; }
public DateTime LastWriteTime { get; internal set; }
public long Length { get; private set; }
}
您的代码中对 fstream.Read() 的调用不正确。 Read方法的第二个参数是文件内容放置的目标字节数组的偏移量,它不是你误解的文件中的起始偏移点。
这一行导致了错误,
fstream.Read(array, prevLength, array.Length);
必须改为,
fstream.Seek(prevLength , SeekOrigin.Begin);
fstream.Read(array, 0, array.Length);
所以,如果你只需要获取新写入文件的部分,你需要先seek
到之前的结束位置读取增量文件内容,然后填写你的字节大批。
请参阅 Read() 文档。这就是为什么 Read() 方法采用 int 而不是 long 作为偏移量的原因,因为偏移量是针对数组缓冲区的,而不是对于文件。