码迷,mamicode.com
首页 > Windows程序 > 详细

C# - CSV(Comma-Separated Values)文件读取.

时间:2014-10-21 19:20:07      阅读:366      评论:0      收藏:0      [点我收藏+]

标签:style   blog   color   io   os   ar   for   sp   文件   

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Diagnostics;
  4 using System.IO;
  5 using System.Text;
  6 
  7 namespace CsvFile
  8 {
  9     /// <summary>
 10     /// Determines how empty lines are interpreted when reading CSV files.
 11     /// These values do not affect empty lines that occur within quoted fields
 12     /// or empty lines that appear at the end of the input file.
 13     /// </summary>
 14     public enum EmptyLineBehavior
 15     {
 16         /// <summary>
 17         /// Empty lines are interpreted as a line with zero columns.
 18         /// </summary>
 19         NoColumns,
 20         /// <summary>
 21         /// Empty lines are interpreted as a line with a single empty column.
 22         /// </summary>
 23         EmptyColumn,
 24         /// <summary>
 25         /// Empty lines are skipped over as though they did not exist.
 26         /// </summary>
 27         Ignore,
 28         /// <summary>
 29         /// An empty line is interpreted as the end of the input file.
 30         /// </summary>
 31         EndOfFile,
 32     }
 33 
 34     /// <summary>
 35     /// Common base class for CSV reader and writer classes.
 36     /// </summary>
 37     public abstract class CsvFileCommon
 38     {
 39         /// <summary>
 40         /// These are special characters in CSV files. If a column contains any
 41         /// of these characters, the entire column is wrapped in double quotes.
 42         /// </summary>
 43         protected char[] SpecialChars = new char[] { ,, ", \r, \n };
 44 
 45         // Indexes into SpecialChars for characters with specific meaning
 46         private const int DelimiterIndex = 0;
 47         private const int QuoteIndex = 1;
 48 
 49         /// <summary>
 50         /// Gets/sets the character used for column delimiters.
 51         /// </summary>
 52         public char Delimiter
 53         {
 54             get { return SpecialChars[DelimiterIndex]; }
 55             set { SpecialChars[DelimiterIndex] = value; }
 56         }
 57 
 58         /// <summary>
 59         /// Gets/sets the character used for column quotes.
 60         /// </summary>
 61         public char Quote
 62         {
 63             get { return SpecialChars[QuoteIndex]; }
 64             set { SpecialChars[QuoteIndex] = value; }
 65         }
 66     }
 67 
 68     /// <summary>
 69     /// Class for reading from comma-separated-value (CSV) files
 70     /// </summary>
 71     public class CsvFileReader : CsvFileCommon, IDisposable
 72     {
 73         // Private members
 74         private StreamReader Reader;
 75         private string CurrLine;
 76         private int CurrPos;
 77         private EmptyLineBehavior EmptyLineBehavior;
 78 
 79         /// <summary>
 80         /// Initializes a new instance of the CsvFileReader class for the
 81         /// specified stream.
 82         /// </summary>
 83         /// <param name="stream">The stream to read from</param>
 84         /// <param name="emptyLineBehavior">Determines how empty lines are handled</param>
 85         public CsvFileReader(Stream stream,
 86             EmptyLineBehavior emptyLineBehavior = EmptyLineBehavior.NoColumns)
 87         {
 88             Reader = new StreamReader(stream);
 89             EmptyLineBehavior = emptyLineBehavior;
 90         }
 91 
 92         /// <summary>
 93         /// Initializes a new instance of the CsvFileReader class for the
 94         /// specified file path.
 95         /// </summary>
 96         /// <param name="path">The name of the CSV file to read from</param>
 97         /// <param name="emptyLineBehavior">Determines how empty lines are handled</param>
 98         public CsvFileReader(string path,
 99             EmptyLineBehavior emptyLineBehavior = EmptyLineBehavior.NoColumns)
100         {
101             Reader = new StreamReader(path);
102             EmptyLineBehavior = emptyLineBehavior;
103         }
104 
105         /// <summary>
106         /// Reads a row of columns from the current CSV file. Returns false if no
107         /// more data could be read because the end of the file was reached.
108         /// </summary>
109         /// <param name="columns">Collection to hold the columns read</param>
110         public bool ReadRow(List<string> columns)
111         {
112             // Verify required argument
113             if (columns == null)
114                 throw new ArgumentNullException("columns");
115 
116         ReadNextLine:
117             // Read next line from the file
118             CurrLine = Reader.ReadLine();
119             CurrPos = 0;
120             // Test for end of file
121             if (CurrLine == null)
122                 return false;
123             // Test for empty line
124             if (CurrLine.Length == 0)
125             {
126                 switch (EmptyLineBehavior)
127                 {
128                     case EmptyLineBehavior.NoColumns:
129                         columns.Clear();
130                         return true;
131                     case EmptyLineBehavior.Ignore:
132                         goto ReadNextLine;
133                     case EmptyLineBehavior.EndOfFile:
134                         return false;
135                 }
136             }
137 
138             // Parse line
139             string column;
140             int numColumns = 0;
141             while (true)
142             {
143                 // Read next column
144                 if (CurrPos < CurrLine.Length && CurrLine[CurrPos] == Quote)
145                     column = ReadQuotedColumn();
146                 else
147                     column = ReadUnquotedColumn();
148                 // Add column to list
149                 if (numColumns < columns.Count)
150                     columns[numColumns] = column;
151                 else
152                     columns.Add(column);
153                 numColumns++;
154                 // Break if we reached the end of the line
155                 if (CurrLine == null || CurrPos == CurrLine.Length)
156                     break;
157                 // Otherwise skip delimiter
158                 Debug.Assert(CurrLine[CurrPos] == Delimiter);
159                 CurrPos++;
160             }
161             // Remove any unused columns from collection
162             if (numColumns < columns.Count)
163                 columns.RemoveRange(numColumns, columns.Count - numColumns);
164             // Indicate success
165             return true;
166         }
167 
168         /// <summary>
169         /// Reads a quoted column by reading from the current line until a
170         /// closing quote is found or the end of the file is reached. On return,
171         /// the current position points to the delimiter or the end of the last
172         /// line in the file. Note: CurrLine may be set to null on return.
173         /// </summary>
174         private string ReadQuotedColumn()
175         {
176             // Skip opening quote character
177             Debug.Assert(CurrPos < CurrLine.Length && CurrLine[CurrPos] == Quote);
178             CurrPos++;
179 
180             // Parse column
181             StringBuilder builder = new StringBuilder();
182             while (true)
183             {
184                 while (CurrPos == CurrLine.Length)
185                 {
186                     // End of line so attempt to read the next line
187                     CurrLine = Reader.ReadLine();
188                     CurrPos = 0;
189                     // Done if we reached the end of the file
190                     if (CurrLine == null)
191                         return builder.ToString();
192                     // Otherwise, treat as a multi-line field
193                     builder.Append(Environment.NewLine);
194                 }
195 
196                 // Test for quote character
197                 if (CurrLine[CurrPos] == Quote)
198                 {
199                     // If two quotes, skip first and treat second as literal
200                     int nextPos = (CurrPos + 1);
201                     if (nextPos < CurrLine.Length && CurrLine[nextPos] == Quote)
202                         CurrPos++;
203                     else
204                         break;  // Single quote ends quoted sequence
205                 }
206                 // Add current character to the column
207                 builder.Append(CurrLine[CurrPos++]);
208             }
209 
210             if (CurrPos < CurrLine.Length)
211             {
212                 // Consume closing quote
213                 Debug.Assert(CurrLine[CurrPos] == Quote);
214                 CurrPos++;
215                 // Append any additional characters appearing before next delimiter
216                 builder.Append(ReadUnquotedColumn());
217             }
218             // Return column value
219             return builder.ToString();
220         }
221 
222         /// <summary>
223         /// Reads an unquoted column by reading from the current line until a
224         /// delimiter is found or the end of the line is reached. On return, the
225         /// current position points to the delimiter or the end of the current
226         /// line.
227         /// </summary>
228         private string ReadUnquotedColumn()
229         {
230             int startPos = CurrPos;
231             CurrPos = CurrLine.IndexOf(Delimiter, CurrPos);
232             if (CurrPos == -1)
233                 CurrPos = CurrLine.Length;
234             if (CurrPos > startPos)
235                 return CurrLine.Substring(startPos, CurrPos - startPos);
236             return String.Empty;
237         }
238 
239         // Propagate Dispose to StreamReader
240         public void Dispose()
241         {
242             Reader.Dispose();
243         }
244     }
245 
246     /// <summary>
247     /// Class for writing to comma-separated-value (CSV) files.
248     /// </summary>
249     public class CsvFileWriter : CsvFileCommon, IDisposable
250     {
251         // Private members
252         private StreamWriter Writer;
253         private string OneQuote = null;
254         private string TwoQuotes = null;
255         private string QuotedFormat = null;
256 
257         /// <summary>
258         /// Initializes a new instance of the CsvFileWriter class for the
259         /// specified stream.
260         /// </summary>
261         /// <param name="stream">The stream to write to</param>
262         public CsvFileWriter(Stream stream)
263         {
264             Writer = new StreamWriter(stream);
265         }
266 
267         /// <summary>
268         /// Initializes a new instance of the CsvFileWriter class for the
269         /// specified file path.
270         /// </summary>
271         /// <param name="path">The name of the CSV file to write to</param>
272         public CsvFileWriter(string path)
273         {
274             Writer = new StreamWriter(path);
275         }
276 
277         /// <summary>
278         /// Writes a row of columns to the current CSV file.
279         /// </summary>
280         /// <param name="columns">The list of columns to write</param>
281         public void WriteRow(List<string> columns)
282         {
283             // Verify required argument
284             if (columns == null)
285                 throw new ArgumentNullException("columns");
286 
287             // Ensure we‘re using current quote character
288             if (OneQuote == null || OneQuote[0] != Quote)
289             {
290                 OneQuote = String.Format("{0}", Quote);
291                 TwoQuotes = String.Format("{0}{0}", Quote);
292                 QuotedFormat = String.Format("{0}{{0}}{0}", Quote);
293             }
294 
295             // Write each column
296             for (int i = 0; i < columns.Count; i++)
297             {
298                 // Add delimiter if this isn‘t the first column
299                 if (i > 0)
300                     Writer.Write(Delimiter);
301                 // Write this column
302                 if (columns[i].IndexOfAny(SpecialChars) == -1)
303                     Writer.Write(columns[i]);
304                 else
305                     Writer.Write(QuotedFormat, columns[i].Replace(OneQuote, TwoQuotes));
306             }
307             Writer.WriteLine();
308         }
309 
310         // Propagate Dispose to StreamWriter
311         public void Dispose()
312         {
313             Writer.Dispose();
314         }
315     }
316 }

 

C# - CSV(Comma-Separated Values)文件读取.

标签:style   blog   color   io   os   ar   for   sp   文件   

原文地址:http://www.cnblogs.com/listened/p/4041096.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!