summaryrefslogtreecommitdiff
path: root/ThirdParty/CsvHelper-master/docs/getting-started/index.html
blob: 3572457787cc7a58c34ba45be1c1662f37209f6f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
<!DOCTYPE html>
<html lang="en-us">
<head>
	<meta charSet="UTF-8" />
	<meta name="viewport" content="width=device-width, initial-scale=1" />
	<link rel="apple-touch-icon" sizes="57x57" href="/CsvHelper/favicons/apple-icon-57x57.png" />
	<link rel="apple-touch-icon" sizes="60x60" href="/CsvHelper/favicons/apple-icon-60x60.png" />
	<link rel="apple-touch-icon" sizes="72x72" href="/CsvHelper/favicons/apple-icon-72x72.png" />
	<link rel="apple-touch-icon" sizes="76x76" href="/CsvHelper/favicons/apple-icon-76x76.png" />
	<link rel="apple-touch-icon" sizes="114x114" href="/CsvHelper/favicons/apple-icon-114x114.png" />
	<link rel="apple-touch-icon" sizes="120x120" href="/CsvHelper/favicons/apple-icon-120x120.png" />
	<link rel="apple-touch-icon" sizes="144x144" href="/CsvHelper/favicons/apple-icon-144x144.png" />
	<link rel="apple-touch-icon" sizes="152x152" href="/CsvHelper/favicons/apple-icon-152x152.png" />
	<link rel="apple-touch-icon" sizes="180x180" href="/CsvHelper/favicons/apple-icon-180x180.png" />
	<link rel="icon" type="image/png" sizes="192x192" href="/CsvHelper/favicons/android-icon-192x192.png" />
	<link rel="icon" type="image/png" sizes="32x32" href="/CsvHelper/favicons/favicon-32x32.png" />
	<link rel="icon" type="image/png" sizes="96x96" href="/CsvHelper/favicons/favicon-96x96.png" />
	<link rel="icon" type="image/png" sizes="16x16" href="/CsvHelper/favicons/favicon-16x16.png" />
	<link rel="manifest" href="/CsvHelper/manifest.json" />
	<meta name="msapplication-TileColor" content="#ffffff" />
	<meta name="msapplication-TileImage" content="/ms-icon-144x144.png" />
	<meta name="theme-color" content="#ffffff" />
	<title>Getting Started | CsvHelper</title>

	
	
		<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.9.1/css/bulma.min.css" />
	
	<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/styles/default.min.css" />
	<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/styles/vs.min.css" />
	<link rel="stylesheet" href="/CsvHelper/styles/index.css" />

	<script defer src="https://use.fontawesome.com/releases/v5.14.0/js/all.js"></script>
	<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/highlight.min.js"></script>
</head>
<body>
	<header id="header" class="header">
	<nav class="navbar is-light">
		<div class="navbar-brand">
			<a class="navbar-item" href="/CsvHelper">
				<img src="/CsvHelper/images/logo.svg" width="66" height="28" />
			</a>
			<div id="navbar-burger" class="navbar-burger">
				<span></span>
				<span></span>
				<span></span>
			</div>
		</div>
		<div id="navbar-menu" class="navbar-menu">
			<div class="navbar-start">
				<a class="navbar-item" href="/CsvHelper/getting-started">Getting Started</a>
				<a class="navbar-item" href="/CsvHelper/examples">Examples</a>
				<a class="navbar-item" href="/CsvHelper/migration">Migration</a>
				<a class="navbar-item" href="/CsvHelper/change-log">Change Log</a>
			</div>
			<div class="navbar-end">
				<a class="navbar-item" href="https://twitter.com/JoshClose">
					<span class="icon">
						<i class="fab fa-twitter"></i>
					</span>
				</a>
				<a class="navbar-item" href="https://github.com/JoshClose/CsvHelper">
					<span class="icon">
						<i class="fab fa-github"></i>
					</span>
				</a>
			</div>
		</div>
	</nav>
</header>


	<main id="main" class="container is-fluid">
		<div class="columns is-variable is-1">
					<div class="column is-2">
						
<div id="sidebar" class="sidebar">
	<ul class="">
		<li>
	<span>

		<a href="#installation">Installation</a>
	</span>

</li>

		<li>
	<span>

		<a href="#cultureinfo">CultureInfo</a>
	</span>

</li>

		<li>
	<span>

		<a href="#newlines">Newlines</a>
	</span>

</li>

		<li>
	<span>

		<a href="#reading-a-csv-file">Reading a CSV file</a>
	</span>

</li>

		<li>
	<span>

		<a href="#writing-a-csv-file">Writing a CSV file</a>
	</span>

</li>

		<li>
	<span>

		<a href="#">Back to top</a>
	</span>

</li>

</ul>

</div>

					</div>
				<div class="column">
					<div class="content">
						<h1 id="getting-started">Getting Started</h1>
