跳至頁尾內容
USING IRONXL

在 C# 中匯入 CSV 檔案 | ASP.NET Core 教學課程 | IronXL

在C#中使用ASP.NET Core導入CSV文件意味著需要讀取文件流、解析分隔行,並將每個記錄映射到一個型別化物件,這一切都是在您可以對資料進行任何有用的操作之前完成的。 IronXL通過一個單一的API處理每個步驟,這個API同樣適用於CSV、XLSX和TSV文件,因此您可以將時間花在應用程式邏輯上而不是字串分割的邊緣情況上。

開始免費試用,以便在您自己的環境中測試這些程式碼範例。

如何在.NET專案中安裝IronXL?

在撰寫任何解析程式碼之前,請將IronXL新增到您的項目中。 在Visual Studio中的包管理器控制台或您的項目目錄中的終端中打開,並運行以下命令之一:

Install-Package IronXL.Excel

該包針對.NET 10, .NET 6+, .NET Framework 4.6.2+,和.NET Standard 2.0,因此適合任何現代項目型別。 伺服器上不需要安裝Microsoft Office。 在還原包後,在調用該程式庫的任何文件的頂部新增using IronXL;

有關詳細的安裝選項,包括全域工具安裝和CI/CD管道配置,請存取IronXL安裝指南

在ASP.NET Core中如何導入CSV文件?

在ASP.NET Core中導入CSV文件需要從伺服器中讀取文件流,解析每一行,並將值映射到模型類。 雖然有些開發人員會使用手動StreamReader實現或第三方包,但IronXL提供了一種單一的方法處理CSV文件及Excel格式,無需額外配置。

以下程式碼顯示如何使用IronXL的WorkBook.LoadCSV方法載入CSV文件:

using IronXL;

// Load the CSV file directly using the full file path
var csv = WorkBook.LoadCSV("products.csv");
WorkSheet worksheet = csv.DefaultWorkSheet;

// Access CSV data by iterating through rows
foreach (var row in worksheet.Rows)
{
    string productName = row.Columns[1].StringValue;
    decimal price = row.Columns[2].DecimalValue;
    Console.WriteLine($"Product: {productName}, Price: {price}");
}
using IronXL;

// Load the CSV file directly using the full file path
var csv = WorkBook.LoadCSV("products.csv");
WorkSheet worksheet = csv.DefaultWorkSheet;

// Access CSV data by iterating through rows
foreach (var row in worksheet.Rows)
{
    string productName = row.Columns[1].StringValue;
    decimal price = row.Columns[2].DecimalValue;
    Console.WriteLine($"Product: {productName}, Price: {price}");
}
Imports IronXL

' Load the CSV file directly using the full file path
Dim csv = WorkBook.LoadCSV("products.csv")
Dim worksheet As WorkSheet = csv.DefaultWorkSheet

' Access CSV data by iterating through rows
For Each row In worksheet.Rows
    Dim productName As String = row.Columns(1).StringValue
    Dim price As Decimal = row.Columns(2).DecimalValue
    Console.WriteLine($"Product: {productName}, Price: {price}")
Next
$vbLabelText   $csharpLabel

瞭解WorkBook.LoadCSV方法

WorkBook.LoadCSV方法讀取CSV文件並建立一個工作表,其中每行變成一行,每個分隔的值變成一個單元格。 IronXL會自動檢測分隔符(逗號、分號或製表符)並處理在值中包含逗號的引號字段。 對於標準CSV文件,您不需要手動配置分隔符。

StringValue, DecimalValue, IntValue, 還有decimal.Parse進行手動解析。 當一個單元格為空或包含未識別的值時,這些存取器返回型別的預設值,而不是拋出異常,這樣可以防止在批量導入操作中出現未處理的錯誤。

這種方法消除了自定義實現所需的錯誤多發的手動字串解析,尤其是針對像逃逸引號、Windows風格的行結束符號和多行單元格值等邊緣情況。 有關支持的格式和分隔符選項的更多詳細資訊,請參見IronXL CSV文件

ASP導入CSV:完整的C#開發人員指南:圖1 - 導入簡單的CSV文件並在控制台中讀取輸出

