C# 在C中向后读取大文件(从头到尾)#
我有一个包含一系列价格数据的文本文件。 这个问题可以匹配任何历史数据的长期历史,如温度、空气湿度、价格、日志文件等 “我的历史记录”文件的标题如下所示:C# 在C中向后读取大文件(从头到尾)#,c#,file,bigdata,streamreader,C#,File,Bigdata,Streamreader,我有一个包含一系列价格数据的文本文件。 这个问题可以匹配任何历史数据的长期历史,如温度、空气湿度、价格、日志文件等 “我的历史记录”文件的标题如下所示: 如果我想读取和处理内存太大的文件,我通常会选择以下代码: using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) using (BufferedStream bs = new BufferedStream(fs))
如果我想读取和处理内存太大的文件,我通常会选择以下代码:
using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (BufferedStream bs = new BufferedStream(fs))
using (StreamReader sr = new StreamReader(bs))
{
string line;
while ((line = sr.ReadLine()) != null)
{
// Process Data
}
}
在我的例子中,每1000毫秒创建一个记录。最新数据位于文件末尾。
在尝试处理最新数据时会出现问题
示例:我希望生成过去30天的平均值。
最有效的方法是从文件末尾开始,然后移到开头,直到达到X天阈值。 上面的示例代码将读取整个文件,在这种情况下几乎不可用。每次我需要更新最新的数据指标时都会出现最坏的情况。 当然,这个问题适用于您想要处理最后x元素的任何操作
是否有从文件的末尾到开头读取的功能 您可以使用Seek转到文件的结尾,但是您需要“猜测”或计算距离结尾有多远。。。例如,要读取最后1024个字节:
stream.Seek(-1024, SeekOrigin.End);
只需计算出最后30行的最大字节数,并查找到文件末尾之前的最大字节数,然后只读取文件的该部分,然后尝试以下代码。最后一行可以是空的。不确定处理最后一行为空的最佳方式
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace GetFileReverse
{
class Program
{
const string FILENAME = @"c:\temp\test.txt";
static void Main(string[] args)
{
GetFileReverse getFileReverse = new GetFileReverse(FILENAME);
string line = "";
while ((line = getFileReverse.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
}
public class GetFileReverse : IDisposable
{
const int BUFFER_SIZE = 1024;
private FileStream stream { get; set; }
private string data { get; set; }
public Boolean SOF { get; set; }
private long position { get; set; }
public GetFileReverse(string filename)
{
stream = File.OpenRead(filename);
if (stream != null)
{
position = stream.Seek(0, SeekOrigin.End);
SOF = false;
data = string.Empty;
}
else
{
SOF = true;
}
}
private byte[] ReadStream()
{
byte[] bytes = null;
int size = BUFFER_SIZE;
if (position != 0)
{
bytes = new byte[BUFFER_SIZE];
long oldPosition = position;
if (position >= BUFFER_SIZE)
{
position = stream.Seek(-1 * BUFFER_SIZE, SeekOrigin.Current);
}
else
{
position = stream.Seek(-1 * position, SeekOrigin.Current);
size = (int)(oldPosition - position);
bytes = new byte[size];
}
stream.Read(bytes, 0, size);
stream.Seek(-1 * size, SeekOrigin.Current);
}
return bytes;
}
public string ReadLine()
{
string line = "";
while (!SOF && (!data.Contains("\r\n")))
{
byte[] bytes = ReadStream();
if (bytes != null)
{
string temp = Encoding.UTF8.GetString(bytes);
data = data.Insert(0, temp);
}
SOF = position == 0;
}
int lastReturn = data.LastIndexOf("\r\n");
if (lastReturn == -1)
{
if (data.Length > 0)
{
line = data;
data = string.Empty;
}
else
{
line = null;
}
}
else
{
line = data.Substring(lastReturn + 2);
data = data.Remove(lastReturn);
}
return line;
}
public void Close()
{
stream.Close();
}
public void Dispose()
{
stream.Dispose();
data = string.Empty;
position = -1;
}
}
}
如果我理解正确的话,我会做
Filestream fs=…
然后fs.Seek(x)
然后像往常一样sr.ReadLine()?是的,但正如我提到的,您需要计算正确的值,然后传递到Seek(),才能到达您想要开始阅读的地方谢谢您。如果(行==“”)继续,它将与添加的一起工作
但不幸的是,尽管我调用了getFileReverse.Close()
和getFileReverse.Dispose()
文件似乎被锁定了您是否使用了我的最新代码?在我首次发布后做了一些改进。如果代码挂起,则使用VS菜单Debug:BreakAll查找挂起的位置。如果文件没有同时包含“\r\n”或编码为unicode,则代码可能无法工作。我做了很多调试。我可能没有正确处理像大于而不是大于等于(或小于)这样的边界条件。与其在using语句中处理包装,不如更好地处理:使用(GetFileReverse GetFileReverse=new GetFileReverse(FILENAME)){在此处输入代码}嘿,谢谢你的代码。太棒了!不幸的是,我的问题被标记为已回答,即使另一个线程没有为我的问题提供有效的答案。