简体   繁体   English

读取/写入xml变量

[英]reading/writing variables to xml

I have been looking for a while how to write a list of details of each player registered on a server so that when people log in, their details are loaded from the xml file and they resume from where they logged off. 我一直在寻找如何编写服务器上注册的每个播放器的详细信息列表的方法,这样,当人们登录时,其详细信息将从xml文件加载,并从注销位置恢复。

I know there are a lot of tutorials out there, but I cant seem to make any work. 我知道那里有很多教程,但是我似乎无法做任何工作。 I need random access and for the file to be updated on the hard disk in real time. 我需要随机访问,并且要在硬盘上实时更新文件。 Current code (far from working) shows the sort of format im after, but I dont understand most concepts of xml, for example what is an attribute/node/element? 当前的代码(远没有奏效)显示了im之后的格式,但是我不了解xml的大多数概念,例如什么是属性/节点/元素? tutorials seem to like to assume you know.. 教程似乎想假设您知道..

XMLFile = XDocument.Load(@"C:/users.xml");
var users = XMLFile.Descendants( "Users" );
int count = 0;
foreach ( var user in users )
{
  count++;
  userName[count] = user.ToString();

  XElement element = (XMLFile.FirstNode as XElement);
  userPass[count] = element.Value;

  XAttribute attribute = (XMLFile.NextNode as XAttribute);
  userLocation[count] = attribute.Value;

  attribute = (XAttribute)XMLFile.NextNode;
  userRotation[count] = attribute.Value;
}

The idea is that the file would be formatted something like this (as xml..) 这个想法是文件将被格式化为这样的格式(如xml ..)。

Users
    Aaron
        password
        vector3 of location
        Quaternion of Rotation
    SomeoneElse
        hispassword
        Vector3 of location
        Quaternion of rotation
    //and so on....

The values would be read upon a client logging in and sent accross the network everything else works I just cant get any method of reading/writing xml to work so thanks for the help. 客户端登录后将读取值,并在整个网络上发送该值,其他所有方法都起作用,我只是无法获得任何读取/写入xml的方法来工作,因此感谢您的帮助。

First of all it's not a valid XML format. 首先,它不是有效的XML格式。 I guess you meant this: 我想你的意思是:

<Users>
   <User>
    <Username>...</Username>
    <Password>...</Password>
    <Location>...</Location>
    <Rotation>..</Rotation>
  </User>

</Users>

Second, as i see you storing each user values into seperate arrays, why ? 第二,正如我看到的那样,将每个用户值存储到单独的数组中,为什么呢? Just add a User class, and define a collection of Users, and for reading use this code: 只需添加一个User类,并定义一个Users集合,供阅读,请使用以下代码:

XDocument xDoc = XDocument.Load(@"C:/users.xml");
List<User> users = (from u in xDoc.Descendants("User")
                    select new User {
                        Name = u.Element("Username").Value,
                        Password = u.Element("Password").Value,
                        Location = u.Element("Locations").Value,
                        Rotation = u.Element("Rotation").Value
                    }).ToList();

And you asked " what is an attribute/node/element " 然后您问“ what is an attribute/node/element

Let's assume we have this element: 假设我们有这个元素:

<User ID = "23">
   <Username>User123</Username>
</User>

In this particular element: 在此特定元素中:

  • ID is an Xml Attribute IDXml属性
  • User and Username are Xml Element UserUsernameXml元素
  • User is parent element of Username User是的父元素 Username
  • And everything is Xml Node , for Example: User is an Element Node , "User123" is a Text Node etc... 一切都是Xml Node ,例如: UserElement Node"User123"Text Node等...

Update: Write to XML 更新:写入XML

If you have this xml structure you can simply append new values like this (or create a new xml): 如果您具有此xml结构,则可以简单地附加这样的新值(或创建一个新的xml):

I assume you have a collection named users 我假设您有一个名为users的集合

XElement xmlElement = new XElement("Users",
            from user in users
            select new XElement("User",
                new XElement("Username", user.Username),
                new XElement("Password", user.Password),
                new XElement("Location", user.Location),
                new XElement("Rotation", user.Rotation)));
xmlElement.Save("Users.xml");

Update: Validate User 更新:验证用户

string userName = textBox1.Text;
string password = textBox2.Text;
XDocument xDoc = XDocument.Load(@"C:/users.xml");
var userControl = (from u in xDoc.Descendants("User") 
                    where u.Element("Username").Value == userName
                         && u.Element("Password").Value == password
                           select u).Any();

if(userControl)
{
    // validated...
} else {
 // User doesn't exist or password wrong
}

First of all you can consider these two xml document formats: 首先,您可以考虑以下两种xml文档格式:

This one is using attributes to store your data: 这是使用属性来存储数据的方法:

<Users>
  <User UserName="User1" Pass="Pass1" Location="Location1" Rotation="Rotaition1" />
  <User UserName="User2" Pass="Pass2" Location="Location2" Rotation="Rotaition2" />
</Users>

and this one is using elements to store your data: 而这是使用元素来存储您的数据:

<Users>
  <User>
    <UserName>User1</UserName>
    <Pass>Pass1</Pass>
    <Location>Location1</Location>
    <Rotation>Rotation1</Rotation>
  </User>
  <User>
    <UserName>User2</UserName>
    <Pass>Pass2</Pass>
    <Location>Location2</Location>
    <Rotation>Rotation2</Rotation>
  </User>
</Users>