您如何為CSV資料建立模型類?

將CSV資料映射到強型別物件需要一個鏡像文件結構的模型類。 您將原始字串資料轉換為特定型別,如整數、小數和DateTime值。 對於產品庫存資料,建立一個類,其屬性與每個CSV列匹配:

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public decimal Price { get; set; }
    public int Quantity { get; set; }
}
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public decimal Price { get; set; }
    public int Quantity { get; set; }
}
Public Class Product
    Public Property Id As Integer
    Public Property Name As String = String.Empty
    Public Property Price As Decimal
    Public Property Quantity As Integer
End Class
$vbLabelText   $csharpLabel

將CSV行解析為型別化集合

定義了模型類後,您可以將CSV記錄解析為型別化集合。 以下範例使用迴圈索引跳過標題行,並將每個後續行映射為Product物件:

using IronXL;

WorkBook workbook = WorkBook.LoadCSV("inventory.csv");
WorkSheet ws = workbook.DefaultWorkSheet;
var records = new List<Product>();

// Skip header row (index 0), iterate through data rows
for (int i = 1; i < ws.Rows.Count(); i++)
{
    var row = ws.Rows[i];
    var product = new Product
    {
        Id = row.Columns[0].IntValue,
        Name = row.Columns[1].StringValue,
        Price = row.Columns[2].DecimalValue,
        Quantity = row.Columns[3].IntValue
    };
    records.Add(product);
}

Console.WriteLine($"Loaded {records.Count} products.");
using IronXL;

WorkBook workbook = WorkBook.LoadCSV("inventory.csv");
WorkSheet ws = workbook.DefaultWorkSheet;
var records = new List<Product>();

// Skip header row (index 0), iterate through data rows
for (int i = 1; i < ws.Rows.Count(); i++)
{
    var row = ws.Rows[i];
    var product = new Product
    {
        Id = row.Columns[0].IntValue,
        Name = row.Columns[1].StringValue,
        Price = row.Columns[2].DecimalValue,
        Quantity = row.Columns[3].IntValue
    };
    records.Add(product);
}

Console.WriteLine($"Loaded {records.Count} products.");
Imports IronXL

Dim workbook As WorkBook = WorkBook.LoadCSV("inventory.csv")
Dim ws As WorkSheet = workbook.DefaultWorkSheet
Dim records As New List(Of Product)()

' Skip header row (index 0), iterate through data rows
For i As Integer = 1 To ws.Rows.Count() - 1
    Dim row = ws.Rows(i)
    Dim product As New Product With {
        .Id = row.Columns(0).IntValue,
        .Name = row.Columns(1).StringValue,
        .Price = row.Columns(2).DecimalValue,
        .Quantity = row.Columns(3).IntValue
    }
    records.Add(product)
Next

Console.WriteLine($"Loaded {records.Count} products.")
$vbLabelText   $csharpLabel

Product物件。 IronXL的單元格值存取器自動處理型別轉換,包括可選字段的空值處理。

處理可選和可空字段

現實世界的CSV文件通常包含空單元格或可選列。 當單元格為空白時,IronXL的值存取器返回預設值而不是異常。 對於可空型別,您可以使用條件檢查:

// Reading an optional DateTime field
DateTime? lastUpdated = string.IsNullOrEmpty(row.Columns[4].StringValue)
    ? null
    : row.Columns[4].DateTimeValue;
// Reading an optional DateTime field
DateTime? lastUpdated = string.IsNullOrEmpty(row.Columns[4].StringValue)
    ? null
    : row.Columns[4].DateTimeValue;
' Reading an optional DateTime field
Dim lastUpdated As DateTime? = If(String.IsNullOrEmpty(row.Columns(4).StringValue), Nothing, row.Columns(4).DateTimeValue)
$vbLabelText   $csharpLabel

這種模式使您的導入程式碼保持防禦性,而不需要將每個單元格存取包裝在try-catch塊中。 有關處理複雜資料型別和大文件的指導,請參見IronXL WorkSheet文件

您如何在Web API中處理CSV文件上傳?

