C#操作CSV文件的詳細(xì)教程
一、CSV 格式詳解
基本語(yǔ)法
- CSV 文件以純文本形式存儲(chǔ)數(shù)據(jù),每一行代表一條記錄。
- 字段之間以逗號(hào)(
,)分隔,例如:姓名,年齡,性別。 - 如果字段中包含逗號(hào)、雙引號(hào)(
")或換行符,需要用雙引號(hào)將字段包圍起來。如果字段本身包含雙引號(hào),則需要用兩個(gè)雙引號(hào)表示一個(gè)雙引號(hào)。例如:"張三,程序員","25","男",其中第一個(gè)字段包含逗號(hào),因此用雙引號(hào)包圍;若字段是"O'Neill",則應(yīng)寫成"""O""Neill"""。
編碼格式
常見的 CSV 文件編碼有 UTF - 8、GBK 等。在讀寫 CSV 文件時(shí),需要確保指定正確的編碼格式,否則可能會(huì)出現(xiàn)亂碼。例如,在使用 StreamReader 或 StreamWriter 時(shí),可以通過 Encoding 參數(shù)指定編碼:
using (StreamReader reader = new StreamReader("data.csv", System.Text.Encoding.UTF8))
{
// 讀取操作
}二、讀取 CSV 文件的多種方式
(一)使用StreamReader逐行讀取
原理 :通過 StreamReader 逐行讀取 CSV 文件內(nèi)容,然后對(duì)每一行進(jìn)行處理,將字符串按逗號(hào)分隔成數(shù)組。
代碼示例 :
using System;
using System.Collections.Generic;
using System.IO;
class Program
{
static void Main()
{
List<string[]> csvData = new List<string[]>();
using (StreamReader reader = new StreamReader("data.csv"))
{
string line;
while ((line = reader.ReadLine()) != null)
{
// 將每一行按逗號(hào)分隔成數(shù)組
string[] fields = line.Split(',');
csvData.Add(fields);
}
}
// 輸出讀取的數(shù)據(jù)
foreach (string[] row in csvData)
{
foreach (string field in row)
{
Console.Write(field + "\t");
}
Console.WriteLine();
}
}
}- 優(yōu)點(diǎn) :簡(jiǎn)單易用,適合小型 CSV 文件的讀取。
- 缺點(diǎn) :對(duì)于包含復(fù)雜字段(如字段中包含逗號(hào)、引號(hào)等特殊字符)的 CSV 文件,無(wú)法正確解析。
(二)使用TextFieldParser(需引用Microsoft.VisualBasic.dll組件)
- 原理 :
TextFieldParser是 .NET Framework 提供的一個(gè)專門用于解析文本文件的類,它可以更好地處理 CSV 文件中包含特殊字符的字段。 - 代碼示例 :
using System;
using Microsoft.VisualBasic.FileIO;
class Program
{
static void Main()
{
using (TextFieldParser parser = new TextFieldParser("data.csv"))
{
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
while (!parser.EndOfData)
{
try
{
string[] fields = parser.ReadFields();
foreach (string field in fields)
{
Console.Write(field + "\t");
}
Console.WriteLine();
}
catch (MalformedLineException ex)
{
Console.WriteLine("行 {0} 格式錯(cuò)誤: {1}", parser.LineNumber, ex.Message);
}
}
}
}
}- 優(yōu)點(diǎn) :能夠正確處理字段中包含逗號(hào)、引號(hào)等特殊字符的情況。
- 缺點(diǎn) :需要引用
Microsoft.VisualBasic.dll組件。
(三)使用第三方庫(kù)(如 CsvHelper)
- 原理 :CsvHelper 是一個(gè)功能強(qiáng)大的開源 CSV 操作庫(kù),它提供了更簡(jiǎn)便的 API,可以輕松地讀取和寫入 CSV 文件,并且支持將 CSV 數(shù)據(jù)映射到對(duì)象。
- 安裝 CsvHelper :通過 NuGet 包管理器安裝 CsvHelper,命令如下:
Install-Package CsvHelper
- 代碼示例 - 讀取 CSV 文件 :
using System;
using System.Collections.Generic;
using System.IO;
using CsvHelper;
using CsvHelper.Configuration;
class Program
{
static void Main()
{
using (StreamReader reader = new StreamReader("data.csv"))
using (CsvReader csv = new CsvReader(reader, new CsvConfiguration(System.Globalization.CultureInfo.InvariantCulture)))
{
var records = csv.GetRecords<Person>().ToList();
foreach (Person person in records)
{
Console.WriteLine($"姓名: {person.Name}, 年齡: {person.Age}, 性別: {person.Gender}");
}
}
}
}
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
}- 優(yōu)點(diǎn) :功能強(qiáng)大,易于使用,支持對(duì)象映射和高級(jí)配置。
- 缺點(diǎn) :需要引入外部依賴。
三、寫入 CSV 文件的多種方式
(一)使用StreamWriter寫入
- 原理 :將二維數(shù)據(jù)數(shù)組或列表轉(zhuǎn)換為字符串,按行寫入到 CSV 文件中。
- 代碼示例 :
using System;
using System.IO;
class Program
{
static void Main()
{
string[][] data = new string[][]
{
new string[] {"姓名", "年齡", "性別"},
new string[] {"張三", "25", "男"},
new string[] {"李四", "30", "女"}
};
using (StreamWriter writer = new StreamWriter("data.csv"))
{
foreach (string[] row in data)
{
// 將數(shù)組元素用逗號(hào)連接成一行
writer.WriteLine(string.Join(",", row));
}
}
}
}- 優(yōu)點(diǎn) :簡(jiǎn)單易用,適合小型 CSV 文件的寫入。
- 缺點(diǎn) :無(wú)法自動(dòng)處理字段中的特殊字符。
(二)使用StringBuilder構(gòu)建內(nèi)容后寫入
- 原理 :先用
StringBuilder構(gòu)建整個(gè) CSV 內(nèi)容,最后一次性寫入文件,減少文件操作次數(shù),尤其適用于大量數(shù)據(jù)寫入。 - 代碼示例 :
using System;
using System.IO;
using System.Text;
class Program
{
static void Main()
{
string[][] data = new string[][]
{
new string[] {"姓名", "年齡", "性別"},
new string[] {"張三", "25", "男"},
new string[] {"李四", "30", "女"}
};
StringBuilder sb = new StringBuilder();
foreach (string[] row in data)
{
sb.AppendLine(string.Join(",", row));
}
File.WriteAllText("data.csv", sb.ToString());
}
}- 優(yōu)點(diǎn) :提高寫入效率,適合大量數(shù)據(jù)寫入。
- 缺點(diǎn) :無(wú)法自動(dòng)處理字段中的特殊字符。
(三)使用第三方庫(kù)(如 CsvHelper)寫入
- 原理 :利用 CsvHelper 提供的簡(jiǎn)便 API,將對(duì)象列表寫入 CSV 文件,自動(dòng)處理字段中的特殊字符。
- 代碼示例 :
using System;
using System.Collections.Generic;
using System.IO;
using CsvHelper;
class Program
{
static void Main()
{
List<Person> persons = new List<Person>
{
new Person { Name = "張三", Age = 25, Gender = "男" },
new Person { Name = "李四", Age = 30, Gender = "女" }
};
using (StreamWriter writer = new StreamWriter("data.csv"))
using (CsvWriter csv = new CsvWriter(writer, System.Globalization.CultureInfo.InvariantCulture))
{
csv.WriteRecords(persons);
}
}
}
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
}- 優(yōu)點(diǎn) :功能強(qiáng)大,易于使用,自動(dòng)處理特殊字符。
- 缺點(diǎn) :需要引入外部依賴。
四、CSV 數(shù)據(jù)的解析與處理
(一)處理字段中的特殊字符
- 引號(hào)包圍字段 :如果字段中包含逗號(hào)、引號(hào)或換行符,需要用雙引號(hào)將字段包圍起來。如果字段本身包含雙引號(hào),則需要用兩個(gè)雙引號(hào)表示一個(gè)雙引號(hào)。
- 代碼示例 - 寫入包含特殊字符的字段 :
using System;
using System.IO;
class Program
{
static void Main()
{
string[][] data = new string[][]
{
new string[] {"姓名", "年齡", "愛好"},
new string[] {"張三", "25", "讀書, 旅行"},
new string[] {"李四", "30", "打籃球\" \"排球"}
};
using (StreamWriter writer = new StreamWriter("data.csv"))
{
foreach (string[] row in data)
{
for (int i = 0; i < row.Length; i++)
{
// 如果字段中包含逗號(hào)、引號(hào)或換行符,用雙引號(hào)包圍
if (row[i].Contains(",") || row[i].Contains("\"") || row[i].Contains("\n") || row[i].Contains("\r"))
{
// 將字段中的雙引號(hào)替換為兩個(gè)雙引號(hào)
row[i] = "\"" + row[i].Replace("\"", "\"\"") + "\"";
}
writer.Write(row[i]);
if (i < row.Length - 1)
{
writer.Write(",");
}
}
writer.WriteLine();
}
}
}
}(二)將 CSV 數(shù)據(jù)映射到對(duì)象
- 定義數(shù)據(jù)類 :根據(jù) CSV 文件的結(jié)構(gòu)定義一個(gè)對(duì)應(yīng)的類,方便對(duì)數(shù)據(jù)進(jìn)行操作。
- 代碼示例 :
using System;
using System.Collections.Generic;
using System.IO;
class Program
{
static void Main()
{
List<Person> persons = new List<Person>();
using (StreamReader reader = new StreamReader("data.csv"))
{
// 跳過標(biāo)題行
reader.ReadLine();
string line;
while ((line = reader.ReadLine()) != null)
{
string[] fields = line.Split(',');
Person person = new Person
{
Name = fields[0],
Age = int.Parse(fields[1]),
Gender = fields[2]
};
persons.Add(person);
}
}
// 輸出對(duì)象數(shù)據(jù)
foreach (Person person in persons)
{
Console.WriteLine($"姓名: {person.Name}, 年齡: {person.Age}, 性別: {person.Gender}");
}
}
}
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
}五、注意事項(xiàng)
文件路徑問題
- 確保提供的文件路徑正確。如果文件不存在,讀取操作會(huì)拋出異常;如果寫入路徑無(wú)效,可能會(huì)導(dǎo)致寫入失敗或創(chuàng)建新文件在錯(cuò)誤的位置。
- 可以使用
File.Exists方法檢查文件是否存在:
if (!File.Exists("data.csv"))
{
Console.WriteLine("文件不存在!");
}數(shù)據(jù)類型轉(zhuǎn)換問題
- 在將 CSV 數(shù)據(jù)轉(zhuǎn)換為對(duì)象屬性時(shí),要注意數(shù)據(jù)類型的正確轉(zhuǎn)換。如果轉(zhuǎn)換失敗,可能會(huì)引發(fā)異常,如將字符串轉(zhuǎn)換為整數(shù)時(shí),字符串不是有效的整數(shù)格式。
- 可以使用
TryParse方法進(jìn)行安全轉(zhuǎn)換:
int age;
if (int.TryParse(fields[1], out age))
{
person.Age = age;
}
else
{
Console.WriteLine("年齡數(shù)據(jù)格式錯(cuò)誤!");
}性能優(yōu)化
- 對(duì)于大型 CSV 文件的讀寫操作,可以考慮使用流式處理,避免一次性加載整個(gè)文件到內(nèi)存中。例如,使用
StreamReader逐行讀取,或使用StreamWriter逐行寫入。 - 如果需要頻繁讀寫 CSV 文件,可以考慮使用內(nèi)存映射文件(Memory - Mapped Files)技術(shù)提高性能。
以上就是C#操作CSV文件的詳細(xì)教程的詳細(xì)內(nèi)容,更多關(guān)于C#操作CSV文件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#使用Interlocked實(shí)現(xiàn)線程同步
今天小編就為大家分享一篇關(guān)于C#使用Interlocked實(shí)現(xiàn)線程同步,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2018-10-10
C#獲取串口列表實(shí)現(xiàn)實(shí)時(shí)監(jiān)控串口
本文主要介紹兩種獲取串口列表的方法,比較簡(jiǎn)單,方便大家使用,另外分享了一個(gè)已封裝的API,需要的朋友可以參考下。2016-05-05
使用C#實(shí)現(xiàn)上位機(jī)與PLC通信的過程詳解
隨著工業(yè)自動(dòng)化技術(shù)的不斷發(fā)展,PLC(可編程邏輯控制器)已成為現(xiàn)代生產(chǎn)過程中不可或缺的設(shè)備,為了實(shí)現(xiàn)設(shè)備之間的數(shù)據(jù)交換和遠(yuǎn)程控制,上位機(jī)系統(tǒng)需要與PLC進(jìn)行通信,在本文中,我們將從零開始,介紹如何使用C#實(shí)現(xiàn)上位機(jī)與PLC的通信,需要的朋友可以參考下2025-01-01
C#驗(yàn)證用戶輸入信息是否包含危險(xiǎn)字符串的方法
這篇文章主要介紹了C#驗(yàn)證用戶輸入信息是否包含危險(xiǎn)字符串的方法,可針對(duì)and、or、exec、insert、select等SQL操作技巧進(jìn)行過濾操作,非常具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03
C#實(shí)現(xiàn)讀取ini配置文件的內(nèi)容
INI就是擴(kuò)展名為"INI"的文件,其實(shí)他本身是個(gè)文本文件,可以用記事本打開,本文主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)讀取ini配置文件內(nèi)容的方法,需要的小伙伴可以了解下2023-12-12

