PageRenderTime 154ms CodeModel.GetById 29ms RepoModel.GetById 26ms app.codeStats 0ms

/BOFC/PartialFileRead.cs

#
C# | 433 lines | 302 code | 100 blank | 31 comment | 50 complexity | 6c8742f955bebb7a0fc5fcc048fa63ec MD5 | raw file
  1. using System;
  2. using System.IO;
  3. using System.Text;
  4. namespace BOF
  5. {
  6. public enum LinesPercentage
  7. {
  8. Lines = 0,
  9. Percentage
  10. }
  11. public enum ReadType
  12. {
  13. Start = 0,
  14. Middle,
  15. End
  16. }
  17. public class PartialFileRead
  18. {
  19. #region Fields and Properties
  20. public string FileName { get; set; }
  21. public FileInfo FileInfo { get; private set; }
  22. public ReadType ReadType { get; set; }
  23. public long Lines { get; set; }
  24. public long ReadChars { get; private set; }
  25. public string ReadLines { get; private set; }
  26. public LinesPercentage LinesOrPercentage { get; set; }
  27. public bool DoTabs { get; set; }
  28. public long StartLine { get; set; }
  29. public long EndLine { get; set; }
  30. public string LineTerminator
  31. {
  32. get { return GetLineTerminator(); }
  33. }
  34. public string HeaderLine { get; private set; }
  35. public bool HasHeader { get; private set; }
  36. public string FooterLine { get; private set; }
  37. public bool HasFooter { get; private set; }
  38. #endregion
  39. #region Events
  40. public event ReadFileProgressChangedEventHandler ReadProgress;
  41. public event FileReadEventHandler FileRead;
  42. #endregion
  43. #region Constructor
  44. public PartialFileRead()
  45. {
  46. FileName = string.Empty;
  47. ReadType = ReadType.Start;
  48. Lines = 10;
  49. ReadChars = 0;
  50. ReadLines = string.Empty;
  51. LinesOrPercentage = LinesPercentage.Lines;
  52. DoTabs = false;
  53. StartLine = 0;
  54. EndLine = 0;
  55. }
  56. #endregion
  57. public string ReadFile()
  58. {
  59. //reset variables
  60. ReadChars = 0;
  61. ReadLines = string.Empty;
  62. HasFooter = false;
  63. FooterLine = string.Empty;
  64. HasHeader = false;
  65. HeaderLine = string.Empty;
  66. switch (ReadType)
  67. {
  68. case ReadType.Start:
  69. ReadFileStart();
  70. break;
  71. case ReadType.Middle:
  72. ReadFileMiddle();
  73. break;
  74. case ReadType.End:
  75. ReadFileEnd();
  76. break;
  77. default:
  78. break;
  79. }
  80. CheckForHeaderAndFooter();
  81. OnFileRead();
  82. return ReadLines;
  83. }
  84. /// <summary>
  85. /// Crude guesstimate at the existence of a header or footer record.
  86. /// Based if line length less half of normal line, or if 2/3rds are non-numeric
  87. /// </summary>
  88. private void CheckForHeaderAndFooter()
  89. {
  90. //checks for header/footer in *read* text, not much use
  91. //string[] lines = ReadLines.Split('\n');
  92. //if (lines[0].Length < lines[1].Length / 2)
  93. // HasHeader = true;
  94. //else
  95. // HasHeader = false;
  96. ////there's an blank line at the end we need to ignore
  97. //if (lines[lines.Length - 2].Length < lines[lines.Length - 3].Length / 2)
  98. // HasFooter = true;
  99. //else
  100. // HasFooter = false;
  101. //header check, read first 2 lines
  102. using (StreamReader sr = FileInfo.OpenText())
  103. {
  104. string line1 = sr.ReadLine();
  105. string line2 = sr.ReadLine();
  106. if (line2 != null
  107. && line1.Length < line2.Length / 2
  108. || !(System.Text.RegularExpressions.Regex.Matches(line1, "[0-9]").Count > line1.Length / 3))
  109. {
  110. HasHeader = true;
  111. HeaderLine = line1;
  112. }
  113. }
  114. //footer check, read last 2 lines
  115. using (StreamReader sr = new StreamReader(FileInfo.FullName, true))
  116. {
  117. long len = sr.BaseStream.Length;
  118. int[] rb = new int[2];
  119. //skip trailing line terminators
  120. do
  121. {
  122. len -= 2;
  123. sr.BaseStream.Seek(len, SeekOrigin.Begin);
  124. rb[1] = sr.BaseStream.ReadByte();
  125. rb[0] = sr.BaseStream.ReadByte();
  126. } while (rb[0] == 10 && rb[1] == 13);
  127. //go back _lines lines
  128. int b = 0;
  129. for (int i = 0; i < 3 - 1; i++)
  130. {
  131. do
  132. {
  133. len -= 1;
  134. try
  135. {
  136. sr.BaseStream.Seek(len, SeekOrigin.Begin);
  137. b = sr.BaseStream.ReadByte();
  138. }
  139. catch (IOException ex)
  140. {
  141. Console.WriteLine(ex.Message);
  142. //more lines asked for than in file
  143. //move to beginning
  144. sr.BaseStream.Seek(0, SeekOrigin.Begin);
  145. }
  146. } while (b != 10 && len > 0);
  147. }
  148. string line1 = sr.ReadLine();
  149. string line2 = sr.ReadLine();
  150. if (line2.Length < line1.Length / 2 ||
  151. !(System.Text.RegularExpressions.Regex.Matches(line1, "[0-9]").Count > line1.Length / 3))
  152. {
  153. HasFooter = true;
  154. FooterLine = line2;
  155. }
  156. }
  157. }
  158. private string GetLineTerminator()
  159. {
  160. FileInfo = new FileInfo(FileName);
  161. if (!FileInfo.Exists)
  162. throw new ApplicationException(FileInfo.Name + " not found!");
  163. byte[] b = new byte[2];
  164. //open file stream
  165. using (FileStream fs = FileInfo.Open(FileMode.Open, FileAccess.Read))
  166. {
  167. //read 2 bytes from end of file into b
  168. fs.Seek(-2, SeekOrigin.End);
  169. fs.Read(b, 0, 2);
  170. }
  171. return b[0].ToString() + ", " + b[1].ToString();
  172. }
  173. private void ReadFileStart()
  174. {
  175. FileInfo = new FileInfo(FileName);
  176. if (!FileInfo.Exists)
  177. throw new ApplicationException(FileInfo.Name + " not found!");
  178. long i = 0;
  179. string line;
  180. StringBuilder sb = new StringBuilder();
  181. using (StreamReader sr = FileInfo.OpenText())
  182. {
  183. switch (LinesOrPercentage)
  184. {
  185. case LinesPercentage.Lines:
  186. while ((i < Lines) && !sr.EndOfStream)
  187. {
  188. line = sr.ReadLine();
  189. ReadChars += line.Length;
  190. if (DoTabs)
  191. line = line.Replace(',', '\t');
  192. sb.AppendLine(line);
  193. i++;
  194. OnReadFileProgress(i, Lines);
  195. }
  196. break;
  197. case LinesPercentage.Percentage:
  198. double percent = FileInfo.Length * (Lines / 100);
  199. while (ReadChars <= percent && !sr.EndOfStream)
  200. {
  201. line = sr.ReadLine();
  202. ReadChars += line.Length;
  203. if (DoTabs)
  204. line = line.Replace(',', '\t');
  205. sb.AppendLine(line);
  206. i++;
  207. OnReadFileProgress(ReadChars, (long) percent);
  208. }
  209. break;
  210. }
  211. }
  212. ReadLines = sb.ToString();
  213. }
  214. private void ReadFileMiddle()
  215. {
  216. FileInfo = new FileInfo(FileName);
  217. if (!FileInfo.Exists)
  218. throw new ApplicationException(FileInfo.Name + " not found!");
  219. if (StartLine <= 0)
  220. StartLine = 1;
  221. if (EndLine <= StartLine)
  222. EndLine = StartLine + 1;
  223. string line;
  224. long i = 0;
  225. StringBuilder sb = new StringBuilder();
  226. using (StreamReader sr = FileInfo.OpenText())
  227. {
  228. //skip the first lines
  229. while (i < (StartLine - 1) && !sr.EndOfStream)
  230. {
  231. sr.ReadLine();
  232. i++;
  233. OnReadFileProgress(i, StartLine);
  234. }
  235. while (i < EndLine && !sr.EndOfStream)
  236. {
  237. line = sr.ReadLine();
  238. ReadChars += line.Length;
  239. if (DoTabs)
  240. line = line.Replace(',', '\t');
  241. sb.AppendLine(line);
  242. i++;
  243. OnReadFileProgress(i, EndLine);
  244. }
  245. }
  246. ReadLines = sb.ToString();
  247. }
  248. private void ReadFileEnd()
  249. {
  250. FileInfo = new FileInfo(FileName);
  251. if (!FileInfo.Exists)
  252. throw new ApplicationException(FileInfo.Name + " not found!");
  253. StringBuilder sb = new StringBuilder();
  254. using (StreamReader sr = new StreamReader(FileInfo.FullName, true))
  255. {
  256. long len = sr.BaseStream.Length;
  257. int[] rb = new int[2];
  258. //skip trailing line terminators
  259. do
  260. {
  261. len -= 2;
  262. sr.BaseStream.Seek(len, SeekOrigin.Begin);
  263. rb[1] = sr.BaseStream.ReadByte();
  264. rb[0] = sr.BaseStream.ReadByte();
  265. } while (rb[0] == 10 && rb[1] == 13);
  266. //go back _lines lines
  267. int b = 0;
  268. for (int i = 0; i < Lines - 1; i++)
  269. {
  270. do
  271. {
  272. len -= 1;
  273. try
  274. {
  275. sr.BaseStream.Seek(len, SeekOrigin.Begin);
  276. b = sr.BaseStream.ReadByte();
  277. }
  278. catch (IOException ex)
  279. {
  280. Console.WriteLine(ex.Message);
  281. //more lines asked for than in file
  282. //move to beginning
  283. sr.BaseStream.Seek(0, SeekOrigin.Begin);
  284. }
  285. } while (b != 10 && len > 0);
  286. OnReadFileProgress(i, Lines);
  287. }
  288. string line = string.Empty;
  289. do
  290. {
  291. line = sr.ReadLine();
  292. if (DoTabs)
  293. line = line.Replace(',', '\t');
  294. sb.AppendLine(line);
  295. } while (!String.IsNullOrEmpty(line) && !sr.EndOfStream);
  296. }
  297. ReadLines = sb.ToString();
  298. }
  299. #region Event Firers
  300. private void OnReadFileProgress(long progress, long total)
  301. {
  302. // if we have subscribers...fire
  303. if (ReadProgress != null)
  304. {
  305. int perc;
  306. if (total == 0)
  307. total = 1;
  308. if (progress > total)
  309. perc = 100;
  310. else
  311. perc = (int) ((decimal) progress / total * 100);
  312. ReadProgress(this, new ReadProgressEventArgs(perc));
  313. }
  314. }
  315. private void OnFileRead()
  316. {
  317. // if we have subscribers...fire
  318. if (FileRead != null)
  319. FileRead(this, new EventArgs());
  320. }
  321. #endregion
  322. }
  323. public delegate void FileReadEventHandler(object sender, EventArgs e);
  324. public delegate void ReadFileProgressChangedEventHandler(object sender, ReadProgressEventArgs e);
  325. public class ReadProgressEventArgs : EventArgs
  326. {
  327. public int Percentage;
  328. public ReadProgressEventArgs(int percentage)
  329. {
  330. this.Percentage = percentage;
  331. }
  332. }
  333. }