除資料庫外,文字檔 (Flat Files) 為常見資料儲存格式。本教學涵蓋 .txt、.csv、.xml 檔案讀取、解析與動態呈現,適合小型資料、匯入匯出、日誌分析、設定檔等場景。
Server.MapPath("~/App_Data/file.txt") 取得實體路徑在 ~/App_Data/Persons.txt 建立內容:
George,Lucas
Steven,Spielberg
Alfred,Hitchcock
@{
var dataFile = Server.MapPath("~/App_Data/Persons.txt");
var userData = File.ReadAllLines(dataFile); // 回傳 string[],每行一個元素
}
<!DOCTYPE html>
<html><body>
<h1>Reading Data from a File</h1>
@foreach (var dataLine in userData) {
@foreach (var dataItem in dataLine.Split(',')) {
@dataItem <text> </text>
}
<br />
}
</body></html>
關鍵方法解析:
Server.MapPath("~/App_Data/Persons.txt"):虛擬路徑轉實體路徑File.ReadAllLines(path):一次讀取所有行至字串陣列 (小檔案適用)dataLine.Split(','):依逗號分割欄位<text> </text>:Razor 顯式輸出 HTML 實體/文字@using System.IO
@{
var dataFile = Server.MapPath("~/App_Data/large_log.txt");
}
<h1>Large File Streaming</h1>
<pre>
@using (var reader = new StreamReader(dataFile, Encoding.UTF8)) {
string line;
int lineNumber = 0;
while ((line = reader.ReadLine()) != null) {
lineNumber++;
if (lineNumber > 100) break; // 示範只讀前 100 行
@line <br />
}
}
</pre>
StreamReader 逐行讀取,不將整個檔案載入記憶體,適合 GB 級日誌檔案。
Excel 另存為 CSV (逗號分隔值) 後,可直接套用上述邏輯:
@{
var csvFile = Server.MapPath("~/App_Data/products.csv");
var lines = File.ReadAllLines(csvFile);
var headers = lines[0].Split(',');
var dataRows = lines.Skip(1).Select(l => l.Split(',')).ToList();
}
<table class="table">
<thead><tr>@foreach (var h in headers) { <th>@h</th> }</tr></thead>
<tbody>
@foreach (var row in dataRows) {
<tr>@foreach (var cell in row) { <td>@cell</td> }</tr>
}
</tbody></table>
@using Microsoft.VisualBasic.FileIO
@{
var csvFile = Server.MapPath("~/App_Data/complex.csv");
var records = new List<string[]>();
using (var parser = new TextFieldParser(csvFile)) {
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
parser.HasFieldsEnclosedInQuotes = true;
while (!parser.EndOfData) {
records.Add(parser.ReadFields());
}
}
}
需參考 Microsoft.VisualBasic.dll,正確處理欄位包含逗號、雙引號、跨行等 RFC 4180 標準情況。
@{
var logFile = Server.MapPath("~/App_Data/app.log");
var logEntry = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} | {Request.UserHostAddress} | {Request.Url}";
// 附加模式寫入 (非覆蓋)
File.AppendAllText(logFile, logEntry + Environment.NewLine, Encoding.UTF8);
}
@{
var db = Database.Open("SmallBakery");
var products = db.Query("SELECT Id, Name, Price FROM Product");
var csvLines = new List<string> { "Id,Name,Price" };
csvLines.AddRange(products.Select(p => $"{p.Id},{p.Name},{p.Price}"));
File.WriteAllLines(Server.MapPath("~/App_Data/export_products.csv"), csvLines, Encoding.UTF8);
}
@functions {
public static string SafeMapPath(string virtualPath) {
var fullPath = Server.MapPath(virtualPath);
var appRoot = Server.MapPath("~");
// 確保解析路徑在應用程式根目錄下
if (!fullPath.StartsWith(appRoot, StringComparison.OrdinalIgnoreCase)) {
throw new SecurityException("Invalid path access attempt");
}
return fullPath;
}
}
絕不直接使用使用者輸入路徑,務必驗證路徑在允許目錄範圍內。
@using System.Xml.Linq
@{
var xmlFile = Server.MapPath("~/App_Data/config.xml");
var doc = XDocument.Load(xmlFile);
var settings = doc.Descendants("setting")
.ToDictionary(x => x.Attribute("key").Value, x => x.Attribute("value").Value);
}
<h1>Configuration Settings</h1>
@foreach (var kvp in settings) {
<p><strong>@kvp.Key:</strong> @kvp.Value</p>
}
XDocument (LINQ to XML) 提供現代、可讀的 XML 查詢與操作 API。