You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用DataTable.WriteXml()生成的XML文件无法读取数据问题排查

问题描述

我创建了一个包含以下列的DataTable:

dataTable.Columns.Add("ID", typeof(string));
dataTable.Columns.Add("File Name", typeof(string));
dataTable.Columns.Add("Date Taken", typeof(string));
dataTable.Columns.Add("Size", typeof(string));
dataTable.Columns.Add("Unique", typeof(bool));

我用以下代码将DataTable写入XML文件:

if (dgView.DataSource is DataTable dataTable) // 确保数据源是DataTable
{
    if (string.IsNullOrWhiteSpace(dataTable.TableName))
    {
        dataTable.TableName = "MyDataTable"; // 赋值表名避免序列化错误
    }

    string dataTime = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"); // 动态时间戳
    string defaultFolder = txtSort.Text.Trim(); // 从txtSort获取默认文件夹
    string defaultFileName = $"{dataTime}.xml";

    using (SaveFileDialog saveFileDialog = new SaveFileDialog())
    {
        saveFileDialog.InitialDirectory = Directory.Exists(defaultFolder) ? defaultFolder : Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
        saveFileDialog.FileName = defaultFileName;
        saveFileDialog.Filter = "XML Files (*.xml)|*.xml|All Files (*.*)|*.*";
        saveFileDialog.Title = "将DataTable保存为XML";

        if (saveFileDialog.ShowDialog() == DialogResult.OK)
        {
            try
            {
                dataTable.WriteXml(saveFileDialog.FileName);
                MessageBox.Show($"数据已保存到 {saveFileDialog.FileName}", "保存成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"保存数据出错: {ex.Message}", "保存错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }
}
else
{
    MessageBox.Show("DataGridView中未找到有效的DataTable。", "无数据", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}

生成的XML文件内容如下:

<?xml version="1.0" standalone="yes"?>
<DocumentElement>
  <MyDataTable>
    <ID>1</ID>
    <File_x0020_Name>H:\Image backup\TEST_SOURCE\01\IMG_7718(8).jpg</File_x0020_Name>
    <Date_x0020_Taken>Jan/17/2016 14:46:06</Date_x0020_Taken>
    <Size>0.673 MB</Size>
    <Unique>true</Unique>
  </MyDataTable>
  <MyDataTable>
    <ID>2</ID>
    <File_x0020_Name>H:\Image backup\TEST_SOURCE\01\IMG_7718(2).jpg</File_x0020_Name>
    <Date_x0020_Taken>Jan/17/2016 14:46:06</Date_x0020_Taken>
    <Size>0.673 MB</Size>
    <Unique>true</Unique>
  </MyDataTable>
  <MyDataTable>
    <ID>3</ID>
    <File_x0020_Name>H:\Image backup\TEST_SOURCE\01\IMG_7719(3).jpg</File_x0020_Name>
    <Date_x0020_Taken>Jan/17/2016 14:46:07</Date_x0020_Taken>
    <Size>1.045 MB</Size>
    <Unique>true</Unique>
  </MyDataTable>
  <MyDataTable>
    <ID>7</ID>
    <File_x0020_Name>H:\Image backup\TEST_SOURCE\01\IMG_7719(2).jpg</File_x0020_Name>
    <Date_x0020_Taken>Jan/17/2016 14:46:07</Date_x0020_Taken>
    <Size>1.045 MB</Size>
    <Unique>true</Unique>
  </MyDataTable>
</DocumentElement>

但我用以下代码读取该文件时,没有加载到任何数据(行数为0):

private void btnRetrieve_Click(object sender, EventArgs e)
{
    OpenFileDialog OpenFileDialog = new OpenFileDialog();
    if (OpenFileDialog.ShowDialog() == DialogResult.OK)
    {
        string fileName = OpenFileDialog.FileName;
        Task.Run(() =>
        {
            // 将XML中的数据加载到DataTable
            DataTable dataTable = new DataTable();
            dataTable.Columns.Add("ID", typeof(string));
            dataTable.Columns.Add("File_x0020_Name", typeof(string)); // 处理空格为_x0020_
            dataTable.Columns.Add("Date_x0020_Taken", typeof(string)); // 处理空格为_x0020_
            dataTable.Columns.Add("Size", typeof(string));
            dataTable.Columns.Add("Unique", typeof(bool));

            // 读取XML到DataTable
            if (File.Exists(fileName))
            {
                try
                {
                    dataTable.ReadXml(fileName);

                    // 检查是否加载到数据
                    if (dataTable.Rows.Count == 0)
                    {
                        this.Invoke(new Action(() =>
                        {
                            MessageBox.Show("XML文件已加载,但未找到数据。", "数据加载错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        }));
                    }
                    else
                    {
                        // 用DataTable中的数据填充字典
                        ConcurrentDictionary<string, List<mediaFile>> g_allFiles = new ConcurrentDictionary<string, List<mediaFile>>();

                        foreach (DataRow row in dataTable.Rows)
                        {
                            mediaFile media = new mediaFile
                            {
                                id = row["ID"].ToString(),
                                fileName = row["File_x0020_Name"].ToString(),
                                exif_date = row["Date_x0020_Taken"].ToString(),
                                fileSize = row["Size"].ToString(),
                                unique = Convert.ToBoolean(row["Unique"])
                            };

                            // 提取文件扩展名(3个字符)
                            string fileExtension = Path.GetExtension(media.fileName)?.Substring(1, 3).ToLower();

                            if (!string.IsNullOrEmpty(fileExtension))
                            {
                                if (!g_allFiles.ContainsKey(fileExtension))
                                {
                                    g_allFiles[fileExtension] = new List<mediaFile>();
                                }

                                g_allFiles[fileExtension].Add(media);
                            }
                        }

                        dataTable.Columns["File_x0020_Name"].ColumnName = "File Name";
                        dataTable.Columns["Date_x0020_Taken"].ColumnName = "Date Taken";

                        // 更新DataGridView显示加载的数据
                        this.Invoke(new Action(() =>
                        {
                            dgView.DataSource = dataTable;
                        }));
                    }
                }
                catch (Exception ex)
                {
                    // 处理读取XML时的错误
                    this.Invoke(new Action(() =>
                    {
                        MessageBox.Show($"读取XML文件出错: {ex.Message}", "文件读取错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }));
                }
            }
            else
            {
                // 如果文件不存在,在UI线程显示提示
                this.Invoke(new Action(() =>
                {
                    MessageBox.Show("指定的文件路径不存在。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }));
            }
        });
    }
    var k = g_allFiles;
}

请问我哪里操作出错了?


解决方法

问题核心在于读取XML时创建的DataTable未设置与写入时一致的TableName:你写入XML时给DataTable指定了MyDataTable的表名,XML中的数据都包裹在<MyDataTable>节点下;但读取时新建的DataTable用的是默认表名(如Table),ReadXml会默认寻找与当前DataTable表名匹配的节点,两者不匹配导致数据无法加载。

另外还有一个编译错误:你在Task.Run外部访问了内部定义的g_allFiles变量,局部变量作用域不允许这种操作。

修正后的读取代码

private void btnRetrieve_Click(object sender, EventArgs e)
{
    OpenFileDialog openFileDialog = new OpenFileDialog();
    if (openFileDialog.ShowDialog() == DialogResult.OK)
    {
        string fileName = openFileDialog.FileName;
        Task.Run(() =>
        {
            // 关键:设置和写入时一致的表名
            DataTable dataTable = new DataTable("MyDataTable");
            dataTable.Columns.Add("ID", typeof(string));
            dataTable.Columns.Add("File_x0020_Name", typeof(string));
            dataTable.Columns.Add("Date_x0020_Taken", typeof(string));
            dataTable.Columns.Add("Size", typeof(string));
            dataTable.Columns.Add("Unique", typeof(bool));

            // 读取XML到DataTable
            if (File.Exists(fileName))
            {
                try
                {
                    dataTable.ReadXml(fileName);

                    // 检查是否加载到数据
                    if (dataTable.Rows.Count == 0)
                    {
                        this.Invoke(new Action(() =>
                        {
                            MessageBox.Show("XML文件已加载,但未找到数据。", "数据加载错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        }));
                    }
                    else
                    {
                        // 用DataTable中的数据填充字典
                        ConcurrentDictionary<string, List<mediaFile>> g_allFiles = new ConcurrentDictionary<string, List<mediaFile>>();

                        foreach (DataRow row in dataTable.Rows)
                        {
                            mediaFile media = new mediaFile
                            {
                                id = row["ID"].ToString(),
                                fileName = row["File_x0020_Name"].ToString(),
                                exif_date = row["Date_x0020_Taken"].ToString(),
                                fileSize = row["Size"].ToString(),
                                unique = Convert.ToBoolean(row["Unique"])
                            };

                            // 提取文件扩展名(3个字符)
                            string fileExtension = Path.GetExtension(media.fileName)?.Substring(1, 3).ToLower();

                            if (!string.IsNullOrEmpty(fileExtension))
                            {
                                if (!g_allFiles.ContainsKey(fileExtension))
                                {
                                    g_allFiles[fileExtension] = new List<mediaFile>();
                                }

                                g_allFiles[fileExtension].Add(media);
                            }
                        }

                        dataTable.Columns["File_x0020_Name"].ColumnName = "File Name";
                        dataTable.Columns["Date_x0020_Taken"].ColumnName = "Date Taken";

                        // 更新DataGridView显示加载的数据
                        this.Invoke(new Action(() =>
                        {
                            dgView.DataSource = dataTable;
                        }));

                        // 若需外部使用g_allFiles,需将其改为类成员变量,或通过回调传递
                        // 示例:this.g_allFiles = g_allFiles;
                    }
                }
                catch (Exception ex)
                {
                    // 处理读取XML时的错误
                    this.Invoke(new Action(() =>
                    {
                        MessageBox.Show($"读取XML文件出错: {ex.Message}", "文件读取错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }));
                }
            }
            else
            {
                // 如果文件不存在,在UI线程显示提示
                this.Invoke(new Action(() =>
                {
                    MessageBox.Show("指定的文件路径不存在。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }));
            }
        });
    }
    // 移除无效的var k = g_allFiles; 局部变量作用域限制无法访问
}

额外说明

  • 读取时的DataTable表名必须和写入时完全一致,ReadXml才能正确识别XML中的数据节点。
  • 若不想手动设置表名,也可先调用dataTable.ReadXmlSchema()读取XML结构(需写入时用WriteXmlSchema保存Schema),再读取数据。
  • 局部变量g_allFiles无法跨作用域访问,需改为类成员变量或通过其他方式传递到外部。

内容的提问来源于stack exchange,提问作者PCG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 16:27:02