構建一個接受來自瀏覽器的CSV文件上傳的API端點需要結合ASP.NET Core的IFormFile和IronXL的解析能力。 以下程式碼演示了一個完整的控制器實現,解析上傳的文件並返回JSON響應:

using IronXL;
using Microsoft.AspNetCore.Mvc;

[Route("api/[controller]")]
[ApiController]
public class CsvController : ControllerBase
{
    [HttpPost("upload")]
    public async Task<IActionResult> UploadCsv(IFormFile file)
    {
        if (file == null || file.Length == 0)
            return BadRequest("Please upload a valid CSV file.");

        try
        {
            using var stream = new MemoryStream();
            await file.CopyToAsync(stream);
            stream.Position = 0;

            WorkBook workbook = WorkBook.Load(stream, "csv");
            WorkSheet ws = workbook.DefaultWorkSheet;
            var records = new List<Product>();

            // Skip header row, iterate through data rows
            for (int i = 1; i < ws.Rows.Count(); i++)
            {
                var row = ws.Rows[i];
                records.Add(new Product
                {
                    Id = row.Columns[0].IntValue,
                    Name = row.Columns[1].StringValue,
                    Price = row.Columns[2].DecimalValue,
                    Quantity = row.Columns[3].IntValue
                });
            }

            return Ok(new
            {
                message = "Import successful",
                count = records.Count,
                data = records
            });
        }
        catch (Exception ex)
        {
            return BadRequest($"Error processing file: {ex.Message}");
        }
    }
}
using IronXL;
using Microsoft.AspNetCore.Mvc;

[Route("api/[controller]")]
[ApiController]
public class CsvController : ControllerBase
{
    [HttpPost("upload")]
    public async Task<IActionResult> UploadCsv(IFormFile file)
    {
        if (file == null || file.Length == 0)
            return BadRequest("Please upload a valid CSV file.");

        try
        {
            using var stream = new MemoryStream();
            await file.CopyToAsync(stream);
            stream.Position = 0;

            WorkBook workbook = WorkBook.Load(stream, "csv");
            WorkSheet ws = workbook.DefaultWorkSheet;
            var records = new List<Product>();

            // Skip header row, iterate through data rows
            for (int i = 1; i < ws.Rows.Count(); i++)
            {
                var row = ws.Rows[i];
                records.Add(new Product
                {
                    Id = row.Columns[0].IntValue,
                    Name = row.Columns[1].StringValue,
                    Price = row.Columns[2].DecimalValue,
                    Quantity = row.Columns[3].IntValue
                });
            }

            return Ok(new
            {
                message = "Import successful",
                count = records.Count,
                data = records
            });
        }
        catch (Exception ex)
        {
            return BadRequest($"Error processing file: {ex.Message}");
        }
    }
}
Imports IronXL
Imports Microsoft.AspNetCore.Mvc
Imports System.IO
Imports System.Threading.Tasks

<Route("api/[controller]")>
<ApiController>
Public Class CsvController
    Inherits ControllerBase

    <HttpPost("upload")>
    Public Async Function UploadCsv(file As IFormFile) As Task(Of IActionResult)
        If file Is Nothing OrElse file.Length = 0 Then
            Return BadRequest("Please upload a valid CSV file.")
        End If

        Try
            Using stream As New MemoryStream()
                Await file.CopyToAsync(stream)
                stream.Position = 0

                Dim workbook As WorkBook = WorkBook.Load(stream, "csv")
                Dim ws As WorkSheet = workbook.DefaultWorkSheet
                Dim records As New List(Of Product)()

                ' Skip header row, iterate through data rows
                For i As Integer = 1 To ws.Rows.Count() - 1
                    Dim row = ws.Rows(i)
                    records.Add(New Product With {
                        .Id = row.Columns(0).IntValue,
                        .Name = row.Columns(1).StringValue,
                        .Price = row.Columns(2).DecimalValue,
                        .Quantity = row.Columns(3).IntValue
                    })
                Next

                Return Ok(New With {
                    .message = "Import successful",
                    .count = records.Count,
                    .data = records
                })
            End Using
        Catch ex As Exception
            Return BadRequest($"Error processing file: {ex.Message}")
        End Try
    End Function
