C#實現List導出CSV:深入解析完整方案

C#實現List導出CSV:深入解析完整方案

在數據交互場景中,CSV文件憑借其跨平臺兼容性和簡潔性,成為數據交換的重要載體。本文將基于C#反射機制實現的通用CSV導出方案,結合實際開發中的痛點,從基礎實現、深度優化到生產級實踐進行全方位解析。

一、基礎實現:反射驅動的動態導出

核心代碼架構

public void Save<T>(List<T> items, string path)
{using var sw = new StreamWriter(path, false, Encoding.UTF8);var type = typeof(T);var props = type.GetProperties();// 生成表頭sw.WriteLine(string.Join(",", props.Select(p => p.Name)));// 寫入數據foreach (var item in items){var values = props.Select(p => EscapeField(p.GetValue(item)?.ToString() ?? "")).ToArray();sw.WriteLine(string.Join(",", values));}
}private string EscapeField(string value)
{if (value.Contains(',') || value.Contains('"') || value.Contains('\n')){return $"\"{value.Replace("\"", "\"\"")}\"";}return value;
}

關鍵設計點

  1. 反射機制:通過typeof(T).GetProperties()動態獲取類型元數據,實現泛型支持
  2. 流處理:使用StreamWriter的using塊確保資源自動釋放,支持大文件導出
  3. 基本轉義:通過EscapeField方法處理包含分隔符、引號和換行符的字段
  4. UTF-8編碼:默認使用UTF-8編碼,兼容多語言環境

使用示例

class Product
{public string Name { get; set; }public decimal Price { get; set; }public DateTime ReleaseDate { get; set; }
}var products = new List<Product>
{new() { Name = "Apple Watch", Price = 399.99m, ReleaseDate = DateTime.Now }
};Save(products, "products.csv");

二、深度優化:解決生產級痛點

1. 特殊字符處理增強

問題場景
  • 字段內容包含逗號導致列錯位
  • 文本內容包含引號或換行符
  • Excel打開時科學計數法顯示問題
解決方案
private string EscapeField(string value)
{if (string.IsNullOrEmpty(value)) return "\"\"";bool needsQuotes = value.Contains(',') || value.Contains('"') || value.Contains('\n') || value.Contains('\r');if (needsQuotes){return $"\"{value.Replace("\"", "\"\"")}\"";}// 防止Excel自動轉換格式if (value.StartsWith('-') || value.Contains('.') || value.Contains(':')){return $"'{value}";}return value;
}

2. 數據類型格式化

問題場景
  • 日期類型導出為默認字符串格式
  • 數值類型需要千位分隔符
  • 枚舉類型需要顯示名稱而非整數值
解決方案
public class CsvColumnAttribute : Attribute
{public string Name { get; set; }public string Format { get; set; }
}public void Save<T>(List<T> items, string path)
{using var sw = new StreamWriter(path, false, Encoding.UTF8);var type = typeof(T);var props = type.GetProperties().Select(p => new {Property = p,Attribute = p.GetCustomAttribute<CsvColumnAttribute>()}).ToList();// 生成表頭sw.WriteLine(string.Join(",", props.Select(p => p.Attribute?.Name ?? p.Property.Name)));// 寫入數據foreach (var item in items){var values = props.Select(p => {var value = p.Property.GetValue(item);if (value == null) return "\"\"";if (p.Attribute != null && !string.IsNullOrEmpty(p.Attribute.Format)){return value.ToString().FormatWith(p.Attribute.Format);}return EscapeField(value.ToString());}).ToArray();sw.WriteLine(string.Join(",", values));}
}

使用示例:

class Order
{[CsvColumn(Name = "Order ID", Format = "D10")]public int Id { get; set; }[CsvColumn(Name = "Amount", Format = "C")]public decimal Total { get; set; }[CsvColumn(Name = "Order Date", Format = "yyyy-MM-dd HH:mm:ss")]public DateTime OrderDate { get; set; }
}

3. 錯誤處理機制