<h2 id="installation">Installation</h2>
<hr />
<h3 id="package-manager-console">Package Manager Console</h3>
<pre><code>PM&gt; Install-Package CsvHelper
</code></pre>
<h3 id="net-cli-console">.NET CLI Console</h3>
<pre><code>&gt; dotnet add package CsvHelper
</code></pre>
<h2 id="prerequisites">Prerequisites</h2>
<p>There is some basic .NET knowledge that is implied when using this documentation. Please look over the prequisites to make sure you have an
understanding of them. <a href="/CsvHelper/examples/prerequisites">Prerequisites</a></p>
<h2 id="cultureinfo">CultureInfo</h2>
<p>CsvHelper requires you to specify the <code>CultureInfo</code> that you want to use. The culture is used to determine the default delimiter, default line ending, and formatting when type converting. You can change the configuration of any of these too if you like. Choose the appropriate culture for your data. <code>InvariantCulture</code> will be the most portable for writing a file and reading it back again, so that will be used in most of the examples.</p>
<h2 id="newlines">Newlines</h2>
<p>By default, CsvHelper will follow <a href="https://tools.ietf.org/html/rfc4180#page-2">RFC 4180</a> and use <code>\r\n</code> for writing newlines no matter what operating system
you are running on. CsvHelper can read <code>\r\n</code>, <code>\r</code>, or <code>\n</code> without any configuration changes. If you want to read or write in a non-standard format, you can
change the configuration for <code>NewLine</code>.</p>
<pre><code class="language-cs">var config = new CsvConfiguration(CultureInfo.InvariantCulture)
{
	NewLine = Environment.NewLine,
};
</code></pre>
<h2 id="reading-a-csv-file">Reading a CSV File</h2>
<hr />
<p>Let's say we have CSV file that looks like this.</p>
<pre><code>Id,Name
1,one
2,two
</code></pre>
<p>And a class definition that looks like this.</p>
<pre><code class="language-cs">public class Foo
{
	public int Id { get; set; }
	public string Name { get; set; }
}
</code></pre>
<p>If our class property names match our CSV file header names, we can read the file without any configuration.</p>
<pre><code class="language-cs">using (var reader = new StreamReader(&quot;path\\to\\file.csv&quot;))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
	var records = csv.GetRecords&lt;Foo&gt;();
}
</code></pre>
<p>The <code>GetRecords&lt;T&gt;</code> method will return an <code>IEnumerable&lt;T&gt;</code> that will <code>yield</code> records.
What this means is that only a single record is returned at a time as you iterate the records.
That also means that only a small portion of the file is read into memory. Be careful though.
If you do anything that executes a LINQ projection, such as calling <code>.ToList()</code>, the entire file
will be read into memory. <code>CsvReader</code> is forward only, so if you want to run any LINQ queries
against your data, you'll have to pull the whole file into memory. Just know that is what you're doing.</p>
<p>Let's say our CSV file names are a little different than our class properties and we don't want to
make our properties match.</p>
<pre><code>id,name
1,one
2,two
</code></pre>
<p>In this case, the names are lower case. We want our property names to be Pascal Case, so we can
just change how our properties match against the header names.</p>
<pre><code class="language-cs">var config = new CsvConfiguration(CultureInfo.InvariantCulture)
{
	PrepareHeaderForMatch = args =&gt; args.Header.ToLower(),
};
using (var reader = new StreamReader(&quot;path\\to\\file.csv&quot;))
using (var csv = new CsvReader(reader, config))
{
	var records = csv.GetRecords&lt;Foo&gt;();
}
</code></pre>
<p>Using the configuration <code>PrepareHeaderForMatch</code>, we're able to change how the header matching
is done against the property name. Both the header and the property name are ran through the
<code>PrepareHeaderForMatch</code> function. When the reader needs to find the property to set for the
header, they will now match. You can use this function to do other things such as remove
whitespace or other characters.</p>
<p>Let's say out CSV file doesn't have a header at all.</p>
<pre><code>1,one
2,two
</code></pre>
<p>First we need to tell the reader that there is no header record, using configuration.</p>
<pre><code class="language-cs">var config = new CsvConfiguration(CultureInfo.InvariantCulture)
{
	HasHeaderRecord = false,
};
using (var reader = new StreamReader(&quot;path\\to\\file.csv&quot;))
using (var csv = new CsvReader(reader, config))
{
	var records = csv.GetRecords&lt;Foo&gt;();
}
</code></pre>
<p>CsvReader will use the position of the properties in the class as the index position. There is an
issue with this though. <a href="https://blogs.msdn.microsoft.com/haibo_luo/2006/07/10/member-order-returned-by-getfields-getmethods/">You can't rely on the ordering of class members in .NET</a>.
We can solve this by mapping the property to a position in the CSV file.</p>
<p>One way to do this is with attribute mapping.</p>
<pre><code class="language-cs">public class Foo
{
	[Index(0)]
	public int Id { get; set; }

	[Index(1)]
	public string Name { get; set; }
}
</code></pre>
<p>The <code>IndexAttribute</code> allows you to specify which position the CSV field is that you want to use
for the property.</p>
<p>You can also map by name. Let's use our lower case header example from before and see how we can
use attributes instead of changing the header matching.</p>
<pre><code class="language-cs">public class Foo
{
	[Name(&quot;id&quot;)]
	public int Id { get; set; }

	[Name(&quot;name&quot;)]
	public string Name { get; set; }
}
</code></pre>
<p><a href="/CsvHelper/examples/configuration/attributes">There are many other attributes you can use also.</a></p>
<p>What if we don't have control over the class we want to map to so we can't add attributes to it?
In this case, we can use a fluent <code>ClassMap</code> to do the mapping.</p>
<pre><code class="language-cs">public class FooMap : ClassMap&lt;Foo&gt;
{
	public FooMap()
	{
		Map(m =&gt; m.Id).Name(&quot;id&quot;);
		Map(m =&gt; m.Name).Name(&quot;name&quot;);
	}
}
</code></pre>
<p>To use the mapping, we need to register it in the context.</p>
<pre><code class="language-cs">using (var reader = new StreamReader(&quot;path\\to\\file.csv&quot;))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
	csv.Context.RegisterClassMap&lt;FooMap&gt;();
	var records = csv.GetRecords&lt;Foo&gt;();
}
</code></pre>
<p>Creating a class map is the recommended way of mapping files in CsvHelper because it's a
lot more powerful.</p>
<p>You can also read rows by hand.</p>
<pre><code class="language-cs">using (var reader = new StreamReader(&quot;path\\to\file.csv&quot;))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
	csv.Read();
	csv.ReadHeader();
	while (csv.Read())
	{
		var record = csv.GetRecord&lt;Foo&gt;();
		// Do something with the record.
	}
}
</code></pre>
<p><code>Read</code> will advance row. <code>ReadHeader</code> will read the row into CsvHelper as the header values.
Separating <code>Read</code> and <code>ReadHeader</code> allows you to do other things with the header row before
moving onto the next row. <code>GetRecord</code> also does not advance the reader to allow you to do
other things with the row you might need to do. You may need to <code>GetField</code> for a single field
or maybe call <code>GetRecord</code> multiple times to fill more than one object.</p>
<h2 id="writing-a-csv-file">Writing a CSV File</h2>
<p>Now let's look at how we can write CSV files. It's basically the same thing, but in reverse order.</p>
<p>Let's use the same class definition as before.</p>
<pre><code class="language-cs">public class Foo
{
	public int Id { get; set; }
	public string Name { get; set; }
}
</code></pre>
<p>And we have a set of records like this.</p>
<pre><code class="language-cs">var records = new List&lt;Foo&gt;
{
	new Foo { Id = 1, Name = &quot;one&quot; },
	new Foo { Id = 2, Name = &quot;two&quot; },
};
</code></pre>
<p>We can write the records to a file without any configuration.</p>
<pre><code class="language-cs">using (var writer = new StreamWriter(&quot;path\\to\\file.csv&quot;))
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
	csv.WriteRecords(records);
}
</code></pre>
<p>The <code>WriteRecords</code> method will write all the records to the file. After you are done writing,
you should call <code>writer.Flush()</code> to ensure that all the data in the writer's internal buffer
has been flushed to the file. Once a <code>using</code> block has exited, the writer is automatically
flushed, so we don't have to explicitly do it here. It's recommended to always wrap any
<code>IDisposable</code> object with <code>using</code> blocks. The object will dispose of itself (and in our case
flush too) as soon as possible after the <code>using</code> block has exited.</p>
<p>Remember how we can't rely on property order in .NET? If we are writing a class that has a header,
it doesn't matter, as long as we are reading using the headers later. If we want to position
the headers in the CSV file, we need to specify an index to guarantee it's order. It's
recommended to always set an index when writing.</p>
<pre><code class="language-cs">public class FooMap : ClassMap&lt;Foo&gt;
{
	public FooMap()
	{
		Map(m =&gt; m.Id).Index(0).Name(&quot;id&quot;);
		Map(m =&gt; m.Name).Index(1).Name(&quot;name&quot;);
	}
}
</code></pre>
<p>You can also write rows by hand.</p>
<pre><code class="language-cs">using (var writer = new StreamWriter(&quot;path\\to\\file.csv&quot;))
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
	csv.WriteHeader&lt;Foo&gt;();
	csv.NextRecord();
	foreach (var record in records)
	{
		csv.WriteRecord(record);
		csv.NextRecord();
	}
}
</code></pre>
<p><code>WriteHeader</code> will not advance you to the next row. Separating <code>NextRecord</code> from <code>WriteHeader</code>
allows you to write more things in the header if you need to. <code>WriteRecord</code> also will not
advance you to the next row to give you the ability to write multiple objects or use
<code>WriteField</code> to write individual fields.</p>
<br/>

					</div>
				</div>
		</div>
	</main>

	<br /><br />

	<footer id="footer" class="footer">
	<div class="has-text-centered">&copy; 2009-2022 Josh Close</div>
</footer>



	<script>
		hljs.configure({
			tabReplace: "    "
		});
		hljs.initHighlightingOnLoad();
	</script>
	<script src="/CsvHelper/scripts/header.js"></script>
	<script src="/CsvHelper/scripts/sidebar.js"></script>
	
</body>
</html>