Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在C中向后读取大文件(从头到尾)#_C#_File_Bigdata_Streamreader - Fatal编程技术网

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)){在此处输入代码}嘿,谢谢你的代码。太棒了!不幸的是,我的问题被标记为已回答,即使另一个线程没有为我的问题提供有效的答案。