/// <summary> /// Start to read /// </summary> /// <param name="offset">How many rows to read</param> /// <param name="toward">If start from begin or end of file</param> /// <param name="visualizationType">Set Visualization type</param> /// <returns></returns> public TextInfo Read(int offset, OffsetTowards toward, VisulaziationType visualizationType) { switch (visualizationType) { case VisulaziationType.Rows: return(ReadRows(offset, toward)); } return(new TextInfo()); }
private TextInfo ReadRows(int offset, OffsetTowards toward) { TextInfo result = new TextInfo(); /*no lines to read*/ if (offset == 0) { return(result); } using (FileStream fs = new FileStream(FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 2048, true)) { List <char> charBuilder = new List <char>(); /*StringBuilder doesn't work with Encoding: example char 𐍈 */ StringBuilder sb = new StringBuilder(); Stopwatch stopWatch = new Stopwatch(); int count = 0; switch (toward) { case OffsetTowards.Downwards: { /*tested with utf8 file encoded by notepad-pp; other encoding may not work*/ stopWatch.Start(); var decoder = ReaderEncoding.GetDecoder(); byte[] buffer; int bufferLength; fs.Seek(0, SeekOrigin.End); while (true) { bufferLength = 1; buffer = new byte[1]; /*for variable byte dimension encoding, everytime i read a byte that is * a part of character and not whole character the decoder return '�' (invalid character) */ char[] chars = { '�' }; //� 65533 int iteration = 0; while (chars.Contains('�')) { /*at every iteration that does not produce character, buffer get bigger, up to 4 byte*/ if (iteration > 0) { bufferLength = buffer.Length + 1; byte[] newBuffer = new byte[bufferLength]; Array.Copy(buffer, newBuffer, bufferLength - 1); buffer = newBuffer; } /*there are no characters with more than 4 bytes in utf-8*/ if (iteration > 4) { stopWatch.Stop(); result.TimeOfRead = stopWatch.Elapsed; throw new Exception(); } /*if all is ok, the last seek return IOError with chars = empty*/ try { fs.Seek(-(bufferLength), SeekOrigin.Current); } catch { chars = new char[] { '\0' }; break; } fs.Read(buffer, 0, bufferLength); var charCount = decoder.GetCharCount(buffer, 0, bufferLength); chars = new char[charCount]; decoder.GetChars(buffer, 0, bufferLength, chars, 0); ++iteration; } /*when i get a char*/ charBuilder.InsertRange(0, chars); if (chars.Length > 0 && chars[0] == '\n') { ++count; } /*exit when i get the correctly number of line (*last row is in interval)*/ if (count == offset) { break; } /*the first search goes back, the reading goes on then we come back again, except the last */ try { fs.Seek(-(bufferLength), SeekOrigin.Current); } catch (Exception) { break; } } stopWatch.Stop(); /*everithing must be reversed, but not \0*/ charBuilder.RemoveAt(0); /*yuppi!*/ result.Text = new string(charBuilder.ToArray()); result.TimeOfRead = stopWatch.Elapsed; break; } case OffsetTowards.Upwards: { using (StreamReader sr = new StreamReader(fs, ReaderEncoding)) { string line; stopWatch.Start(); while ((line = sr.ReadLine()) != null) { sb.AppendLine(line); if (++count == offset) { break; } } stopWatch.Stop(); result.Text = sb.ToString(); result.TimeOfRead = stopWatch.Elapsed; break; } } } }/*end outer using*/ return(result); }
public async Task LoadAsync() { /*subfunctions*/ OffsetTowards GetOffset() { OffsetTowards result = OffsetTowards.Unselected; var rdbSelectedButtonFilter = gpbTowards .Controls .OfType <RadioButton>() .Where(r => r.Checked).ToArray(); switch (rdbSelectedButtonFilter.FirstOrDefault()?.Name) { case "rdbFilterFirst": result = OffsetTowards.Upwards; break; case "rdbFilterLast": result = OffsetTowards.Downwards; break; default: break; } return(result); } /*start*/ /*get info by form*/ await Task.Run(() => { var toward = GetOffset(); string offsetText = (toward == OffsetTowards.Upwards) ? tbxFirstRows.Text : tbxLastRows.Text; Int32.TryParse(offsetText, out int offset); /*setting up the down info*/ statusStripEncoding.Items[0].Text = "Encoding: " + _reader.ReaderEncoding.HeaderName; statusStripEncoding.Items[2].Text = "Info: try to change encoding if the file is not utf-8 and the log is empty or unreadable, the backwards read is guaranteed only with utf-8 encoded file."; /*start reading*/ TextInfo result = new TextInfo(); var mainForm = (MainForm)this .Parent .Parent .Parent; /*setting up the last down info*/ mainForm.Invoke(new Action(() => { tsslElaborationTime.Text = "Loading.."; statusStripEncoding.Items[1].Enabled = false; cbxCompatibility.Enabled = false; btnCloseTab.Enabled = false; })); try { result = _reader.Read(offset, toward, VisulaziationType.Rows); mainForm.Invoke(new Action(() => { /*delete \n in Upwords forward*/ result.Text = result.Text.TrimEnd(); if (cbxCompatibility.Checked) { tbxLog.Text = string.Empty; tbxLog.Visible = false; tbxLogCompatibility.Text = result.Text.Replace("\n", Environment.NewLine); } else { tbxLog.Visible = true; tbxLog.Text = result.Text; tbxLog.GoEnd(); tbxLogCompatibility.Text = string.Empty; } })); } /*same encoding of the reader but bad encoded*/ catch { MessageBox.Show("An error occurred during the reading of file: " + mainForm.Invoke(new Func <string>(() => tsslFullName.Text)), "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly); mainForm.Invoke(new Action(() => { tbxLog.Text = string.Empty; tbxLogCompatibility.Text = string.Empty; BtnCloseTab_Click(null, null); })); return; } /*setting up the last down info*/ mainForm.Invoke(new Action(() => { tsslElaborationTime.Text = result.TimeOfRead.TotalSeconds.ToString(); statusStripEncoding.Items[1].Enabled = true; cbxCompatibility.Enabled = true; btnCloseTab.Enabled = true; })); }); }