走一遍流程(2)
ExcelDataMgr这个类里写了一个字典变量tableDic,来存所有的字典
再写一个取tableDic里的 含字典的Container类
反射用的很多,反射和类的Type深度绑定
具体操作对象是每次都要传递作为参数的,因为反射是和类的定义绑定
方法和成员变量都用Object接,配合了反射的适配性,通过字符串来得到其中的变量,也是为反射的适配范围锦上添花
所以读出信息的时候,也要按这个顺序把byte一个一个的读出来
之前把excel信息变二进制的时候,存法
LoadTable<T,K>前面是字典类,后面是单个信息类
单例模式的问题,构造函数要写在静态变量下面
c#里成员的 书写,一般来说位置不影响,但如果是静态的,则会按照顺序依次的执行或者赋值
再往上就是,把流里输到文件的bytes再转换到具体的info类对象上
然后存到字典里,用excel里第四行规定的键当这个字典的键
每一行TableRow作为信息的对应,给到c#里的自定义info类上
然后就成功把excel中的信息存到了内存中,在游戏运行中就可以自然的调用了
执行完毕之后,fs.Close();
关闭文件流,也就是断开和当前绑定文件的bytes传输关系
ps:文件流不是只能往绑定的文件里传输bytes的,二进制只是一种信息的表述方式,用bytes装载信息再 去做其他信息交互,是有很大好处,所以才选择往流里写bytes,并不是因为只能fs.Write(bytes,int offset基于当前Position属性的位置的偏移,int 操作长度)
把bytes直接理解成二进制会更容易理解,看上去byte也是八个二进制位构成的,可能会产生一种byte的不底层感,如果犹豫不定,直接把bytes理解成二进制,在实际数据操作中也没有任何问题
对byte底层意识的再强调
byte是非常底层的,这一点需要有深刻意识,不仅仅是不否认“byte是8个bit,bit构成一切数据”
重点在对byte重要性认识的权重增加,
看上去bit构成byte,所以bit有一定的占比
但平时的逻辑操作中,bit完全是排除在外,甚至完全不用的,byte默认就是bit都可以
1. 关闭文件流(断开绑定)
文件流(FileStream
等)是用于在程序和文件之间传递数据的桥梁。关闭文件流意味着:
- 释放文件句柄:解除与文件系统的绑定,其他进程或操作系统资源可以重新访问该文件。
- 停止字节传输:不再允许通过该流写入或读取数据。
以下方法关闭文件流:
Dispose()
或Close()
:解除对资源的“囚禁”并断开和该文件的交互关系。using
语句:文件流在代码块结束时自动释放资源。
using (FileStream fs = new FileStream("example.txt", FileMode.OpenOrCreate))
{byte[] data = System.Text.Encoding.UTF8.GetBytes("Hello, FileStream!");fs.Write(data, 0, data.Length); // 写入数据
} // using 语句自动调用 fs.Dispose(),关闭文件流
2. 关于 bytes
的作用与理解
最底层的抽象:在编码层面,byte
是许多信息表达的基础单位,比如字符、图像数据、音频流等。
信息载体:程序处理数据时,以 byte
为单位更高效,因为它直接与硬件的存储和传输机制匹配。
为什么文件流传输的是 bytes
?
- 通用性:
byte
是最底层的抽象,可以被用于存储任何形式的数据(文本、图片、音频等)。 - 效率:流操作本质是对内存和磁盘的直接读写,硬件设备直接处理字节,所以传输
bytes
最为高效。 - 灵活性:通过对
bytes
的编码与解码,可以表达任意复杂的数据格式。
直接理解为二进制
将 byte
理解为二进制数据是完全可以的:
- 物理层面:存储和传输中,
byte
的每一位本质上就是高低电平或磁极方向。 - 逻辑层面:从程序角度看,
byte
作为 8 位的二进制数字,可以承载 0–255 的数据(无符号)或 -128–127(有符号)。
示例:
byte[] bytes = { 0b00000001, 0b00000010, 0b11111111 }; // 每个byte都是8个二进制位
Console.WriteLine(string.Join(", ", bytes)); // 输出: 1, 2, 255
3. 文件流传输的扩展
文件流的设计并不仅仅服务于文件系统写入,它的核心理念是提供一个高效的数据传输通道。以下是几种常见的应用场景:
(1) 文件读写
文件流最直接的用途是操作磁盘上的文件:
FileStream fs = new FileStream("data.txt", FileMode.OpenOrCreate);
byte[] data = System.Text.Encoding.UTF8.GetBytes("FileStream Example");
fs.Write(data, 0, data.Length);
fs.Close(); // 手动关闭
(2) 网络传输
文件流可以用于将文件通过网络流进行传输:
NetworkStream networkStream = ... // 假设是一个打开的网络流
byte[] buffer = File.ReadAllBytes("file.jpg");
networkStream.Write(buffer, 0, buffer.Length);
(3) 数据压缩
通过 MemoryStream
或 GZipStream
等对数据进行压缩处理:
using (FileStream originalFileStream = new FileStream("data.txt", FileMode.Open))
using (FileStream compressedFileStream = File.Create("data.gz"))
using (GZipStream compressionStream = new GZipStream(compressedFileStream, CompressionMode.Compress))
{originalFileStream.CopyTo(compressionStream); // 将数据从原文件流压缩后写入新流
}
(4) 数据解码/编码
使用流作为媒介,可以对字节数据进行编码解码:
FileStream fs = new FileStream("image.bmp", FileMode.Open);
BinaryReader reader = new BinaryReader(fs);
byte[] imageData = reader.ReadBytes((int)fs.Length);
// 对字节进行处理,比如解码成图片像素
reader.Close();
fs.Close();
总结
- 文件流的本质:是对字节传输的抽象,便于在不同媒介之间进行数据传输。
bytes
的作用:作为信息载体,其底层是二进制,可以表达任意信息。- 关闭流的意义:断开资源占用,确保数据一致性,释放文件锁。
DataRow
DataRow
是 .NET 框架 System.Data
命名空间中的一个类, 是DataTable
细化拆分每一行,构成单个行对象的类。
允许开发者读取、修改、添加或删除表格中的行。
DataRow
的基本组成
- 一个
DataRow
对象由DataTable
的架构定义(列名、数据类型等)。 DataRow
通过索引或列名访问单元格数据。
常用属性
ItemArray和HasErrors
object[] rowValues = dataRow.ItemArray;
dataRow.ItemArray = new object[] { 1, "John", 30 };
if (dataRow.HasErrors)
{Console.WriteLine(dataRow.GetColumnsInError());
}
常用方法(但目前不常用,没有修改excel在c#中的转换的需求)
-
AcceptChanges
- 确认对行的更改,将行的状态重置为
Unchanged
。 - 示例:
dataRow.AcceptChanges();
- 确认对行的更改,将行的状态重置为
-
RejectChanges
- 撤消自上次调用
AcceptChanges
以来对行的所有更改。 - 示例:
dataRow.RejectChanges();
- 撤消自上次调用
-
BeginEdit
和EndEdit
- 在编辑模式下,修改多个值后再一次性提交。
- 示例:
dataRow.BeginEdit(); dataRow["Name"] = "Alice"; dataRow["Age"] = 25; dataRow.EndEdit();
-
Delete
- 将行标记为删除,但不会立即从
DataTable
中移除。 - 示例:
dataRow.Delete();
- 将行标记为删除,但不会立即从
-
SetColumnError
和ClearErrors
- 设置或清除列错误。
- 示例:
dataRow.SetColumnError("Name", "Invalid Name"); dataRow.ClearErrors();
使用 DataRow
的示例
using System;
using System.Data;class Program
{static void Main(){// 创建 DataTableDataTable table = new DataTable("Students");table.Columns.Add("ID", typeof(int));table.Columns.Add("Name", typeof(string));table.Columns.Add("Age", typeof(int));// 添加一行数据DataRow row = table.NewRow();row["ID"] = 1;row["Name"] = "John";row["Age"] = 20;table.Rows.Add(row);// 修改数据row["Age"] = 21;// 删除数据row.Delete();// 遍历 DataTableforeach (DataRow dr in table.Rows){Console.WriteLine($"ID: {dr["ID"]}, Name: {dr["Name"]}, Age: {dr["Age"]}");}}
}
DataRow
和 DataTable
的关系
DataRow
是DataTable.Rows
集合的元素。- 通过
DataTable.NewRow()
方法可以创建一个与DataTable
架构匹配的新行。 - 添加、修改或删除行时,
DataRow
的更改会反映在其所属的DataTable
中。
总结
DataRow
是 DataTable
的核心操作单元,提供了对表格中每一行的灵活操作。无论是数据读写还是状态管理,它都在数据操作中发挥重要作用。
DataTable
在 C# 中,DataTable
是一个强大的类,用于存储数据表格。
属性
1. 基础属性
-
TableName
数据表的名称,字符串类型。DataTable table = new DataTable(); table.TableName = "MyTable";
-
Namespace
表的命名空间,主要在 XML 操作中使用。 -
Columns
获取表格的列集合 (DataColumnCollection
)。DataColumn column = table.Columns.Add("Column1", typeof(int));
-
Rows
获取表格的行集合 (DataRowCollection
)。DataRow newRow = table.NewRow(); table.Rows.Add(newRow);
-
Constraints
表的约束集合 (ConstraintCollection
)。UniqueConstraint constraint = new UniqueConstraint(table.Columns["Column1"]); table.Constraints.Add(constraint);
-
PrimaryKey
设置或获取表的主键列集合。table.PrimaryKey = new DataColumn[] { table.Columns["Column1"] };
2. 数据操作相关
-
DefaultView
返回一个DataView
,可以对表的数据进行排序或筛选。table.DefaultView.RowFilter = "Column1 > 10";
-
CaseSensitive
指定字符串比较是否区分大小写。table.CaseSensitive = true;
-
Locale
获取或设置表的区域设置。table.Locale = new System.Globalization.CultureInfo("en-US");
-
MinimumCapacity
表的最小初始容量,用于优化性能。table.MinimumCapacity = 100;
3. Schema 和元数据相关
-
ExtendedProperties
一个可以存储任意用户自定义数据的集合。table.ExtendedProperties["CustomProperty"] = "MyValue";
-
ChildRelations
获取表的子关系集合。DataRelationCollection childRelations = table.ChildRelations;
-
ParentRelations
获取表的父关系集合。
4. 事件相关属性
-
HasErrors
指示表中是否有错误。if (table.HasErrors) {// 处理错误 }
-
RowErrors
和GetErrors()
用于处理表中的错误行。DataRow[] errorRows = table.GetErrors();
常用组合
下面是一个实际场景的示例:
DataTable table = new DataTable("Employees");// 添加列
table.Columns.Add("ID", typeof(int));
table.Columns.Add("Name", typeof(string));
table.Columns.Add("Age", typeof(int));// 添加主键
table.PrimaryKey = new DataColumn[] { table.Columns["ID"] };// 添加数据行
DataRow row = table.NewRow();
row["ID"] = 1;
row["Name"] = "Alice";
row["Age"] = 30;
table.Rows.Add(row);// 检查是否有错误
if (!table.HasErrors) {Console.WriteLine("No errors in the table.");
}// 使用 DefaultView 过滤
table.DefaultView.RowFilter = "Age > 25";
方法
C# 中的 DataTable
提供了丰富的方法,用于操作数据、结构和元数据。以下是常用的 DataTable
方法分类和示例:
1. 数据操作相关方法
-
NewRow()
创建一个与表架构匹配的新数据行。DataRow newRow = table.NewRow(); newRow["Column1"] = 123; table.Rows.Add(newRow);
-
ImportRow(DataRow row)
从另一个表复制一行数据到当前表。table.ImportRow(otherTable.Rows[0]);
-
Select(string filterExpression, string sort = null)
筛选表中的数据行,并可指定排序条件。DataRow[] filteredRows = table.Select("Column1 > 100", "Column2 ASC");
-
Merge(DataTable table)
合并两个表的数据。table1.Merge(table2);
-
Clear()
清空表中的所有数据行。table.Clear();
-
Copy()
创建一个表的副本(包括架构和数据)。DataTable copyTable = table.Copy();
-
Clone()
创建一个只包含架构的表副本,不包含数据。DataTable schemaTable = table.Clone();
-
Compute(string expression, string filter)
计算表的聚合函数(如求和、平均值),可以带筛选条件。object sum = table.Compute("SUM(Column1)", "Column2 > 50");
2. 架构操作相关方法
-
SetColumnsOrder(params string[] columnNames)
设置列的顺序(需要手动实现)。table.SetColumnsOrder("Column2", "Column1", "Column3");
-
AddColumn(string columnName, Type dataType)
添加新列。table.Columns.Add("NewColumn", typeof(double));
-
RemoveColumn(string columnName)
删除指定的列。table.Columns.Remove("UnnecessaryColumn");
3. 错误处理方法
column架构无错,只错在行的数据落实
-
GetErrors()
获取表中包含错误的所有行。DataRow[] errorRows = table.GetErrors();
-
ClearErrors()
清除表中所有行的错误状态。table.ClearErrors();
4. 关系操作方法
-
GetChildRows(string relationName)
获取指定关系名下的子行。DataRow[] childRows = parentRow.GetChildRows("RelationName");
-
GetParentRow(string relationName)
获取指定关系名下的父行。DataRow parentRow = childRow.GetParentRow("RelationName");
5. 数据导入导出方法
-
WriteXml(string filePath)
和ReadXml(string filePath)
将表的数据写入 XML 文件或从 XML 文件读取数据。table.WriteXml("data.xml"); table.ReadXml("data.xml");
-
WriteXmlSchema(string filePath)
和ReadXmlSchema(string filePath)
只导入或导出表的架构。table.WriteXmlSchema("schema.xml"); table.ReadXmlSchema("schema.xml");
6. 调试和查看方法
-
ToString()
返回表的名称。Console.WriteLine(table.ToString());
-
Extensions
(自定义扩展方法)
可以扩展方法以便于调试和快速查看数据,例如打印表内容。
示例代码
以下展示了这些方法的实际应用:
DataTable table = new DataTable("SampleTable");// 添加列
table.Columns.Add("ID", typeof(int));
table.Columns.Add("Name", typeof(string));
table.Columns.Add("Age", typeof(int));// 添加数据
DataRow row = table.NewRow();
row["ID"] = 1;
row["Name"] = "Alice";
row["Age"] = 30;
table.Rows.Add(row);// 复制和筛选
DataTable copy = table.Copy();
DataRow[] selectedRows = table.Select("Age > 20");// 聚合计算
object sum = table.Compute("SUM(Age)", "");// 导出为 XML
table.WriteXml("table_data.xml");