/BOFC/PartialFileRead.cs
# · C# · 433 lines · 302 code · 100 blank · 31 comment · 50 complexity · 6c8742f955bebb7a0fc5fcc048fa63ec MD5 · raw file
- using System;
- using System.IO;
- using System.Text;
-
- namespace BOF
- {
- public enum LinesPercentage
- {
- Lines = 0,
- Percentage
- }
-
- public enum ReadType
- {
- Start = 0,
- Middle,
- End
- }
-
- public class PartialFileRead
- {
- #region Fields and Properties
-
- public string FileName { get; set; }
-
- public FileInfo FileInfo { get; private set; }
-
- public ReadType ReadType { get; set; }
-
- public long Lines { get; set; }
-
- public long ReadChars { get; private set; }
-
- public string ReadLines { get; private set; }
-
- public LinesPercentage LinesOrPercentage { get; set; }
-
- public bool DoTabs { get; set; }
-
- public long StartLine { get; set; }
-
- public long EndLine { get; set; }
-
- public string LineTerminator
- {
- get { return GetLineTerminator(); }
- }
-
- public string HeaderLine { get; private set; }
-
- public bool HasHeader { get; private set; }
-
- public string FooterLine { get; private set; }
-
- public bool HasFooter { get; private set; }
-
- #endregion
-
- #region Events
-
- public event ReadFileProgressChangedEventHandler ReadProgress;
- public event FileReadEventHandler FileRead;
-
- #endregion
-
- #region Constructor
-
- public PartialFileRead()
- {
- FileName = string.Empty;
- ReadType = ReadType.Start;
- Lines = 10;
- ReadChars = 0;
- ReadLines = string.Empty;
- LinesOrPercentage = LinesPercentage.Lines;
- DoTabs = false;
- StartLine = 0;
- EndLine = 0;
- }
-
- #endregion
-
- public string ReadFile()
- {
- //reset variables
- ReadChars = 0;
- ReadLines = string.Empty;
- HasFooter = false;
- FooterLine = string.Empty;
- HasHeader = false;
- HeaderLine = string.Empty;
-
- switch (ReadType)
- {
- case ReadType.Start:
- ReadFileStart();
- break;
-
- case ReadType.Middle:
- ReadFileMiddle();
- break;
-
- case ReadType.End:
- ReadFileEnd();
- break;
-
- default:
- break;
- }
-
- CheckForHeaderAndFooter();
-
- OnFileRead();
-
- return ReadLines;
- }
-
- /// <summary>
- /// Crude guesstimate at the existence of a header or footer record.
- /// Based if line length less half of normal line, or if 2/3rds are non-numeric
- /// </summary>
- private void CheckForHeaderAndFooter()
- {
- //checks for header/footer in *read* text, not much use
- //string[] lines = ReadLines.Split('\n');
-
- //if (lines[0].Length < lines[1].Length / 2)
- // HasHeader = true;
- //else
- // HasHeader = false;
-
- ////there's an blank line at the end we need to ignore
- //if (lines[lines.Length - 2].Length < lines[lines.Length - 3].Length / 2)
- // HasFooter = true;
- //else
- // HasFooter = false;
-
-
- //header check, read first 2 lines
- using (StreamReader sr = FileInfo.OpenText())
- {
- string line1 = sr.ReadLine();
- string line2 = sr.ReadLine();
-
- if (line2 != null
- && line1.Length < line2.Length / 2
- || !(System.Text.RegularExpressions.Regex.Matches(line1, "[0-9]").Count > line1.Length / 3))
- {
- HasHeader = true;
- HeaderLine = line1;
- }
- }
-
- //footer check, read last 2 lines
- using (StreamReader sr = new StreamReader(FileInfo.FullName, true))
- {
- long len = sr.BaseStream.Length;
- int[] rb = new int[2];
-
- //skip trailing line terminators
- do
- {
- len -= 2;
- sr.BaseStream.Seek(len, SeekOrigin.Begin);
- rb[1] = sr.BaseStream.ReadByte();
- rb[0] = sr.BaseStream.ReadByte();
- } while (rb[0] == 10 && rb[1] == 13);
-
- //go back _lines lines
- int b = 0;
- for (int i = 0; i < 3 - 1; i++)
- {
- do
- {
- len -= 1;
- try
- {
- sr.BaseStream.Seek(len, SeekOrigin.Begin);
- b = sr.BaseStream.ReadByte();
- }
- catch (IOException ex)
- {
- Console.WriteLine(ex.Message);
-
- //more lines asked for than in file
- //move to beginning
- sr.BaseStream.Seek(0, SeekOrigin.Begin);
- }
- } while (b != 10 && len > 0);
-
- }
-
- string line1 = sr.ReadLine();
- string line2 = sr.ReadLine();
-
- if (line2.Length < line1.Length / 2 ||
- !(System.Text.RegularExpressions.Regex.Matches(line1, "[0-9]").Count > line1.Length / 3))
- {
- HasFooter = true;
- FooterLine = line2;
- }
- }
- }
-
- private string GetLineTerminator()
- {
- FileInfo = new FileInfo(FileName);
-
- if (!FileInfo.Exists)
- throw new ApplicationException(FileInfo.Name + " not found!");
-
- byte[] b = new byte[2];
-
- //open file stream
- using (FileStream fs = FileInfo.Open(FileMode.Open, FileAccess.Read))
- {
- //read 2 bytes from end of file into b
- fs.Seek(-2, SeekOrigin.End);
- fs.Read(b, 0, 2);
- }
-
- return b[0].ToString() + ", " + b[1].ToString();
- }
-
- private void ReadFileStart()
- {
- FileInfo = new FileInfo(FileName);
-
- if (!FileInfo.Exists)
- throw new ApplicationException(FileInfo.Name + " not found!");
-
- long i = 0;
- string line;
- StringBuilder sb = new StringBuilder();
-
- using (StreamReader sr = FileInfo.OpenText())
- {
- switch (LinesOrPercentage)
- {
- case LinesPercentage.Lines:
- while ((i < Lines) && !sr.EndOfStream)
- {
- line = sr.ReadLine();
- ReadChars += line.Length;
-
- if (DoTabs)
- line = line.Replace(',', '\t');
-
- sb.AppendLine(line);
-
- i++;
- OnReadFileProgress(i, Lines);
- }
- break;
-
- case LinesPercentage.Percentage:
- double percent = FileInfo.Length * (Lines / 100);
-
- while (ReadChars <= percent && !sr.EndOfStream)
- {
- line = sr.ReadLine();
- ReadChars += line.Length;
-
- if (DoTabs)
- line = line.Replace(',', '\t');
-
- sb.AppendLine(line);
-
- i++;
- OnReadFileProgress(ReadChars, (long) percent);
- }
- break;
- }
- }
-
- ReadLines = sb.ToString();
- }
-
- private void ReadFileMiddle()
- {
- FileInfo = new FileInfo(FileName);
-
- if (!FileInfo.Exists)
- throw new ApplicationException(FileInfo.Name + " not found!");
-
- if (StartLine <= 0)
- StartLine = 1;
-
- if (EndLine <= StartLine)
- EndLine = StartLine + 1;
-
- string line;
- long i = 0;
- StringBuilder sb = new StringBuilder();
-
- using (StreamReader sr = FileInfo.OpenText())
- {
- //skip the first lines
- while (i < (StartLine - 1) && !sr.EndOfStream)
- {
- sr.ReadLine();
- i++;
- OnReadFileProgress(i, StartLine);
- }
-
- while (i < EndLine && !sr.EndOfStream)
- {
- line = sr.ReadLine();
-
- ReadChars += line.Length;
-
- if (DoTabs)
- line = line.Replace(',', '\t');
-
- sb.AppendLine(line);
-
- i++;
- OnReadFileProgress(i, EndLine);
- }
- }
-
- ReadLines = sb.ToString();
- }
-
- private void ReadFileEnd()
- {
- FileInfo = new FileInfo(FileName);
-
- if (!FileInfo.Exists)
- throw new ApplicationException(FileInfo.Name + " not found!");
-
- StringBuilder sb = new StringBuilder();
-
- using (StreamReader sr = new StreamReader(FileInfo.FullName, true))
- {
- long len = sr.BaseStream.Length;
- int[] rb = new int[2];
-
- //skip trailing line terminators
- do
- {
- len -= 2;
- sr.BaseStream.Seek(len, SeekOrigin.Begin);
- rb[1] = sr.BaseStream.ReadByte();
- rb[0] = sr.BaseStream.ReadByte();
- } while (rb[0] == 10 && rb[1] == 13);
-
- //go back _lines lines
- int b = 0;
- for (int i = 0; i < Lines - 1; i++)
- {
- do
- {
- len -= 1;
- try
- {
- sr.BaseStream.Seek(len, SeekOrigin.Begin);
- b = sr.BaseStream.ReadByte();
- }
- catch (IOException ex)
- {
- Console.WriteLine(ex.Message);
-
- //more lines asked for than in file
- //move to beginning
- sr.BaseStream.Seek(0, SeekOrigin.Begin);
- }
- } while (b != 10 && len > 0);
-
- OnReadFileProgress(i, Lines);
- }
-
- string line = string.Empty;
- do
- {
- line = sr.ReadLine();
-
- if (DoTabs)
- line = line.Replace(',', '\t');
-
- sb.AppendLine(line);
- } while (!String.IsNullOrEmpty(line) && !sr.EndOfStream);
- }
-
- ReadLines = sb.ToString();
- }
-
- #region Event Firers
-
- private void OnReadFileProgress(long progress, long total)
- {
- // if we have subscribers...fire
- if (ReadProgress != null)
- {
- int perc;
-
- if (total == 0)
- total = 1;
-
- if (progress > total)
- perc = 100;
- else
- perc = (int) ((decimal) progress / total * 100);
-
- ReadProgress(this, new ReadProgressEventArgs(perc));
- }
- }
-
- private void OnFileRead()
- {
- // if we have subscribers...fire
- if (FileRead != null)
- FileRead(this, new EventArgs());
- }
-
- #endregion
- }
-
- public delegate void FileReadEventHandler(object sender, EventArgs e);
-
- public delegate void ReadFileProgressChangedEventHandler(object sender, ReadProgressEventArgs e);
-
- public class ReadProgressEventArgs : EventArgs
- {
- public int Percentage;
-
- public ReadProgressEventArgs(int percentage)
- {
- this.Percentage = percentage;
- }
- }
-
- }