How to read a text file reversely with iterator in C#

后端 未结 11 2034
甜味超标
甜味超标 2020-11-22 04:05

I need to process a large file, around 400K lines and 200 M. But sometimes I have to process from bottom up. How can I use iterator (yield return) here? Basically I don\'t l

11条回答
  •  执笔经年
    2020-11-22 04:41

    I also add my solution. After reading some answers, nothing really fit to my case. I'm reading byte by byte from from behind until I find a LineFeed, then I'm returing the collected bytes as string, without using buffering.

    Usage:

    var reader = new ReverseTextReader(path);
    while (!reader.EndOfStream)
    {
        Console.WriteLine(reader.ReadLine());  
    }
    

    Implementation:

    public class ReverseTextReader
    {
        private const int LineFeedLf = 10;
        private const int LineFeedCr = 13;
        private readonly Stream _stream;
        private readonly Encoding _encoding;
    
        public bool EndOfStream => _stream.Position == 0;
    
        public ReverseTextReader(Stream stream, Encoding encoding)
        {
            _stream = stream;
            _encoding = encoding;
            _stream.Position = _stream.Length;
        }
    
        public string ReadLine()
        {
            if (_stream.Position == 0) return null;
    
            var line = new List();
            var endOfLine = false;
            while (!endOfLine)
            {
                var b = _stream.ReadByteFromBehind();
    
                if (b == -1 || b == LineFeedLf)
                {
                    endOfLine = true;
                } 
                line.Add(Convert.ToByte(b));
            }
    
            line.Reverse();
            return _encoding.GetString(line.ToArray());
        }
    }
    
    public static class StreamExtensions
    {
        public static int ReadByteFromBehind(this Stream stream)
        {
            if (stream.Position == 0) return -1;
    
            stream.Position = stream.Position - 1;
            var value = stream.ReadByte();
            stream.Position = stream.Position - 1;
            return value;
        }
    }
    

提交回复
热议问题