End Class
$vbLabelText   $csharpLabel

配置端點和多部分表單

為了讓[HttpPost("upload")]動作接受文件上傳,項目必須支持多部分表單資料。 在app.MapControllers()。 端點可以在/api/csv/upload存取。

從瀏覽器表單測試時,將表單的multipart/form-data並使用文件輸入元素。 對於API客戶端,如Postman,在請求體中選擇"form-data",新增一個名為file的鍵,並附加CSV文件。控制器返回一個包含記錄數和解析資料陣列的JSON物件,客戶端的JavaScript可以立即使用。

ASP導入CSV:完整的C#開發者指南:圖片2 - 成功輸出與從導入的CSV文件中讀取的資料

在解析之前驗證文件型別

在將流傳遞給IronXL之前,驗證文件擴展名以拒絕非CSV上傳:

var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
if (extension != ".csv" && extension != ".txt")
    return BadRequest("Only CSV files are accepted.");
var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
if (extension != ".csv" && extension != ".txt")
    return BadRequest("Only CSV files are accepted.");
Dim extension As String = Path.GetExtension(file.FileName).ToLowerInvariant()
If extension <> ".csv" AndAlso extension <> ".txt" Then
    Return BadRequest("Only CSV files are accepted.")
End If
$vbLabelText   $csharpLabel

此檢查防止格式錯誤的二進制資料到達解析器,並向API使用者提供清晰的錯誤資訊。 您可以擴展此驗證使用file.ContentType檢查MIME型別,以更嚴格地執行。

您如何將CSV資料保存到資料庫?

在將CSV文件解析為型別物件後,您通常將記錄保存到資料庫。 以下範例使用Entity Framework Core的AddRangeAsync進行批量插入,擴展了服務層模式:

using IronXL;

public class CsvImportService
{
    private readonly AppDbContext _context;

    public CsvImportService(AppDbContext context)
    {
        _context = context;
    }

    public async Task<int> ImportProductsAsync(Stream csvStream)
    {
        WorkBook workbook = WorkBook.LoadCSV(csvStream);
        WorkSheet ws = workbook.DefaultWorkSheet;
        var products = new List<Product>();

        foreach (var row in ws.Rows.Skip(1))
        {
            products.Add(new Product
            {
                Id = row.Columns[0].IntValue,
                Name = row.Columns[1].StringValue,
                Price = row.Columns[2].DecimalValue,
                Quantity = row.Columns[3].IntValue
            });
        }

        await _context.Products.AddRangeAsync(products);
        return await _context.SaveChangesAsync();
    }
}
using IronXL;

public class CsvImportService
{
    private readonly AppDbContext _context;

    public CsvImportService(AppDbContext context)
    {
        _context = context;
    }

    public async Task<int> ImportProductsAsync(Stream csvStream)
    {
        WorkBook workbook = WorkBook.LoadCSV(csvStream);
        WorkSheet ws = workbook.DefaultWorkSheet;
        var products = new List<Product>();

        foreach (var row in ws.Rows.Skip(1))
        {
            products.Add(new Product
            {
                Id = row.Columns[0].IntValue,
                Name = row.Columns[1].StringValue,
                Price = row.Columns[2].DecimalValue,
                Quantity = row.Columns[3].IntValue
            });
        }

        await _context.Products.AddRangeAsync(products);
        return await _context.SaveChangesAsync();
    }
}
Imports IronXL

Public Class CsvImportService
    Private ReadOnly _context As AppDbContext

    Public Sub New(context As AppDbContext)
        _context = context
    End Sub

    Public Async Function ImportProductsAsync(csvStream As Stream) As Task(Of Integer)
        Dim workbook As WorkBook = WorkBook.LoadCSV(csvStream)
        Dim ws As WorkSheet = workbook.DefaultWorkSheet
        Dim products As New List(Of Product)()

        For Each row In ws.Rows.Skip(1)
            products.Add(New Product With {
                .Id = row.Columns(0).IntValue,
                .Name = row.Columns(1).StringValue,
                .Price = row.Columns(2).DecimalValue,
                .Quantity = row.Columns(3).IntValue
            })
        Next

        Await _context.Products.AddRangeAsync(products)
        Return Await _context.SaveChangesAsync()
    End Function
