You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

89 lines
2.5 KiB

  1. using System.IO;
  2. using System.Text.RegularExpressions;
  3. namespace Swift.web.Library
  4. {
  5. public sealed class CsvReader : System.IDisposable
  6. {
  7. public CsvReader(string fileName)
  8. : this(new FileStream(fileName, FileMode.Open, FileAccess.Read))
  9. {
  10. }
  11. public CsvReader(Stream stream)
  12. {
  13. __reader = new StreamReader(stream);
  14. }
  15. public System.Collections.IEnumerable RowEnumerator
  16. {
  17. get
  18. {
  19. if (null == __reader)
  20. throw new System.ApplicationException("I can't start reading without CSV input.");
  21. __rowno = 0;
  22. string sLine;
  23. string sNextLine;
  24. while (null != (sLine = __reader.ReadLine()))
  25. {
  26. while (rexRunOnLine.IsMatch(sLine) && null != (sNextLine = __reader.ReadLine()))
  27. sLine += "\n" + sNextLine;
  28. __rowno++;
  29. string[] values = rexCsvSplitter.Split(sLine);
  30. for (int i = 0; i < values.Length; i++)
  31. values[i] = Csv.Unescape(values[i]);
  32. yield return values;
  33. }
  34. __reader.Close();
  35. }
  36. }
  37. public long RowIndex { get { return __rowno; } }
  38. public void Dispose()
  39. {
  40. if (null != __reader) __reader.Dispose();
  41. }
  42. private long __rowno = 0;
  43. private TextReader __reader;
  44. private static Regex rexCsvSplitter = new Regex(@",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))");
  45. private static Regex rexRunOnLine = new Regex(@"^[^""]*(?:""[^""]*""[^""]*)*""[^""]*$");
  46. }
  47. public static class Csv
  48. {
  49. public static string Escape(string s)
  50. {
  51. if (s.Contains(QUOTE))
  52. s = s.Replace(QUOTE, ESCAPED_QUOTE);
  53. if (s.IndexOfAny(CHARACTERS_THAT_MUST_BE_QUOTED) > -1)
  54. s = QUOTE + s + QUOTE;
  55. return s;
  56. }
  57. public static string Unescape(string s)
  58. {
  59. if (s.StartsWith(QUOTE) && s.EndsWith(QUOTE))
  60. {
  61. s = s.Substring(1, s.Length - 2);
  62. if (s.Contains(ESCAPED_QUOTE))
  63. s = s.Replace(ESCAPED_QUOTE, QUOTE);
  64. }
  65. return s;
  66. }
  67. private const string QUOTE = "\"";
  68. private const string ESCAPED_QUOTE = "\"\"";
  69. private static char[] CHARACTERS_THAT_MUST_BE_QUOTED = { ',', '"', '\n' };
  70. }
  71. }