首页 > 解决方案 > 从文本文件中读取一行,然后用新文本 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])
                    };
                }
            }
        }
    }
}

任何帮助将不胜感激

标签: c#streamwriter

解决方案


首先,您真的不应该在接受用户输入的同时写入文件。您应该读取数据、更新数据,然后保存数据。不要把它们混在一起。

接下来,不要共享流。

这是我将如何做到这一点:

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);
    }
}

推荐阅读