End Class
$vbLabelText   $csharpLabel

將服務接入依賴注入

CsvImportService,以便控制器可以通過構造函式注入請求它:

builder.Services.AddScoped<CsvImportService>();
builder.Services.AddScoped<CsvImportService>();
$vbLabelText   $csharpLabel

然後更新控制器構造函式,以接受服務並調用ImportProductsAsync,而不是內聯構建列表。此分離使控制器動作保持簡潔,並將資料存取邏輯移到可測試的服務類中。 Entity Framework Core將INSERT語句,這對於包含數千行的CSV文件的性能表現良好。

對於非常大的導入(成千上萬行),考慮使用EF Core的批量擴展或原始SQLBULK INSERT語句,以減少對資料庫的回合次數。

如何使用IronXL將資料導出回CSV?

IronXL不僅限於讀取CSV文件,還能寫入它們。 SaveAsCsv方法將任何工作表導出到CSV文件,這對於生成報告或將資料發送到下游系統很有用:

using IronXL;

WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLS);
WorkSheet ws = workbook.DefaultWorkSheet;

// Write headers
ws["A1"].Value = "Id";
ws["B1"].Value = "Name";
ws["C1"].Value = "Price";

// Write data rows
ws["A2"].Value = 1;
ws["B2"].Value = "Widget A";
ws["C2"].Value = 9.99;

ws["A3"].Value = 2;
ws["B3"].Value = "Widget B";
ws["C3"].Value = 14.49;

// Save as CSV
workbook.SaveAsCsv("export.csv");
Console.WriteLine("CSV export complete.");
using IronXL;

WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLS);
WorkSheet ws = workbook.DefaultWorkSheet;

// Write headers
ws["A1"].Value = "Id";
ws["B1"].Value = "Name";
ws["C1"].Value = "Price";

// Write data rows
ws["A2"].Value = 1;
ws["B2"].Value = "Widget A";
ws["C2"].Value = 9.99;

ws["A3"].Value = 2;
ws["B3"].Value = "Widget B";
ws["C3"].Value = 14.49;

// Save as CSV
workbook.SaveAsCsv("export.csv");
Console.WriteLine("CSV export complete.");
Imports IronXL

Dim workbook As WorkBook = WorkBook.Create(ExcelFileFormat.XLS)
Dim ws As WorkSheet = workbook.DefaultWorkSheet

' Write headers
ws("A1").Value = "Id"
ws("B1").Value = "Name"
ws("C1").Value = "Price"

' Write data rows
ws("A2").Value = 1
ws("B2").Value = "Widget A"
ws("C2").Value = 9.99

ws("A3").Value = 2
ws("B3").Value = "Widget B"
ws("C3").Value = 14.49

' Save as CSV
workbook.SaveAsCsv("export.csv")
Console.WriteLine("CSV export complete.")
$vbLabelText   $csharpLabel

預設情況下,導出的文件使用逗號分隔符。 對於歐洲地區常見的分號分隔文件,調用SaveAsCsv("export.csv", ";"),帶有顯式分隔符參數。 您還可以保存到File(stream, "text/csv", "export.csv")將結果作為文件下載從API端點返回。

有關導出選項的完整參考,請存取IronXL保存和導出文件

為什麼IronXL比手動CSV解析更好?

手動CSV解析看起來很簡單,直到您遇到邊緣情況:值包含在引號中的逗號、嵌入在單元格中的換行符、轉義引號和UTF-8文件開頭的字節順序標記。 在自定義StreamReader迴圈中正確處理所有這些情況需要大量測試和持續維護。

IronXL在內部解決了所有這些情況。 比較兩種方法顯示出明顯的優勢:

IronXL vs. 手動StreamReader用於C#中的CSV解析
功能 IronXL 手動StreamReader
自動分隔符檢測 不 -- 必須手動配置
引號字段處理 內建 需要自定義邏輯
型別轉換(int、decimal、DateTime) 內建存取器 需要Parse/TryParse調用
多行單元格值 自動處理 正確實現困難
BOM處理 自動的 需要StreamReader配置
Excel格式支持(XLSX、XLS) 相同API 需要單獨的程式庫
導出到CSV SaveAsCsv方法 需要單獨的寫邏輯

