从文件读取数据和存储的最佳方式?
Best way to read data and store from file?
我有一个以这种方式存储数据的文本文件:
Player name: NAME HERE
Speed: 7
Strength: 9
Stamina: 4
Player name: ANOTHER NAME HERE
Speed: 5
Strength: 8
Stamina: 3
同一个文件包含大约 15 个不同的选手,我想从他们每个人那里收集数值,存储在一个临时的比赛变量中,然后计算速度强度和耐力的平均值并给出获胜者。我的第一个想法是使用正则表达式,但我目前正在研究是否有另一种更可持续的方法来做到这一点。
这是我的一个副项目,欢迎任何帮助。谢谢
如果文件格式是固定的,解决这个问题的一种方法是使用 System.IO.File.ReadAllLines
获取文件中的每一行,然后遍历行,拆分密钥([=12 的左侧) =]) 和值(:
右边)。使用处理每一行时从文件中读取的值填充某种数据对象(下例中的PlayerObject
)。
PlayerObject player = new PlayerObject();
string[] allLines = System.IO.File.ReadAllLines(FILE_PATH_HERE);
foreach(string dataPair in allLines)
{
string[] pair = dataPair.Split(new[] { ':' });
if(pair.Length == 2)
{
switch(pair[0])
{
case "Player name": /*process pair[1]*/ break;
case "Speed": /*process pair[1]*/ break;
//other possible key strings here
//recommend defining these as constants
}
}
}
这将允许您对文件中的参数重新排序(或至少支持不同的排序),如果缺少任何参数,可以将它们预先设置为数据对象中的某个默认值。
您的格式中唯一缺少的是记录之间的某种标记值。现在您可以假设每个玩家都由一个新的 "Player name" 条目描述,并在您阅读下一个 "Player name".
后开始填充下一个 PlayerObject
定义你的种族Class结构:
public class Race
{
public string Name;
public int Speed;
public int Strength;
public int Stamina;
}
从文本文件中读取数据,实例化 Race
对象并将它们收集到 List<Race>
中。收集完成后,您可以通过 List
调用 Average()
获取结果。
string[] myTextFileLines = File.ReadAllLines(myTextFile);
List<Race> myRaces = new List<Race>();
for (int i = 0; i < myTextFileLines.Length; i += 4)
{
myRaces.Add(new Race()
{
Name = myTextFileLines[i].Substring(myTextFileLines[i].IndexOf(":") + 2),
Speed = Convert.ToInt32(myTextFileLines[i + 1].Substring(myTextFileLines[i + 1].IndexOf(":") + 2)),
Strength = Convert.ToInt32(myTextFileLines[i + 2].Substring(myTextFileLines[i + 2].IndexOf(":") + 2)),
Stamina = Convert.ToInt32(myTextFileLines[i + 3].Substring(myTextFileLines[i + 3].IndexOf(":") + 2)),
});
}
Console.WriteLine("Avg Speed: {0}", myRaces.Average(r => Convert.ToDouble(r.Speed)));
Console.WriteLine("Avg Strength: {0}", myRaces.Average(r => Convert.ToDouble(r.Strength)));
Console.WriteLine("Avg Stamina: {0}", myRaces.Average(r => Convert.ToDouble(r.Strength)));
Console.ReadLine();
结果(使用您在问题中提供的确切数据):
XML 解决方案示例:
Players.xml
<?xml version="1.0" encoding="utf-8" ?>
<players>
<player name="Alice">
<speed>7</speed>
<strength>9</strength>
<stamina>4</stamina>
</player>
<player name="Bob">
<speed>5</speed>
<strength>8</strength>
<stamina>3</stamina>
</player>
</players>
C# 代码
private class Player
{
public string Name { get; set; }
public int Speed { get; set; }
public int Strength { get; set; }
public int Stamina { get; set; }
public override string ToString()
{
return "Name: " + Name + Environment.NewLine +
"Speed: " + Speed + Environment.NewLine +
"Strength: " + Strength + Environment.NewLine +
"Stamina: " + Stamina + Environment.NewLine;
}
}
private static void PrintXmlPlayers(XmlNode players)
{
foreach (XmlNode player in players.SelectNodes("player"))
{
string playerName = player.Attributes["name"].InnerText;
int playerSpeed = XmlConvert.ToInt32(player["speed"].InnerText);
int playerStrength = XmlConvert.ToInt32(player["strength"].InnerText);
int playerStamina = XmlConvert.ToInt32(player["stamina"].InnerText);
Player aPlayer = new Player
{
Name = playerName,
Speed = playerSpeed,
Strength = playerStrength,
Stamina = playerStamina
};
Console.WriteLine(aPlayer);
}
}
private static void TestXml()
{
// path of document is relative to executable
const string xmlPath = "../../Players.xml";
XmlDocument doc = new XmlDocument();
doc.Load(xmlPath);
XmlNode players = doc["players"];
PrintXmlPlayers(players);
XmlNode alice = players.SelectSingleNode("player[@name='Alice']");
string aliceOldString = alice["strength"].InnerText;
alice["strength"].InnerText = "10";
doc.Save(xmlPath);
PrintXmlPlayers(players);
alice["strength"].InnerText = aliceOldString;
doc.Save(xmlPath);
}
输出
Name: Alice
Speed: 7
Strength: 9
Stamina: 4
Name: Bob
Speed: 5
Strength: 8
Stamina: 3
Name: Alice
Speed: 7
Strength: 10
Stamina: 4
Name: Bob
Speed: 5
Strength: 8
Stamina: 3
我有一个以这种方式存储数据的文本文件:
Player name: NAME HERE Speed: 7 Strength: 9 Stamina: 4 Player name: ANOTHER NAME HERE Speed: 5 Strength: 8 Stamina: 3
同一个文件包含大约 15 个不同的选手,我想从他们每个人那里收集数值,存储在一个临时的比赛变量中,然后计算速度强度和耐力的平均值并给出获胜者。我的第一个想法是使用正则表达式,但我目前正在研究是否有另一种更可持续的方法来做到这一点。
这是我的一个副项目,欢迎任何帮助。谢谢
如果文件格式是固定的,解决这个问题的一种方法是使用 System.IO.File.ReadAllLines
获取文件中的每一行,然后遍历行,拆分密钥([=12 的左侧) =]) 和值(:
右边)。使用处理每一行时从文件中读取的值填充某种数据对象(下例中的PlayerObject
)。
PlayerObject player = new PlayerObject();
string[] allLines = System.IO.File.ReadAllLines(FILE_PATH_HERE);
foreach(string dataPair in allLines)
{
string[] pair = dataPair.Split(new[] { ':' });
if(pair.Length == 2)
{
switch(pair[0])
{
case "Player name": /*process pair[1]*/ break;
case "Speed": /*process pair[1]*/ break;
//other possible key strings here
//recommend defining these as constants
}
}
}
这将允许您对文件中的参数重新排序(或至少支持不同的排序),如果缺少任何参数,可以将它们预先设置为数据对象中的某个默认值。
您的格式中唯一缺少的是记录之间的某种标记值。现在您可以假设每个玩家都由一个新的 "Player name" 条目描述,并在您阅读下一个 "Player name".
后开始填充下一个PlayerObject
定义你的种族Class结构:
public class Race
{
public string Name;
public int Speed;
public int Strength;
public int Stamina;
}
从文本文件中读取数据,实例化 Race
对象并将它们收集到 List<Race>
中。收集完成后,您可以通过 List
调用 Average()
获取结果。
string[] myTextFileLines = File.ReadAllLines(myTextFile);
List<Race> myRaces = new List<Race>();
for (int i = 0; i < myTextFileLines.Length; i += 4)
{
myRaces.Add(new Race()
{
Name = myTextFileLines[i].Substring(myTextFileLines[i].IndexOf(":") + 2),
Speed = Convert.ToInt32(myTextFileLines[i + 1].Substring(myTextFileLines[i + 1].IndexOf(":") + 2)),
Strength = Convert.ToInt32(myTextFileLines[i + 2].Substring(myTextFileLines[i + 2].IndexOf(":") + 2)),
Stamina = Convert.ToInt32(myTextFileLines[i + 3].Substring(myTextFileLines[i + 3].IndexOf(":") + 2)),
});
}
Console.WriteLine("Avg Speed: {0}", myRaces.Average(r => Convert.ToDouble(r.Speed)));
Console.WriteLine("Avg Strength: {0}", myRaces.Average(r => Convert.ToDouble(r.Strength)));
Console.WriteLine("Avg Stamina: {0}", myRaces.Average(r => Convert.ToDouble(r.Strength)));
Console.ReadLine();
结果(使用您在问题中提供的确切数据):
XML 解决方案示例:
Players.xml
<?xml version="1.0" encoding="utf-8" ?>
<players>
<player name="Alice">
<speed>7</speed>
<strength>9</strength>
<stamina>4</stamina>
</player>
<player name="Bob">
<speed>5</speed>
<strength>8</strength>
<stamina>3</stamina>
</player>
</players>
C# 代码
private class Player
{
public string Name { get; set; }
public int Speed { get; set; }
public int Strength { get; set; }
public int Stamina { get; set; }
public override string ToString()
{
return "Name: " + Name + Environment.NewLine +
"Speed: " + Speed + Environment.NewLine +
"Strength: " + Strength + Environment.NewLine +
"Stamina: " + Stamina + Environment.NewLine;
}
}
private static void PrintXmlPlayers(XmlNode players)
{
foreach (XmlNode player in players.SelectNodes("player"))
{
string playerName = player.Attributes["name"].InnerText;
int playerSpeed = XmlConvert.ToInt32(player["speed"].InnerText);
int playerStrength = XmlConvert.ToInt32(player["strength"].InnerText);
int playerStamina = XmlConvert.ToInt32(player["stamina"].InnerText);
Player aPlayer = new Player
{
Name = playerName,
Speed = playerSpeed,
Strength = playerStrength,
Stamina = playerStamina
};
Console.WriteLine(aPlayer);
}
}
private static void TestXml()
{
// path of document is relative to executable
const string xmlPath = "../../Players.xml";
XmlDocument doc = new XmlDocument();
doc.Load(xmlPath);
XmlNode players = doc["players"];
PrintXmlPlayers(players);
XmlNode alice = players.SelectSingleNode("player[@name='Alice']");
string aliceOldString = alice["strength"].InnerText;
alice["strength"].InnerText = "10";
doc.Save(xmlPath);
PrintXmlPlayers(players);
alice["strength"].InnerText = aliceOldString;
doc.Save(xmlPath);
}
输出
Name: Alice
Speed: 7
Strength: 9
Stamina: 4
Name: Bob
Speed: 5
Strength: 8
Stamina: 3
Name: Alice
Speed: 7
Strength: 10
Stamina: 4
Name: Bob
Speed: 5
Strength: 8
Stamina: 3