【问题标题】:Gedcom Reader for C#C# 的 Gedcom 阅读器
【发布时间】:2025-12-29 05:40:06
【问题描述】:

有谁知道在 .ged 文件中读取的好类

Gedcom 是一种用于存储家谱信息的文件格式。

我的目标是写一些东西,让我可以导入一个 ged 文件并为 graphviz 导出一个 .dot 文件,这样我就可以对家谱进行可视化表示

谢谢你的帮助

【问题讨论】:

  • 错字:地质学而不是家谱学
  • @Joel C.(标签):GEDCOM 是一种家谱文件格式,而不是地质学或地理位置。 (“家谱的视觉表示”这句话可能也有帮助......)

标签: c# genealogy gedcom


【解决方案1】:

这是我迄今为止最好的尝试。

它似乎可以满足我的需要,尽管它不能完全证明(我的家谱又相当大,这增加了一些复杂性)

如果您认为我可以做出更优雅的东西,请告诉我

struct INDI
        {
            public string ID;
            public string Name;
            public string Sex;
            public string BirthDay;
            public bool Dead;


        }
        struct FAM
        {
            public string FamID;
            public string type;
            public string IndiID;
        }
        List<INDI> Individuals = new List<INDI>();
        List<FAM> Family = new List<FAM>();
        private void button1_Click(object sender, EventArgs e)
        {
            string path = @"C:\mostrecent.ged";
            ParseGedcom(path);
        }

        private void ParseGedcom(string path)
        {
            //Open path to GED file
            StreamReader SR = new StreamReader(path);

            //Read entire block and then plit on 0 @ for individuals and familys (no other info is needed for this instance)
            string[] Holder = SR.ReadToEnd().Replace("0 @", "\u0646").Split('\u0646');

            //For each new cell in the holder array look for Individuals and familys
            foreach (string Node in Holder)
            {

                //Sub Split the string on the returns to get a true block of info
                string[] SubNode = Node.Replace("\r\n", "\r").Split('\r');
                //If a individual is found
                if (SubNode[0].Contains("INDI"))
                {
                    //Create new Structure
                    INDI I = new INDI();
                    //Add the ID number and remove extra formating
                    I.ID = SubNode[0].Replace("@", "").Replace(" INDI", "").Trim();
                    //Find the name remove extra formating for last name
                    I.Name = SubNode[FindIndexinArray(SubNode, "NAME")].Replace("1 NAME", "").Replace("/", "").Trim(); 
                    //Find Sex and remove extra formating
                    I.Sex = SubNode[FindIndexinArray(SubNode, "SEX")].Replace("1 SEX ", "").Trim();

                    //Deterine if there is a brithday -1 means no
                    if (FindIndexinArray(SubNode, "1 BIRT ") != -1)
                    {
                        // add birthday to Struct 
                        I.BirthDay = SubNode[FindIndexinArray(SubNode, "1 BIRT ") + 1].Replace("2 DATE ", "").Trim();
                    }

                    // deterimin if there is a death tag will return -1 if not found
                    if (FindIndexinArray(SubNode, "1 DEAT ") != -1)
                    {
                        //convert Y or N to true or false ( defaults to False so no need to change unless Y is found.
                        if (SubNode[FindIndexinArray(SubNode, "1 DEAT ")].Replace("1 DEAT ", "").Trim() == "Y")
                        {
                            //set death
                            I.Dead = true;
                        }
                    }
                    //add the Struct to the list for later use
                    Individuals.Add(I);
                }

                // Start Family section
                else if (SubNode[0].Contains("FAM"))
                {
                    //grab Fam id from node early on to keep from doing it over and over
                    string FamID = SubNode[0].Replace("@ FAM", "");

                    // Multiple children can exist for each family so this section had to be a bit more dynaimic

                    // Look at each line of node
                    foreach (string Line in SubNode)
                    {
                        // If node is HUSB
                        if (Line.Contains("1 HUSB "))
                        {

                            FAM F = new FAM();
                            F.FamID = FamID;
                            F.type = "PAR";
                            F.IndiID = Line.Replace("1 HUSB ", "").Replace("@","").Trim();
                            Family.Add(F);
                        }
                            //If node for Wife
                        else if (Line.Contains("1 WIFE "))
                        {
                            FAM F = new FAM();
                            F.FamID = FamID;
                            F.type = "PAR";
                            F.IndiID = Line.Replace("1 WIFE ", "").Replace("@", "").Trim();
                            Family.Add(F);
                        }
                            //if node for multi children
                        else if (Line.Contains("1 CHIL "))
                        {
                            FAM F = new FAM();
                             F.FamID = FamID;
                            F.type = "CHIL";
                            F.IndiID = Line.Replace("1 CHIL ", "").Replace("@", "");
                            Family.Add(F);
                        }
                    }
                }
            }
        }

        private int FindIndexinArray(string[] Arr, string search)
        {
            int Val = -1;
            for (int i = 0; i < Arr.Length; i++)
            {
                if (Arr[i].Contains(search))
                {
                    Val = i;
                }
            }
            return Val;
        }

【讨论】:

    【解决方案2】:

    Codeplex 上有一个非常漂亮的:FamilyShow(WPF 展示)。它导入/导出 GEDCOM 5.5 并且有源代码。

    【讨论】:

    • 家庭表演很酷。我正在做一些事情来帮助可视化与此类似的所有内容
    • 我现在已经花了几天时间参加家庭表演。老实说,这很糟糕@#$@$。它非常漂亮不要误会我的意思,但它也非常有问题(至少在 xp 中)并且不能很好地处理很多事情,其中​​最不重要的是 gedcom import
    【解决方案3】:

    如果没有至少一个的开始,我实际上会感到惊讶。我很容易找到Gedcom.NET (sourceforge)

    【讨论】:

    • 我也发现了。这也可能是我完全缺乏经验,但班级结构似乎相当复杂。
    • 在您的问题中提及这一点可能会有所帮助,也许您觉得很复杂。尝试看看你是否能理解这一点(也许联系作者或在这里问另一个问题)可能比重新发明一个会逐渐变得更复杂的更简单的版本更好。
    • @Matthew Flaschen 我在发布问题后找到了它
    • 它是(曾经)在 Monodevelop 下开发的,因此任何错误都可能是由于 VS / .NET 和 Monodevelop / Mono 的差异造成的。它们只是小问题,不需要太多修复。
    【解决方案4】:

    如果网络上有适用于这种格式的 C# 阅读器,我会感到相当惊讶,因为它是一种相当专业的格式。从好的方面来说,如果您需要创建自己的阅读器,这种格式看起来很容易阅读。如果您对实施有具体问题,我建议您沿着这条路走,然后回到 SO。看看System.IO.StreamReader 类;以这种方式逐行读取文件很简单,并且解析各个行也应该很简单。

    祝你好运!

    【讨论】:

    • 我知道这可能会发生。如果可能的话,我想避免这种情况(无需重新发明*)。
    • 我想我可能知道我想如何做到这一点 --- 每个人都是分隔的。然后每个家庭都由一个指向相关个人的指针分隔。我认为如果只是阅读该信息就可以了。我真希望他们能像其他文明格式一样使用 xml。