Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>There are two parts to the solution. For the first part, you need to read the memory map backwards to grab lines, until you have read the number of lines you want (20 in this case).</p> <p>For the second part, you want to truncate the file by the last twenty lines (by setting them to string.Empty). I'm not sure if you can do this with a memory map. <strike>You may have to make a copy of the file somewhere and overwrite the original with the source data except the last xxx bytes (which represents the last twenty lines)</strike></p> <p>The code below will extract the last twenty lines and display it.</p> <p>You'll also get the position (<strong>lastBytePos</strong> variable) where the last twenty lines begin. You can use that information to know where to truncate the file.</p> <p><em><strong>UPDATE:</strong> To truncate the file call <a href="http://msdn.microsoft.com/en-us/library/system.io.filestream.setlength.aspx" rel="nofollow">FileStream.SetLength</a>(lastBytePos)</em></p> <p>I wasn't sure what you meant by the last 20 lines are bad. In case the disk is physically corrupt and the data cannot be read, I've added a <strong>badPositions</strong> list that holds the positions where the memorymap had problems reading the data.</p> <p>I don't have a +2GB file to test with, but it should work (fingers crossed).</p> <pre><code>using System; using System.Collections.Generic; using System.Text; using System.IO.MemoryMappedFiles; using System.IO; namespace ConsoleApplication { class Program { static void Main(string[] args) { string filename = "textfile1.txt"; long fileLen = new FileInfo(filename).Length; List&lt;long&gt; badPositions = new List&lt;long&gt;(); List&lt;byte&gt; currentLine = new List&lt;byte&gt;(); List&lt;string&gt; lines = new List&lt;string&gt;(); bool lastReadByteWasLF = false; int linesToRead = 20; int linesRead = 0; long lastBytePos = fileLen; MemoryMappedFile mapFile = MemoryMappedFile.CreateFromFile(filename, FileMode.Open); using (mapFile) { var view = mapFile.CreateViewAccessor(); for (long i = fileLen - 1; i &gt;= 0; i--) //iterate backwards { try { byte b = view.ReadByte(i); lastBytePos = i; switch (b) { case 13: //CR if (lastReadByteWasLF) { { //A line has been read var bArray = currentLine.ToArray(); if (bArray.LongLength &gt; 1) { //Add line string to lines collection lines.Insert(0, Encoding.UTF8.GetString(bArray, 1, bArray.Length - 1)); //Clear current line list currentLine.Clear(); //Add CRLF to currentLine -- comment this out if you don't want CRLFs in lines currentLine.Add(13); currentLine.Add(10); linesRead++; } } } lastReadByteWasLF = false; break; case 10: //LF lastReadByteWasLF = true; currentLine.Insert(0, b); break; default: lastReadByteWasLF = false; currentLine.Insert(0, b); break; } if (linesToRead == linesRead) { break; } } catch { lastReadByteWasLF = false; currentLine.Insert(0, (byte) '?'); badPositions.Insert(0, i); } } } if (linesToRead &gt; linesRead) { //Read last line { var bArray = currentLine.ToArray(); if (bArray.LongLength &gt; 1) { //Add line string to lines collection lines.Insert(0, Encoding.UTF8.GetString(bArray)); linesRead++; } } } //Print results lines.ForEach( o =&gt; Console.WriteLine(o)); Console.ReadKey(); } } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload