解决  访问txt文件并更改各个字段?

袜子1992

知名会员
已加入
2020年5月20日
留言内容
57
编程经验
Beginner
我设法更改了各个字段,但最终删除了文件中的所有其他内容。我只想编辑一个字段。任何帮助将不胜感激。谢谢

这是我当前的代码:

C#:
  public static void UpdatePatientData()
        {
            string detail, choice;
       
            Console.WriteLine("Please enter the ID of the customer you would like to Update: ");
            ID = Console.ReadLine();

            string[] Name = File.ReadAllText("user.txt").Split('|'); // each field will represent an index from 1-4

            for (int i = 0; i < Name.Length; i++)
            {
                if (Name[i].Contains(ID))
                {
                    // here is where i would like to edit the name/gender/age etc and write it back to the file

                }
            }
        }
 
Last edited:

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,530
地点
弗吉尼亚州切萨皮克
编程经验
10+
对于文本文件,没有插入或删除字段。您必须使用所做的修改来重写整个文件。

似乎您确实应该使用数据库时却使用文本分隔文件。

或者,如果您确实要使用文本文件,请确保使用固定大小的字段。这样,您可以查找到特定行,然后覆盖该行中的字段。
 

袜子1992

知名会员
已加入
2020年5月20日
留言内容
57
编程经验
Beginner
对于文本文件,没有插入或删除字段。您必须使用所做的修改来重写整个文件。

似乎您确实应该使用数据库时却使用文本分隔文件。

或者,如果您确实要使用文本文件,请确保使用固定大小的字段。这样,您可以查找到特定行,然后覆盖该行中的字段。
我目前正在制作一个控制台应用程序来保存患者数据,所以我认为文本文件最合适吗?

如果我将每个对象都保存到字典中,是否可行?

必要时通过字典删除/编辑每个字段

然后将所有数据改写回txt文件
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,523
地点
悉尼,澳大利亚
编程经验
10+
我目前正在制作一个控制台应用程序来保存患者数据,所以我认为文本文件最合适吗?
除非数据量很小,否则数据库将更合适。即使数据量很小,使用数据库也可能更合适,因为这将教您如何使用数据库,这几乎就是您将要做的任何事情"real"应用。文本文件对于在系统之间传输数据很有用,但对于在系统中存储数据则不是那么有用。
如果我将每个对象都保存到字典中,是否可行?

必要时通过字典删除/编辑每个字段

然后将所有数据改写回txt文件
It certainly would. The acts of loading, editing and saving the data are then completely independent, so you can tackle each one that way. Editing a Dictionary has nothing to do with text files.

If you are going to use delimited files then you might consider using a dedicated CSV library, for the reading at least. One option is to reference the Microsoft.VisualBasic.dll assembly and use the TextFieldParser class for reading the data. There are also various third-party options, often available as NuGet packages.
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,926
地点
英国
编程经验
10+
正确地,您应该使用数据库。文本文件似乎不切实际,我希望至少使用Json文件来代替。但那只是我的个人意见。
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,530
地点
弗吉尼亚州切萨皮克
编程经验
10+
即使使用JSON文件,他仍然需要完全重写该文件。他不能随便在文件中的特定位置查找并覆盖一个值(除非新值与旧值具有完全相同的字符数)。
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,530
地点
弗吉尼亚州切萨皮克
编程经验
10+
我目前正在制作一个控制台应用程序来保存患者数据,所以我认为文本文件最合适吗?

如果我将每个对象都保存到字典中,是否可行?

必要时通过字典删除/编辑每个字段

然后将所有数据改写回txt文件
用列表代替字典也可以。
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,926
地点
英国
编程经验
10+
您必须使用所做的修改来重写整个文件。
不,他们没有。为什么?查找和替换有什么问题?
他不能随便在文件中的特定位置查找并覆盖一个值(除非新值与旧值具有完全相同的字符数)。
同样,为什么不呢?节点可以更换。如果我们足够努力,一切皆有可能。谁又说了彼得潘。

如果您足够努力,肯定可以做任何事情。好像您使它听起来比实际更难。

编辑:固定错别字
 
Last edited:

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,926
地点
英国
编程经验
10+
别忘了您可以从类数据创建一个Json对象,反之亦然,从Json数据创建一个类对象,等等。通过使用该类项目的列表(json对象),您将积累一个类项目的列表-即列表<PatientInfo>。如果您问我,似乎并非没有可能,而且更实用。
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,530
地点
弗吉尼亚州切萨皮克
编程经验
10+
不,他们没有。为什么?查找和替换有什么问题?

同样,为什么不呢?节点可以更换。如果我们足够努力,一切皆有可能。谁又说了彼得潘。

如果您足够努力,肯定可以做任何事情。好像您使它听起来比实际更难。

编辑:固定错别字
是的,可以在内存中替换节点。但是如何在不覆盖整个文件的情况下将那些节点放回文件中?
 

袜子1992

知名会员
已加入
2020年5月20日
留言内容
57
编程经验
Beginner
C#:
    字符串[]行= System.IO.File.ReadAllLines("patinfo.csv");
            StreamWriter Write = new System.IO.StreamWriter("temp.csv");
                               
            for (int i = 0; i < lines.Length; i++)          
            {
                string[] fields = lines[i].Split(',');

                if (fields[0] == ID)
                {                                    
                    for (int k = 1; k <= fields.Length; k++)
                    {
                        if(k == choice)
                        {
                            fields[choice-1] = change;
                            Write.WriteLine(fields[0] + "," + fields[1] + "," + fields[2] + "," + fields[3] + "," + fields[4] + "," + fields[5]); 
                        }
                    }            
                }
                else
                {
                    if (!edited )
                    {
                        Write.WriteLine(fields[0] + "," + fields[1] + "," + fields[2]+ "," + fields[3] + "," + fields[4] + "," + fields[5]);             
                    }
                   
                }                                  
            }      
            Write.Close();
 
Last edited:

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,926
地点
英国
编程经验
10+
请不要为已经进行故障排除的相同代码启动新线程。主题已合并。
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,926
地点
英国
编程经验
10+
这是使用Json进行的钝但快速的代码重写。我更喜欢这样做,而不是使用CSV推荐 @jmcilhinney 就个人而言,那只是我。使用CSV文件没有任何问题,但最好使用Json。您不必使用此示例。我只是将其作为工作中的(正在进行的工作)提供,而不是您当前的方法,并且您可以根据自己的喜好轻松对其进行修改。

在第12行上放置一个断点,并逐步执行代码,直到第18行终止。如果需要,可以在我的签名中找到调试教程。

This : var patient1 = WithPatient(0, "Tom", 33, Patient.GenderChoice.Male.ToString(), "666 Home Vile St.", "052895566", 0); calls the WithPatient method which determines the course of action to take based on the last parameter passed to the method. Ie. If the value is 0, it will call the constructor in the Patient class and creates a new Patient each time. We created two patients, and here is your second :
var patient2 = WithPatient(1, "Bob", 36, Patient.GenderChoice.Male.ToString(), "888 Home Vila St.", "052895567", 0); 然后我们更新我们创建的第一位患者。设置新的凭据,例如电话号码和性别更改。

Notice on the WithPatient method, we have an integer on the end of that method. If it's set to 0, it will create a new patient. If it's set to 1, it will update a patient with the new details passed to the method, and then with those details it creates a new Patient by calling the constructor of your Patient class. This takes place on line 24 : 病人 patient = new Patient(id, name, age, gender, address, phonenumber);. Note line 47 requires you to remove the Patient you don't want any longer. Here is the complete code. See the additional notes below this code :

C#:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace CTestConsole
{
    internal static class Program
    {
        public static void Main(string[] args)
        {
            var patient1 = WithPatient(0, "Tom", 33, Patient.GenderChoice.Male.ToString(), "666 Home Vile St.", "052895566", 0);
            var patient2 = WithPatient(1, "Bob", 36, Patient.GenderChoice.Male.ToString(), "888 Home Vila St.", "052895567", 0);
            /* We now have 2 patients in our Dictionary. Now lets update Tom */
            patient1 = WithPatient(0, "Tom", 33, Patient.GenderChoice.Female.ToString(), "999 Lala land", "086997513", 1);

        }
        public static Dictionary<int, Patient> Patients = new Dictionary<int, Patient>();
        static readonly string PathToDBFile = AppDomain.CurrentDomain.BaseDirectory;
        static readonly string FileName = "db.json";
        public static Patient WithPatient(int id, string name, int age, string gender, string address, string phonenumber, int action)
        {
            Patient patient = new Patient(id, name, age, gender, address, phonenumber);
            if (action == 0)
            {
                Patients.Add(patient.ID, patient);
                File.WriteAllText(Path.Combine(PathToDBFile, FileName), JsonConvert.SerializeObject(Patients, Formatting.Indented));
                return patient;
            }
            else if (action == 1)
            {
                string json_Data = File.ReadAllText(Path.Combine(PathToDBFile, FileName));
                Patients.Clear();
                Patients = JsonConvert.DeserializeObject<Dictionary<int, Patient>>(json_Data);

                Patients.Values.Where(x => x.Name == name).Single().Name = name;
                Patients.Values.Where(x => x.Name == name).Single().Age = age;
                Patients.Values.Where(x => x.Name == name).Single().Gender = gender;
                Patients.Values.Where(x => x.Name == name).Single().Address = address;
                Patients.Values.Where(x => x.Name == name).Single().PhoneNumber = phonenumber;
                File.WriteAllText(Path.Combine(PathToDBFile, FileName), JsonConvert.SerializeObject(Patients, Formatting.Indented));
                return patient;
            }
            else if (action == 2)
            {
                /* Read all and remove the one you don't want */
            }
            return null;
        }
    }
    public class Patient
    {
        public Patient(int iD, string name, int age, string gender, string address, string phoneNumber)
        {
            ID = iD;
            Name = name;
            Age = age;
            Gender = gender;
            Address = address;
            PhoneNumber = phoneNumber;
        }
        public int ID { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public string Gender { get; set; }
        public enum GenderChoice
        {
            Male,
            Female
        };
        public string Address { get; set; }
        public string PhoneNumber { get; set; }
    }
}
我使用字典的原因<int, Patient> here and not a List<Patient>仅仅是为了使Json数据更具可读性并且更易于使用。例如,这就是上面的代码创建的内容:
JSON:
{
  "0": {
    "ID": 0,
    "Name": "Tom",
    "Age": 33,
    "Gender": "Female",
    "Address": "999 Lala land",
    "PhoneNumber": "086997513"
  },
  "1": {
    "ID": 1,
    "Name": "Bob",
    "Age": 36,
    "Gender": "Male",
    "Address": "888 Home Vila St.",
    "PhoneNumber": "052895567"
  }
}
但是如果使用列表,您的结构将完全不同。例如。如果我们使用“患者”列表,则数据将看起来像这样(可能不准确):
JSON:
{
  {
    "ID": 0,
    "Name": "Tom",
    "Age": 33,
    "Gender": "Female",
    "Address": "999 Lala land",
    "PhoneNumber": "086997513"
  },
  {
    "ID": 1,
    "Name": "Bob",
    "Age": 36,
    "Gender": "Male",
    "Address": "888 Home Vila St.",
    "PhoneNumber": "052895567"
  }
}
注意到ID已从开始标签中删除:
C#:
  "0": {
    "ID": 0,
这实际上很重要,因为它允许我们稍后在从文件中选择数据时稍后使用该ID,前提是您决定使用这个简单的示例作为开始。尽管如此,它确实有效,并且可能会给您更快的项目开始时间,只需进行少量编辑即可使您自己。

现在,关于p1 /#11上的更新代码。
如果我尝试输入位于第二行或第三行的患者ID,它将不会编辑任何数据。有人知道为什么吗?

单击我的签名上的扰流板,然后按Ctrl + F键入Debug,然后阅读有关如何调试代码的链接。调试是了解所有程序员都应该知道的特质的基本需求。该教程说明了如何对自己的代码进行故障排除,并演示了如何正确使用调试器。请记住,我们在这里为您提供建议并帮助您编写更好的代码。我们不是在这里为您调试代码。如果您自己的代码中有某些您不了解或理解的内容,那么我们很乐意回答有关某些功能为何与您预期的功能不同的直接问题。

是的,可以在内存中替换节点。但是如何在不覆盖整个文件的情况下将那些节点放回文件中?
有几种方法。一个是Regex,但是当您也可以使用一些Linq并以与我们的OP在p1 /#11 @第24行上相同的方式替换一行时,可能会矫kill过正。如果原始海报使用Json,则操作起来会更容易Json结构中的数据。不知何故,我觉得该数据库的设计规模并不是很大。因此,简单地将文件读回到Json不会是一个问题或性能问题。但是,我将深入研究Json文档,以查看是否存在使用Json lib来操纵行的更好的替代方法。
 
Last edited:

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,530
地点
弗吉尼亚州切萨皮克
编程经验
10+
注意,在文章#11中,OP正在重写文件。他从原始文件中读取输入,然后将数据写入临时文件,然后使用临时文件替换原始文件。

这是一个简单的问题:让我们从一个简单的JSON文件开始:
JSON:
{
    "Name" : "Batman"
}

我们想将名称更改为"Bruce Wayne" and get this:
JSON:
{
    "Name" : "Bruce Wayne"
}

原始文件的文件数据如下所示:
C#:
          Offset Bytes                                           Ascii
                 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
          ------ ----------------------------------------------- -----
0000000000000000 7B 0D 0A 20 20 20 20 22 4E 61 6D 65 22 20 3A 20 {��    "Name" :
0000000000000010 22 42 61 74 6D 61 6E 22 0D 0A 7D                "Batman"��}

所需的结果是:
C#:
          Offset Bytes                                           Ascii
                 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
          ------ ----------------------------------------------- -----
0000000000000000 7B 0D 0A 20 20 20 20 22 4E 61 6D 65 22 20 3A 20 {��    "Name" :
0000000000000010 22 42 72 75 63 65 20 57 61 79 6E 65 22 0D 0A 7D "Bruce Wayne"��}

How do you replace 6 bytes at offset 0x11 to 0x16 with 11 bytes to span from 0x11 to 0x1B? What magic operation can be done to Stream to make 11 bytes fit into 6 bytes (and still comply with the JSON format)? (Yes, compression could potentially pack 11 bytes worth of data in 6 bytes, but JSON currently doesn't have compression as part of the standard.)
 
Last edited:

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,926
地点
英国
编程经验
10+
字符串[]行= System.IO.File.ReadAllLines("patinfo.csv");
StreamWriter Write = new System.IO.StreamWriter("temp.csv");
似乎适得其反,不是吗?
我对数据创建的使用不够吗?
我的例子缺乏更好的做法吗?
我是否为OP提供了适合其当前代码的示例?
您是否个人会认为这对OP已有的改进?
我们是否应该因为别人想要的而退而求其次地编写糟糕的代码?

我不喜欢OP提供的代码。所以我改写它以有效地完成同一件事,不是吗?

为什么要全部写入两个文件。这简直是​​双重工作。...我唯一未添加的是第7/17行中的选择选项。
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,523
地点
悉尼,澳大利亚
编程经验
10+
这是使用Json进行的钝但快速的代码重写。我更喜欢这样做,而不是使用CSV推荐 @jmcilhinney 就个人而言,那只是我。
我当然对JSON没有任何问题。我刚才提到了CSV,因为它似乎是OP已经使用的。
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,926
地点
英国
编程经验
10+
我当然对JSON没有任何问题。我刚才提到了CSV,因为它似乎是OP已经使用的。
CSV文件也没有问题。但这不是为什么我做我的事情,并且基本上像使用Json文件那样重写示例。我正在遵循OP最初想做的事情:
我设法更改了各个字段,但最终删除了文件中的所有其他内容。我只想编辑一个字段。任何帮助将不胜感激。谢谢
如果OP仅要编辑一个字段。好吧,如果OP跳到使用JSon,他们可以读回整个Json文件,并更改给定患者的数据,正如我已经演示的那样。在p1 /#13的第31/43行中完成要编辑的患者的匹配。

顺便说一句,我没有看到跳伞者在谈论文件大小这一观点的相关性,因为以前OP从未提出过这个问题。
 
Last edited:

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,926
地点
英国
编程经验
10+
使用JSon VS CSV ... CSV,您很可能会使用定界符等,进行拆分,拼接和连接等。但是使用JSon,您可以将每个患者读取到类对象,然后将该患者类对象存储到自己的位置在字典中。使用患者的ID作为字典的关键字<int, Patient>,因此与使用CSV文件进行循环,拆分和合并相比,数据流的过渡性要大得多。反正我没说过OP"must" use it.  :)

现在晚上晚上!
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,530
地点
弗吉尼亚州切萨皮克
编程经验
10+
顺便说一句,我没有看到跳伞者在谈论文件大小这一观点的相关性,因为以前OP从未提出过这个问题。
在第一篇文章中,OP遇到的问题是如何仅替换一个字段而不覆盖或删除文件的其余部分。您的主张是,仅通过使用JSON文件格式,就可以解决该问题。不幸的是,JSON是纯文本文件格式,就像CSV或某些可变大小的定界文件一样。我试图证明它无处可逃...需要覆盖文件,就像您用以下方法覆盖文件一样:
C#:
File.WriteAllText(Path.Combine(PathToDBFile, FileName), JsonConvert.SerializeObject(Patients, Formatting.Indented));
在第13条帖子的第28行上。

还没有StreamWriter实现(可让您在现有流的中间插入额外的字符,而不接触已经提交到磁盘的其余文件数据)。是的,使用StreamWriter,您可以替换/覆盖部分已提交的数据,但仅限于文件已在使用的空间。
 
Last edited:

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,530
地点
弗吉尼亚州切萨皮克
编程经验
10+
似乎适得其反,不是吗?
我对数据创建的使用不够吗?
有时候您需要确保安全 原子文件替换。使用File.Move(),您可以完成此操作。当您不知道是否还有其他人正在读取与您正在写入的文件相同的文件时,可以采用两种方法:锁定文件或写入另一个文件,然后交换。

锁定要求读取器和写入器在工作时均执行锁定,以确保它们使用一致的数据。这需要协调并传递适当的锁定标志。 (尽管网络共享/ SMB上的文件锁定现在应该可以正常工作,但是考虑到某些数据库实现仍然不鼓励在预期多用户访问的情况下将数据库文件存储在文件共享上,因此我仍然对此表示怀疑。)

即使有读取器当前仍在读取原始文件,也可以使用另一种处理临时文件然后交换的方法(至少在NTFS上)。这就是Windows Update执行修补的方式,即使DLL已映射到进程空间中,程序仍可以继续运行。在停止该过程之前,不会读取新的DLL版本。
 
最佳 底部