Sample code for creating first structure: 用于创建第一个结构的示例代码:

    XDocument xDocument = new XDocument();
    XElement rootElement = new XElement("Users");
    rootElement.Add(new XElement("User", new XAttribute("UserName", "User1"), new XAttribute("Pass", "Pass1"), new XAttribute("Location", "Location1"), new XAttribute("Rotation", "Rotaition1")));
    rootElement.Add(new XElement("User", new XAttribute("UserName", "User2"), new XAttribute("Pass", "Pass2"), new XAttribute("Location", "Location2"), new XAttribute("Rotation", "Rotaition2")));
    xDocument.Add(rootElement);

Sample code for reading first structure: 读取第一个结构的示例代码:

var xElement = xDocument.Descendants("User").Single(element => element.Attribute("UserName").Value == "User1");

Sample code for creating second structure: 用于创建第二个结构的示例代码:

    XDocument xDocument = new XDocument();
    XElement rootElement = new XElement("Users");

    XElement userElement = new XElement("User");
    userElement.Add(new XElement("UserName", "User1"));
    userElement.Add(new XElement("Pass", "Pass1"));
    userElement.Add(new XElement("Location", "Location1"));
    userElement.Add(new XElement("Rotation", "Rotation1"));
    rootElement.Add(userElement);

    userElement = new XElement("User");
    userElement.Add(new XElement("UserName", "User2"));
    userElement.Add(new XElement("Pass", "Pass2"));
    userElement.Add(new XElement("Location", "Location2"));
    userElement.Add(new XElement("Rotation", "Rotation2"));
    rootElement.Add(userElement);

    xDocument.Add(rootElement);

And finally, sample code for reading second structure: 最后,示例代码用于读取第二种结构:

var xElement = xDocument.Descendants("User").Single(element => element.Element("UserName").Value == "User1");

You cas save and load you xml document using this sample: 您可以使用以下示例cas保存并加载xml文档:

xDocument.Save("Your xml file path"); // using Save() instance method
XDocument xDocument = XDocument.Load("Your xml file path"); // using Load() static method

Its your decision whether to choose first structure or second based on your requirements, ease of usage and best practices for a well formed xml document. 您可以根据自己的要求,是否易于使用以及最佳实践来选择格式良好的xml文档,是选择第一种结构还是第二种结构。 In this case I prefer the first structure. 在这种情况下,我更喜欢第一种结构。 For further reading about a well formed xml document refer to this codeproject article: Well-Formed XML 有关结构良好的xml文档的更多信息,请参见以下代码项目文章:结构良好的XML

Note that, the above codes are just some samples for creating those two kinds of xml documents. 请注意,以上代码只是用于创建这两种xml文档的一些示例。 In your case you just have to iterate through users collection and create the xml elements in your loop based on each user object. 在您的情况下,您只需要遍历users集合并根据每个user对象在循环中创建xml元素。

You also asked about xml basic concepts. 您还询问了xml基本概念。 The previous answer by @Selman22 is quick and correct, but for further info see these references: @ Selman22先前的回答是快速正确的,但是有关更多信息,请参见以下参考:

  1. http://www.w3schools.com/xml/default.asp http://www.w3schools.com/xml/default.asp
  2. http://msdn.microsoft.com/en-us/library/bb387019.aspx http://msdn.microsoft.com/en-us/library/bb387019.aspx

Just serialize your user array (or user object and use multiple files) to XML using the XML serializer. 只需使用XML序列化器将用户数组(或用户对象并使用多个文件)序列化为XML。 http://msdn.microsoft.com/en-us/library/182eeyhh(v=vs.110).aspx http://msdn.microsoft.com/zh-CN/library/182eeyhh(v=vs.110).aspx

Write an file (from MSDN) 写入文件(来自MSDN)

MySerializableClass myObject = new MySerializableClass();
// Insert code to set properties and fields of the object.
XmlSerializer mySerializer = new 
XmlSerializer(typeof(MySerializableClass));
// To write to a file, create a StreamWriter object.
using (StreamWriter myWriter = new StreamWriter("myFileName.xml"))
{   
   mySerializer.Serialize(myWriter, myObject);
}

Read from an object (from MSDN) 从对象读取(从MSDN)

MySerializableClass myObject;
// Construct an instance of the XmlSerializer with the type
// of object that is being deserialized.
XmlSerializer mySerializer = 
new XmlSerializer(typeof(MySerializableClass));
// To read the file, create a FileStream.
using (FileStream myFileStream = new FileStream("myFileName.xml", FileMode.Open))
{
   // Call the Deserialize method and cast to the object type.
   myObject = (MySerializableClass) 
   mySerializer.Deserialize(myFileStream)
}

As an aside, writing to disk in "real time" is very expensive, and you may want to consider limiting your disc accesses. 顺便说一句,“实时”写入磁盘非常昂贵,您可能需要考虑限制磁盘访问。 If your users have a "save" option, you could do your disc write then, or do it on some kind of timer. 如果您的用户具有“保存”选项,则可以进行光盘刻录,也可以使用某种计时器进行刻录。

As far as random access is concerned, that should be done in memory (not in the file). 就随机访问而言,这应该在内存中完成(而不是在文件中)。 Basically your flow would be: User logs in -> Read user data from file into memory -> User does stuff -> update object in memory -> user saves or "autosave" -> write object to disk. 基本上,您的流程将是:用户登录->从文件中将用户数据读取到内存中->用户操作->更新内存中的对象->用户保存或“自动保存”->将对象写入磁盘。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM