c# - 从文本文件中读取一行,然后用新文本 C# 替换同一行
问题描述
我试图弄清楚如何在通过 ID 搜索文本文件中替换一行,然后编写新信息来替换它。它适用于客户管理系统,此特定方法是通过 ID 搜索客户,返回搜索到的信息,然后修改相同的信息以将其写回。保存信息的 CSV 设置如下:
[ID][Title][firstName][lastName][Gender][DOB]
[0][夫人][简][Doe][女][1/1/1990]
[1][先生][约翰][Doe][男][1991 年 1 月 1 日]
[2][Ms][Sarah][Doe][Female][1/1/2010]
我有一种感觉StreamWriter
被错误地使用了,因为我可以把所有东西都放进去,当我把断点放进去调试时,作者在底部把它全部捡起来,但是一旦我按下回车,什么都没有发生,数据就消失了。或者我可能没有在正确的位置收集用户输入。我已经对代码进行了格式化,以便更容易获取和调试:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
public class Customer
{
public int ID { get; set; }
public string Title { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Gender { get; set; }
public DateTime DOB { get; set; }
}
static void Main(string[] args)
{
const char DELIM = ',';
const int END = 0;
const string FILENAME = "D:\\customers.csv";
FileStream inFile = new FileStream(FILENAME, FileMode.Open, FileAccess.ReadWrite);
StreamWriter writer = new StreamWriter(inFile);
{
while (true)
{
Console.WriteLine(" **Type " + END + " To Quit** Enter Customer ID Number> ");
var ID = Convert.ToInt32(Console.ReadLine());
if (ID == END) break;
inFile.Position = 0;
Console.WriteLine("{0,5}{1,10}{2,15}{3,15}{4,15}{5,25}\n", "ID", "Title", "First Name", "Last Name", "Gender", "DOB");
foreach (var customer in GetCustomers(inFile, DELIM).Where(x => x.ID == ID))
{
Console.WriteLine("{0,5}{1,10}{2,15}{3,15}{4,15}{5,25}\n", customer.ID, customer.Title, customer.FirstName, customer.LastName, customer.Gender, customer.DOB);
Write(" Title> ");
customer.Title = ReadLine();
Write(" First Name> ");
customer.FirstName = ReadLine();
Write(" Last Name> ");
customer.LastName = ReadLine();
Write(" Gender> ");
customer.Gender = ReadLine();
Write(" Date Of Birth> ");
customer.DOB = Convert.ToDateTime(ReadLine());
writer.WriteLine(customer.ID + DELIM + customer.Title + DELIM + customer.FirstName + DELIM + customer.LastName + DELIM + customer.Gender + DELIM + customer.DOB);
}
}
writer.Close();
inFile.Close();
}
}
static IEnumerable<Customer> GetCustomers(Stream input, char separator)
{
using (var reader = new StreamReader(input))
{
// read header
reader.ReadLine();
while (true)
{
var line = reader.ReadLine();
if (line == null) yield break;
var fields = line.Split(separator);
yield return new Customer
{
ID = Convert.ToInt32(fields[0]),
Title = fields[1],
FirstName = fields[2],
LastName = fields[3],
Gender = fields[4],
DOB = Convert.ToDateTime(fields[5])
};
}
}
}
}
}
任何帮助将不胜感激
解决方案
首先,您真的不应该在接受用户输入的同时写入文件。您应该读取数据、更新数据,然后保存数据。不要把它们混在一起。
接下来,不要共享流。
这是我将如何做到这一点:
static IEnumerable<Customer> GetCustomers(string file, char separator)
{
return
from line in File.ReadLines(file).Skip(1)
let fields = line.Split(separator)
select new Customer()
{
ID = Convert.ToInt32(fields[0]),
Title = fields[1],
FirstName = fields[2],
LastName = fields[3],
Gender = fields[4],
DOB = Convert.ToDateTime(fields[5])
};
}
static void SaveCustomers(string file, char separator, string[] headers, IEnumerable<Customer> customers)
{
IEnumerable<string[]> parts =
from c in customers
select new []
{
c.ID.ToString(),
c.Title,
c.FirstName,
c.LastName,
c.Gender,
c.DOB.ToShortDateString()
};
IEnumerable<string> lines =
from ps in new [] { headers }.Concat(parts)
select String.Join(separator.ToString(), ps);
File.WriteAllLines(file, lines);
}
static void Main(string[] args)
{
const char DELIM = ',';
const int END = 0;
const string FILENAME = "D:\\customer.csv";
string[] headers = new [] { "ID", "Title", "First Name", "Last Name", "Gender", "DOB" };
List<Customer> customers = GetCustomers(FILENAME, DELIM).ToList(); //Must call `.ToList()` to force reading the file.
var ID = -1;
while (ID != 0)
{
Console.WriteLine(" **Type " + END + " To Quit** Enter Customer ID Number> ");
ID = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("{0,5}{1,10}{2,15}{3,15}{4,15}{5,25}\n", headers);
foreach (var customer in customers.Where(x => x.ID == ID))
{
Console.WriteLine("{0,5}{1,10}{2,15}{3,15}{4,15}{5,25}\n", customer.ID, customer.Title, customer.FirstName, customer.LastName, customer.Gender, customer.DOB);
Console.Write(" Title> ");
customer.Title = Console.ReadLine();
Console.Write(" First Name> ");
customer.FirstName = Console.ReadLine();
Console.Write(" Last Name> ");
customer.LastName = Console.ReadLine();
Console.Write(" Gender> ");
customer.Gender = Console.ReadLine();
Console.Write(" Date Of Birth> ");
customer.DOB = Convert.ToDateTime(Console.ReadLine());
}
}
// Always save to a temporary file & then swap.
var saveFileName = FILENAME.Replace(".csv", ".csv-temp");
if (File.Exists(saveFileName))
{
File.Delete(saveFileName);
}
SaveCustomers(saveFileName, DELIM, headers, customers);
if (File.Exists(saveFileName) && File.Exists(FILENAME))
{
File.Delete(FILENAME);
File.Move(saveFileName, FILENAME);
}
}
推荐阅读
- css - primeng p-dialog 样式覆盖
- javascript - 在控制台 javascript 函数中处理错误和日志消息
- merge - 用于更改跟踪表的 Snowflake snowsql 合并语句 - 当目标/源不匹配时,不允许
- r - barplot ggplot中的联合百分比
- python - 在没有 root 权限的情况下在 CentOS 上安装 gcc 时出错,配置:错误:在 $PATH 中找不到可接受的 C 编译器
- typescript - 多态 this 关键字在方法体内没有按预期工作
- r - 根据每组中的百分比为 R 中的列分配一个值
- javascript - Expo Go Stripe:本机模块不能为空
- javascript - 单击后 CSS 在 React JS 中不起作用,在页面重新加载后它正在工作
- python - .txt 文件中每一行的编号