public void Save<T>(List<T> items, string path)
{try{using var sw = new StreamWriter(path, false, Encoding.UTF8);// 核心導出邏輯}catch (IOException ex){Console.WriteLine($"文件操作失敗:{ex.Message}");throw;}catch (Exception ex){Console.WriteLine($"導出失敗:{ex.Message}");throw;}
}

4. 性能優化策略

內存優化
  • 使用StringBuilder替代字符串拼接
  • 批量寫入而非逐行寫入
  • 流式處理大文件(>1GB)
異步支持
public async Task SaveAsync<T>(List<T> items, string path)
{using var sw = new StreamWriter(path, false, Encoding.UTF8);await sw.WriteLineAsync(string.Join(",", props.Select(p => p.Name)));foreach (var item in items){var line = string.Join(",", props.Select(p => EscapeField(p.GetValue(item)?.ToString() ?? "")));await sw.WriteLineAsync(line);}
}

三、生產級實踐

1. 高級配置

自定義分隔符
public void Save<T>(List<T> items, string path, char delimiter = ',')
{// 在生成表頭和數據時使用delimiter參數
}
列篩選
public void Save<T>(List<T> items, string path, params string[] columns)
{var props = type.GetProperties().Where(p => columns.Contains(p.Name)).ToList();// 僅處理指定列
}

2. 第三方庫對比

NReco.Csv
using NReco.Csv;public void SaveWithNReco<T>(List<T> items, string path)
{using var writer = new CsvWriter(path) {Delimiter = ',',QuoteAllFields = false,EscapeMode = CsvEscapeMode.Standard};var type = typeof(T);var props = type.GetProperties();writer.WriteRow(props.Select(p => p.Name).ToArray());foreach (var item in items){writer.WriteRow(props.Select(p => EscapeField(p.GetValue(item)?.ToString() ?? "")).ToArray());}
}
性能對比
方法10萬條數據耗時內存占用
原生實現120ms8MB
NReco.Csv45ms3MB
CSVHelper80ms6MB

3. 實際應用場景

  • 大數據量導出:處理百萬級數據時,采用流式處理和異步寫入
  • 復雜對象處理:支持嵌套對象和集合屬性展開
  • 動態列配置:通過配置文件指定導出列和格式

四、常見問題解決方案

1. Excel打開亂碼

// 使用UTF-8 with BOM編碼
using var sw = new StreamWriter(path, false, Encoding.UTF8);
// 或者指定具體編碼
using var sw = new StreamWriter(path, false, Encoding.GetEncoding("GB2312"));

2. 科學計數法問題

// 在字段前添加單引號
private string EscapeField(string value)
{if (value.Contains('.') || value.Contains('E')){return $"'{value}";}return value;
}

3. 空值處理

var value = p.GetValue(item) ?? string.Empty;

五、總結

本文從基礎實現到生產級優化,全面解析了C#中List導出CSV的完整解決方案。通過反射機制實現動態導出,結合特殊字符處理、數據類型格式化和錯誤處理,構建了健壯的導出框架。同時對比了第三方庫的性能表現,為不同場景提供了優化建議。實際應用中,可根據數據規模、格式復雜度和性能要求選擇合適的實現方案,確保高效穩定地完成CSV導出任務。

最佳實踐建議:

  1. 小規模數據使用原生實現,保持代碼簡潔
  2. 中大規模數據推薦NReco.Csv庫,平衡性能與功能
  3. 復雜格式需求采用CSVHelper,豐富的配置選項更靈活
  4. 始終進行壓力測試,驗證導出性能和內存占用

通過本文的實踐方案,開發者可以快速構建滿足企業級需求的CSV導出功能,有效提升數據交互效率。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/81472.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/81472.shtml
英文地址,請注明出處:http://en.pswp.cn/web/81472.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

字符串day7

344 反轉字符串 字符串理論上也是一個數組&#xff0c;因此只需要用雙指針即可 class Solution { public:void reverseString(vector<char>& s) {for(int i0,js.size()-1;i<j;i,j--){swap(s[i],s[j]);}} };541 反轉字符串 自己實現一個反轉從start到end的字符串…

Grafana XSSOpenRedirectSSRF漏洞復現(CVE-2025-4123)

免責申明: 本文所描述的漏洞及其復現步驟僅供網絡安全研究與教育目的使用。任何人不得將本文提供的信息用于非法目的或未經授權的系統測試。作者不對任何由于使用本文信息而導致的直接或間接損害承擔責任。如涉及侵權,請及時與我們聯系,我們將盡快處理并刪除相關內容。 前…

私服 nexus 之間遷移 npm 倉庫

本文介紹如何將一個 Nexus 特定倉庫中的 npm 包內容遷移到另一個 Nexus 特定倉庫。此過程適用于需要重構倉庫結構或合并倉庫的場景。 遷移腳本 以下是完整的遷移腳本&#xff0c;它會自動完成以下操作&#xff1a; 從源倉庫獲取所有 npm 包列表下載每個包的 .tgz 文件解壓并…

Django ToDoWeb 服務

我們的任務是使用 Django 創建一個簡單的 ToDo 應用程序,允許用戶添加、查看和刪除筆記。我們將通過設置 Django 項目、創建 Todo 模型、設計表單和視圖來處理用戶輸入以及創建模板來顯示任務來構建它。我們將逐步實現核心功能以有效地管理 todo 項。 Django ToDoWeb 服務 …

阿里云服務器遭遇DDoS攻擊?低成本第三方高防解決方案全解析

阿里云服務器因高性能和穩定性備受青睞&#xff0c;但其DDoS高防服務的價格常讓中小企業望而卻步。面對動輒每月數萬元的防護成本&#xff0c;許多用戶不禁疑問&#xff1a;能否通過第三方高防服務保護阿里云服務器&#xff1f;如何實現低成本高效防御&#xff1f; 本文將結合技…

2025山東CCPC補題

2025山東CCPC補題 目錄 2025山東CCPC補題K - UNO&#xff01; &#xff08;雙端隊列的簡單應用&#xff09;M - 第九屆河北省大學生程序設計競賽 &#xff08;二進制枚舉模擬&#xff09;J - Generate 01 String 感覺這場比賽的題目挺不錯的&#xff1b;沒有說那些為了算法而算…

體繪制學習

一、基本概念 體繪制是對一個三維物體數據進行采樣與擬合的過程。 在體繪制中用vtkVolume渲染數據 渲染數據類數據轉換類幾何渲染vtkActorvtkPolyDataMapper體渲染vtkVolumevtkVolumeRayCastMapper 體繪制常用算法如下。 光線投射法。 優點是可視化結果質量好。缺點是計算…

告別“盤絲洞”車間:4-20mA無線傳輸如何重構工廠神經網?

4-20ma無線傳輸是利用無線模塊將傳統的溫度、壓力、液位等4-20mA電流信號轉換為無線信號進行傳輸。這一技術突破了有線傳輸的限制&#xff0c;使得信號可以在更廣泛的范圍內進行靈活、快速的傳遞&#xff0c;無線傳輸距離可達到50KM。達泰4-20ma無線傳輸模塊在實現工業現場應用…

VB.NET與SQL連接問題解決方案

1.基本連接步驟 使用SqlConnection、SqlCommand和SqlDataReader進行基礎操作&#xff1a; vb.net Imports System.Data.SqlClient Public Sub ConnectToDatabase() Dim connectionString As String "ServermyServerAddress;DatabasemyDataBase;Integrated Security…

ElasticSearch--DSL查詢語句

ElasticSearch DSL查詢文檔 分類 查詢類型功能描述典型應用場景示例語法查詢所有匹配所有文檔&#xff0c;無過濾條件數據預覽/測試json { "query": { "match_all": {} } }全文檢索查詢對文本字段分詞后匹配&#xff0c;基于倒排索引搜索框模糊匹配、多字段…

DDR4讀寫壓力測試

1.1測試環境 1.1.1整體環境介紹 板卡&#xff1a; pcie-403板卡 主控芯片&#xff1a; Xilinx xcvu13p-fhgb2104-2 調試軟件&#xff1a; Vivado 2018.3 代碼環境&#xff1a; Vscode utf-8 測試工程&#xff1a; pcie403_user_top 1.1.2硬件介紹 UD PCIe-403…

在 Windows 上使用 WSL 安裝 Ansible詳細步驟

在 Windows 上使用 WSL&#xff08;Windows Subsystem for Linux&#xff09; 安裝 Ansible 是目前最推薦的方式&#xff0c;因為 Ansible 本身是為 Linux 環境設計的&#xff0c;不支持原生 Windows 作為控制節點。 下面是一個 詳細步驟指南 &#xff0c;幫助你在 Windows 上…

編寫第一個ros程序

1.下載VScode 下載鏈接如下&#xff1a; Download Visual Studio Code - Mac, Linux, Windows 下載ARM64下的.deb文件 打開虛擬機&#xff0c;再rosnoetic下新建一個文件夾VSCODE&#xff0c;將windows下的文件導入該文件夾下如下圖。 在該文件夾下右鍵選擇在終端中打開 輸入…

代碼隨想錄算法訓練營第60期第四十九天打卡

大家好&#xff0c;今天我們還是繼續我們的動態規劃章節&#xff0c;可能有的朋友已經開始厭倦了說為什么動態規劃怎么這么多題目&#xff0c;大家可以想想我們前面其實刷過好幾種類型的動態規劃的經典題目比如說各式各樣的背包問題當然包括0-1背包&#xff0c;完全背包&#x…

centos7.9離線升級內核到4.19.12詳細教程

cenots7.9默認安裝的內核版本是:3.10.0-1160.119.1.el7.x86_64,在安裝nvidia顯卡驅動的時候,提示內核版本過低,需要升級內核版本,升級完成之后,就可以順利的安裝上nvidia顯卡驅動了,實測有效。 一、查看當前內核版本命令 uname -r二、下載離線內核的rpm包

Vue3 + TypeScript + el-input 實現人民幣金額的輸入和顯示

輸入人民幣金額的參數要求&#xff1a; 輸入要求&#xff1a; 通過鍵盤&#xff0c;只允許輸入負號、小數點、數字、退格鍵、刪除鍵、方向左鍵、方向右鍵、Home鍵、End鍵、Tab鍵&#xff1b;負號只能在開頭&#xff1b;只保留第一個小數點&#xff1b;替換全角輸入的小數點&a…

方正字庫助力華為,賦能鴻蒙電腦打造全場景字體解決方案

2025年5月19日&#xff0c;搭載華為鴻蒙操作系統的鴻蒙電腦&#xff0c;面向用戶推出集AI智能、互聯流暢、安全保障和精致體驗于一體的全新辦公系統。作為鴻蒙生態核心字體服務商&#xff0c;方正字庫為此次提供了全面的系統字體支持&#xff0c;涵蓋中文、西文及符號三大類字庫…

PHPStudy 一鍵式網站搭建工具的下載使用

目錄 一、下載 PHPStudy二、安裝步驟三、基本使用方法3.1 創建網站3.2 管理數據庫3.3 軟件管理3.4 自動啟動3.5 配置管理 四、注意事項和進階使用4.1 注意事項4.2 進階使用 背景&#xff1a; 我們在學習和工作中&#xff0c;經常會遇到各種需要自己搭建環境的場景&#xff0c;這…

java中的線程安全的集合

1.ConcurrentHashMap。 key,value結構。 jdk1.7通過分段鎖保證不同段同時操作是線程安全的&#xff0c;但并發不足&#xff0c;jdk1.8通過node節點鎖和CAS保證并發安全。不同node節點可以并發讀寫。通過它的computer,computerIfAbsent,等可以保證原子更新value。ifAbsent表示有…

MySQL問題:MySQL中使用索引一定有效嗎?如何排查索引效果

不一定有效&#xff0c;當查詢條件中不包含索引列或查詢條件復雜且不匹配索引順序 對于一些小表&#xff0c;MySQL可能選擇全表掃描而非使用索引&#xff0c;因為全表掃描的開銷可能更小 最終是否用上索引是根據MySQL成本計算決定的&#xff0c;評估CPU和I/O成本 排查索引效…