C# 用C语言从文本文件中读取多维变量#
我正在尝试在C#(Windows窗体应用程序,Visual Studio)中创建一个GUI,用于从文本文件读取和写入某些变量。我对GUI本身没有问题,但我需要一个函数,可以读取(并最终写入)文本文件,识别变量并将其放入内部变量或直接放入GUI控件中。文本文件看起来像这样(但要长得多): 我有一个C代码可以读取文本文件,但它太长了。我的印象是,用一段相对较短的C#代码就可以优雅地完成这项工作。我已经试着按照建议使用字典,但是我的文本文件的格式太复杂了。。。除非某位大师知道一些可以帮助我的技巧 欢迎你的建议。样本代码将不胜感激 以下内容定义了文本文件的格式:C# 用C语言从文本文件中读取多维变量#,c#,file,text,C#,File,Text,我正在尝试在C#(Windows窗体应用程序,Visual Studio)中创建一个GUI,用于从文本文件读取和写入某些变量。我对GUI本身没有问题,但我需要一个函数,可以读取(并最终写入)文本文件,识别变量并将其放入内部变量或直接放入GUI控件中。文本文件看起来像这样(但要长得多): 我有一个C代码可以读取文本文件,但它太长了。我的印象是,用一段相对较短的C#代码就可以优雅地完成这项工作。我已经试着按照建议使用字典,但是我的文本文件的格式太复杂了。。。除非某位大师知道一些可以帮助我的技巧 欢迎
- 所有变量都以
开头/YD/
和/*
之间的文本是注释(无需阅读)*/
- 分隔符可以是空格或制表符,在变量和值之间可以有一个或多个分隔符。也可以有空行
- 有时每行有多个变量
- 有时变量及其值在不同的行中
- 有些变量是单值变量,有些是一维、二维或三维变量
- 格式为xxxxxx的变量(不一定是固定数量的字符)后面跟着它的单个值
- 形式为x1xxxxx的变量为1-D。这些变量后面跟着一个
整数,表示变量的大小,后跟
变量的值(例如变量
是一个一维变量,有三个值:0.7、0.75和0.5)/YD/YDPE/D1PEFR 3 0.7 0.75.5
- 格式为x2xxxxx的变量是二维的。这些变量后面首先是一个数字,告诉您如何读取变量,然后是变量的大小(2个数字),然后是变量的实际值。例如,变量
是一个二维变量,其中数字21表示首先读取更改“x”坐标,然后读取更改“y”坐标(12表示首先读取更改“y”然后更改“x”),接下来的数字/YD/YDPM/I2PMSET 21 3 2 1 3 0 1 0 1
和3
表示大小为[3,2],以下6个数字是变量的值,顺序为2
(x1y1、x2y1、x3y1、x1y2、x2y2、x3y2)
- 最后,x3xxxx形式的变量是3-D。这些变量后面是一个数字,告诉您如何读取它,然后是大小(3个数字),然后是值。例如,变量
是三维的,首先读“x”,然后读“z”,然后读“y”,大小是[2,3,4]。然后按照/YD/YDPN/D3PNFAC 231 2 3 4…
(x1y1z1、x2y1z1、x1y1z2、x2y1z2、x1y1z3、x2y1z3、x1y1z4、x2y1z4、x1y2z1、x2y2z1等)的顺序读取这些值
- Mu建议重新构造文件的构建方式。这样,您就可以使用XML结构,并使所有代码更易于阅读
看看:(
System.Xml.Linq
)
以下是您可以做的一个示例:
<Root>
<Controls>
<Control/>
...
</Controls>
<Properties>
<Property/>
...
</Properties>
</Root>
要获取变量,请查看类。更具体地看一下
Split
、Replace
和Trim
方法。我认为C中的任何东西都不会神奇地为你做这件事,但为了避免我想象中你在C中遇到的意大利面代码,我会将它分解成一些类,每个类负责给定的变量类型。抱歉,这有点假代码,但我希望能有所帮助
首先是基类:
public abstract class DataValue {
public string Category { get; protected set; } // value after /YD
public string Name { get; protected set; } // value after /YD/XXX/
public int DimensionCount { get; protected set; } // number of dimensions
public int[] Dimensions { get; protected set; } // The size of each dimension
protected void ParseHeader(string header) {
// Split of the header into the Category/Name and set it
}
public virtual void ReadValue(string header, StreamReader reader) {
ParseHeader(header);
}
}
然后为每个变量类型创建一个类:
public class ScalarValue: DataValue {
public ScalarValue() {
DimensionCount = 1;
Dimensions = new [] { 1 };
}
public override void ReadValues(string header, StreamReader reader) {
base.ReadValues(header, reader);
// Do custom logic for reading a scalar here.
}
}
您可以为每个主要类型创建这样的类。他们各自负责自己的阅读逻辑。您需要一个主解析器循环来查找变量、创建对象并分派它们:
public static List<DataValue> ParseDataFile(string filePath) {
var reader = new StreamReader(filePath);
var values = new List<DataValue>();
var variableHeader = FindNextVariable(reader);
while(!string.IsNullOrEmpty(variableHeader)) {
DataValue v;
switch(FindVariableType(variableHeader)) {
case Scalar:
v = new ScalarValue();
case OneDimensionalArray:
v = new Array1DValue();
// etc
}
v.ReadValue(variableHeader, reader);
values.Add(v);
variableHeader = FindNextVariable(reader);
}
return values;
}
FindVariableType是:
public enum VariableType {
Scalar,
OneDimensionalValue,
TwoDimensionalValue,
ThreeDimensionalValue,
Other
}
public static VariableType FindVariableType(string header) {
var fields = string.Split('/', header);
// take the third item, parse it to determine type
}
实际实现有很多方法,但这是总体思路。好的,这是我的解决方案。我在代码中包含了几条注释,因此它或多或少是不言自明的 总之,我定义了一个类(一个类用于所有变量,即使它们是多维的!),然后将所有变量存储在字典中。我认为这很简单 要存储我的变量的类:
public class Variable
{
// Properties.
public string Database { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public int Dimensions { get; set; }
public int Order { get; set; }
public int[] Size { get; set; }
public double[] Value { get; set; }
// Default constructor.
public Variable()
{
}
// Constructor.
public Y_Variable(string db, string nam, string typ, int dim, int ord,
int[] siz, double[] val)
{
this.Database = db;
this.Name = nam;
this.Type = typ;
this.Dimensions = dim;
this.Order = ord;
this.Size = siz;
this.Value = val;
}
}
读取文件并在字典中存储变量的代码:
public class Y_File2Dictionary
{
public static Dictionary<string, Y_Variable> File2Dictionary(string fileName)
{
// Define delimiters and block comments.
char[] delimiterChars = { ' ', '\t', '\n', '\r' };
var blockComments = @"/\*(.*?)\*/";
// Read the file, remove comments, and store in array with no spaces.
string[] arrayAllVars = Regex
.Replace(File.ReadAllText(fileName), blockComments, "",
RegexOptions.Singleline)
.Split(delimiterChars, StringSplitOptions.RemoveEmptyEntries);
// Initialize dictionary.
Dictionary<string, Y_Variable> dictAllVars = new
Dictionary<string, Y_Variable>();
// Loop to read variables and store them in dictionary.
int i = 0;
while (i < arrayAllVars.Length)
{
// Read only variables.
if (!char.Equals(arrayAllVars[i][0], '/'))
{
i++;
continue;
}
// Read variable name and separate into array
// e.g. /YD/YDC/DCSTEC => {"", YD, YDC, DCSTEC}.
string[] arrayVarName = Regex.Split(arrayAllVars[i++], "/");
// Identify variable.
string varDb = arrayVarName[2];
string varName = arrayVarName[3];
string varTyp = (varName[0] == 'D') ? "double" : "integer";
int varDim = ((int)Char.GetNumericValue(varName[1]) > 0) ?
((int)Char.GetNumericValue(varName[1])) : 0;
// Initiallization of variables to store order and size.
int varOrder = 0;
int[] varSize = new int[3] { 1, 1, 1 };
// Update order and size, depending on the number of dimensions.
switch (varDim)
{
case 1:
varOrder = 1;
Int32.TryParse(arrayAllVars[i++], out varSize[0]);
varSize[1] = 1;
varSize[2] = 1;
break;
case 2:
Int32.TryParse(arrayAllVars[i++], out varOrder);
Int32.TryParse(arrayAllVars[i++], out varSize[0]);
Int32.TryParse(arrayAllVars[i++], out varSize[1]);
varSize[2] = 1;
break;
case 3:
Int32.TryParse(arrayAllVars[i++], out varOrder);
Int32.TryParse(arrayAllVars[i++], out varSize[0]);
Int32.TryParse(arrayAllVars[i++], out varSize[1]);
Int32.TryParse(arrayAllVars[i++], out varSize[2]);
break;
default:
varOrder = 0;
varSize[0] = 1;
varSize[1] = 1;
varSize[2] = 1;
break;
}
// Determine total size of variable, get values as strings.
var varTotalSize = varSize[0] * varSize[1] * varSize[2];
string[] varValStr = new string[varTotalSize];
Array.Copy(arrayAllVars, i, varValStr, 0, varTotalSize);
// Convert values from string to double.
double[] varValDbl = new double[varTotalSize];
varValDbl = Array.ConvertAll(varValStr, Double.Parse);
// Add variable to dictionary.
if (dictAllVars.ContainsKey(varDb + "_" + varName))
dictAllVars.Remove(varDb + "_" + varName);
dictAllVars.Add(varDb + "_" + varName, new Y_Variable(varDb, varName,
varTyp, varDim, varOrder, varSize, varValDbl));
i += varTotalSize;
}
return dictAllVars;
}
}
public class Y\u File2Dictionary
{
公共静态字典File2Dictionary(字符串文件名)
{
//定义分隔符和块注释。
char[]delimiterChars={'','\t','\n','\r'};
var blockComments=@“/\*(.*?\*/”;
//读取文件,删除注释,并存储在数组中,不留空格。
字符串[]arrayAllVars=Regex
.Replace(File.ReadAllText(文件名),blockComments,“,
RegexOptions.Singleline)
.Split(delimiterChars、StringSplitOptions.RemoveEmptyEntries);
//初始化字典。
Dictionary dictAllVars=新
字典();
//循环读取变量并将其存储在字典中。
int i=0;
而(i{”,YD,YDC,DCSTEC}。
字符串[]arrayVarName=Regex.Split(arrayAllVars[i++],“/”;
//识别变量。
字符串varDb=arrayVarName[2];
字符串varName=arrayVarName[3];
字符串varTyp=(varName[0]='D')?“double”:“integer”;
int varDim=((int)Char.GetNumericValue(varNa)
public enum VariableType {
Scalar,
OneDimensionalValue,
TwoDimensionalValue,
ThreeDimensionalValue,
Other
}
public static VariableType FindVariableType(string header) {
var fields = string.Split('/', header);
// take the third item, parse it to determine type
}
public class Variable
{
// Properties.
public string Database { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public int Dimensions { get; set; }
public int Order { get; set; }
public int[] Size { get; set; }
public double[] Value { get; set; }
// Default constructor.
public Variable()
{
}
// Constructor.
public Y_Variable(string db, string nam, string typ, int dim, int ord,
int[] siz, double[] val)
{
this.Database = db;
this.Name = nam;
this.Type = typ;
this.Dimensions = dim;
this.Order = ord;
this.Size = siz;
this.Value = val;
}
}
public class Y_File2Dictionary
{
public static Dictionary<string, Y_Variable> File2Dictionary(string fileName)
{
// Define delimiters and block comments.
char[] delimiterChars = { ' ', '\t', '\n', '\r' };
var blockComments = @"/\*(.*?)\*/";
// Read the file, remove comments, and store in array with no spaces.
string[] arrayAllVars = Regex
.Replace(File.ReadAllText(fileName), blockComments, "",
RegexOptions.Singleline)
.Split(delimiterChars, StringSplitOptions.RemoveEmptyEntries);
// Initialize dictionary.
Dictionary<string, Y_Variable> dictAllVars = new
Dictionary<string, Y_Variable>();
// Loop to read variables and store them in dictionary.
int i = 0;
while (i < arrayAllVars.Length)
{
// Read only variables.
if (!char.Equals(arrayAllVars[i][0], '/'))
{
i++;
continue;
}
// Read variable name and separate into array
// e.g. /YD/YDC/DCSTEC => {"", YD, YDC, DCSTEC}.
string[] arrayVarName = Regex.Split(arrayAllVars[i++], "/");
// Identify variable.
string varDb = arrayVarName[2];
string varName = arrayVarName[3];
string varTyp = (varName[0] == 'D') ? "double" : "integer";
int varDim = ((int)Char.GetNumericValue(varName[1]) > 0) ?
((int)Char.GetNumericValue(varName[1])) : 0;
// Initiallization of variables to store order and size.
int varOrder = 0;
int[] varSize = new int[3] { 1, 1, 1 };
// Update order and size, depending on the number of dimensions.
switch (varDim)
{
case 1:
varOrder = 1;
Int32.TryParse(arrayAllVars[i++], out varSize[0]);
varSize[1] = 1;
varSize[2] = 1;
break;
case 2:
Int32.TryParse(arrayAllVars[i++], out varOrder);
Int32.TryParse(arrayAllVars[i++], out varSize[0]);
Int32.TryParse(arrayAllVars[i++], out varSize[1]);
varSize[2] = 1;
break;
case 3:
Int32.TryParse(arrayAllVars[i++], out varOrder);
Int32.TryParse(arrayAllVars[i++], out varSize[0]);
Int32.TryParse(arrayAllVars[i++], out varSize[1]);
Int32.TryParse(arrayAllVars[i++], out varSize[2]);
break;
default:
varOrder = 0;
varSize[0] = 1;
varSize[1] = 1;
varSize[2] = 1;
break;
}
// Determine total size of variable, get values as strings.
var varTotalSize = varSize[0] * varSize[1] * varSize[2];
string[] varValStr = new string[varTotalSize];
Array.Copy(arrayAllVars, i, varValStr, 0, varTotalSize);
// Convert values from string to double.
double[] varValDbl = new double[varTotalSize];
varValDbl = Array.ConvertAll(varValStr, Double.Parse);
// Add variable to dictionary.
if (dictAllVars.ContainsKey(varDb + "_" + varName))
dictAllVars.Remove(varDb + "_" + varName);
dictAllVars.Add(varDb + "_" + varName, new Y_Variable(varDb, varName,
varTyp, varDim, varOrder, varSize, varValDbl));
i += varTotalSize;
}
return dictAllVars;
}
}