跨格式一致性

IronXL的一個實用優勢是相同的WorkBook.Load和工作表迭代模式適用於XLSX、XLS、ODS和CSV文件。 如果您的應用程式需要接受使用者的多個電子表格格式,您可以在不更改解析邏輯的情況下在格式之間切換。 將文件流傳遞給WorkBook.Load,IronXL根據文件簽名自動檢測格式。

這種跨格式API意味著您編寫並測試一個程式碼路徑,而不是為CSV和Excel維護單獨的實現。 有關支持格式的完整列表,請參見IronXL支持的文件格式頁面。

大文件的性能考量

對於小於100 MB的CSV文件,IronXL無需任何調整即可良好運行。 對於更大的文件,考慮這些策略:

  • 從路徑載入文件而不是將其複製到MemoryStream以減少記憶體分配。
  • 在插入資料庫時批量處理行,而不是在第一次插入前收集所有記錄。
  • 使用Product物件。

IronXL性能指南涵蓋了包括並行處理和流模式在內的高容量導入場景的其他優化。

您接下來的步驟是什麼?

您現在擁有ASP.NET Core中CSV導入的每一階段的工作模式:安裝程式庫、從磁盤或上傳流載入文件、將行映射到型別化模型物件、使用Entity Framework Core將記錄保存到資料庫,並在需要時將資料導出回CSV。

要在此基礎上構建,探索以下資源:

在您的項目中使用IronXL,除了CSV外,增加對XLSX上傳的支持不需要額外的程式碼更改 -- 相同WorkBook.Load調用處理兩者。 這種一致性意味著您可以隨著應用程式需求的增長,逐步擴展您的導入端點的功能集。

常見問題

我可以如何在ASP.NET Core應用程式中匯入CSV檔案?

您可以使用IronXL在ASP.NET Core應用程式中匯入CSV文件,處理檔案上傳、解析CSV資料及將其映射到模型類別物件。IronXL提供API以有效地促進這些任務。

使用IronXL在C#中進行CSV匯入有什麼好處?

IronXL提供的API簡化了CSV檔案匯入的過程,讓您可以輕鬆地解析資料,將其映射到模型並將記錄轉換為JSON,非常適合資料驅動的應用程式。

IronXL能將CSV資料解析為模型類別物件嗎?

是的,IronXL能將CSV資料解析為模型類別物件,讓您在.NET應用程式中能有效地處理結構化資料。

IronXL在匯入CSV檔案時如何幫助進行資料庫整合?

IronXL通過允許您解析CSV資料並將其映射到可以輕鬆插入或更新到資料庫中的模型物件來幫助進行資料庫整合。

使用IronXL可以將CSV記錄轉換為JSON嗎?

可以,使用IronXL,您可以將CSV記錄轉換為JSON格式,這對建立網頁API或與前端應用整合非常有用。

IronXL除了CSV還能處理哪些文件格式?

除了CSV,IronXL還能處理多種Excel文件格式如XLSX、XLS等,提供針對不同電子表需求的靈活性。

IronXL支援大型CSV檔案匯入嗎?

IronXL旨在高效處理大型CSV檔案匯入,確保在資料驅動應用程式中的效能與可靠性。

Curtis Chau
技術作家

Curtis Chau擁有Carleton大學的電腦科學學士學位,專精於前端開發,擁有Node.js、TypeScript、JavaScript和React的專業知識。Curtis熱衷於建立直觀且美觀的使用者介面,喜愛使用現代框架並建立結構良好、視覺吸引力的手冊。

除了開發,Curtis對物聯網(IoT)有濃厚的興趣,探索創新的方法來整合硬體和軟體。在空閒時間,他喜歡玩遊戲和建立Discord機器人,結合他對技術的熱愛與創造力。

Iron 支援團隊

我們線上24小時,每週5天。
聊天
電子郵件
給我打電話