2013-07-30 10 views
5

Czytam plik xml o nieznanej długości i czytając każdy element w strukturze listy. Teraz, gdy dojdę do końca pliku, kontynuuję czytanie, to powoduje wyjątek. Właśnie złapałem ten wyjątek i kontynuowałem swoje życie, ale czy istnieje lepszy sposób na zrobienie tego?Jak obsługiwać koniec pliku podczas odczytu pliku XML

try 
{ 
    while(!textReader.EOF) 
    { 
     // Used to store info from each command as they are read from the xml file 
     ATAPassThroughCommands command = new ATAPassThroughCommands();      
     // the following is just commands being read and their contents being saved 
     XmlNodeType node = textReader.NodeType;            

     textReader.ReadStartElement("Command"); 
     node = textReader.NodeType; 
     name = textReader.ReadElementString("Name"); 
     node = textReader.NodeType; 
     CommandListContext.Add(name); 
     command.m_Name = name; 
     command.m_CMD = Convert .ToByte(textReader.ReadElementString("CMD"),16); 
     command.m_Feature = Convert .ToByte(textReader.ReadElementString("Feature"),16); 

     textReader.ReadEndElement(); //</command> 
     m_ATACommands.Add(command); 
    } 
} 
catch (Exception ex) 
{ 
    //</ATAPassThrough> TODO: this is an ugly fix come up with something better later 
    textReader.ReadEndElement(); 
    //cUtils.DisplayError(ex.Message); 
} 

plik xml:

<ATAPassThrough> 
    <Command> 
    <Name>Smart</Name> 
    <CMD>B0</CMD> 
    <Feature>D0</Feature> 
    </Command> 
    <Command> 
    <Name>Identify</Name> 
    <CMD>B1</CMD> 
    <Feature>D0</Feature> 
    </Command> 
    . 
    . 
    . 
    . 
</ATAPassThrough> 
+4

Dowolny powód, dla którego nie używasz [XmlDocument] (http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.aspx) lub [XDocument] (http://msdn.microsoft .com/en-us/library/system.xml.linq.xdocument.aspx) (preferowane, jeśli masz dostęp do .Net 3.5)? –

+0

nie tylko go nie znasz – yawnobleix

+0

Czy możesz pominąć przykład twojego pliku XML? –

Odpowiedz

11

Polecam przy użyciu XDocument do odczytywania danych XML ... na przykład w przypadku, ponieważ masz już TextReader dla XML można po prostu przekazać, że w Metoda XDocument.Load ... cała powyższa funkcja wygląda tak:

var doc = XDocument.Load(textReader); 
foreach (var commandXml in doc.Descendants("Command")) 
{ 
    var command = new ATAPassThroughCommands(); 
    var name = commandXml.Descendants("Name").Single().Value; 
    // I'm not sure what this does but it looks important... 
    CommandListContext.Add(name); 
    command.m_Name = name; 
    command.m_CMD = 
     Convert.ToByte(commandXml.Descendants("CMD").Single().Value, 16); 
    command.m_Feature = 
     Convert.ToByte(commandXml.Descendants("Feature").Single().Value, 16); 
    m_ATACommands.Add(command); 
} 

Znacznie łatwiej. Pozwól ramie wykonać dla ciebie ciężki lifting.

+0

działał idealnie Prawdopodobnie spędzę trochę czasu, ucząc się więcej o XDocument, ponieważ wydaje się całkiem przydatny. – yawnobleix

+0

Zdecydowanie tak. Nazywa się to linq do xml, jeśli chcesz wyszukać informacje o tym, jak manipulować XML w ten sposób. – Kevin

+0

Dzięki za pomoc! – paqogomez

6

Prawdopodobnie najprostszym sposobem, jeśli masz normalny i spójny XML, jest użycie XML Serializer.

Pierwszy tworzyć obiekty, które pasują do Twojego XML

[Serializable()] 
public class Command 
{ 
    [System.Xml.Serialization.XmlElement("Name")] 
    public string Name { get; set; } 

    [System.Xml.Serialization.XmlElement("CMD")] 
    public string Cmd { get; set; } 

    [System.Xml.Serialization.XmlElement("Feature")] 
    public string Feature { get; set; } 
} 

[Serializable()] 
[System.Xml.Serialization.XmlRoot("ATAPassthrough")] 
public class CommandCollection 
{ 
    [XmlArrayItem("Command", typeof(Command))] 
    public Command[] Command { get; set; } 
} 

The sposób do powrotu CommandCollection

public class CommandSerializer 
{ 
    public commands Deserialize(string path) 
    { 
    CommandCollection commands = null; 

    XmlSerializer serializer = new XmlSerializer(typeof(CommandCollection)); 

    StreamReader reader = new StreamReader(path); 
    reader.ReadToEnd(); 
    commands = (CommandCollection)serializer.Deserialize(reader); 
    reader.Close(); 

    return commands ; 
    } 
} 

Nie jestem pewien, czy to jest dokładnie poprawne, nie mam środków do przetestuj to, ale powinno być naprawdę blisko.

+1

FYI, Serializator XML nie potrzebuje atrybutu "[Serializable]". –

+1

Zgadzam się, mam tendencję do oznaczania klas jako '[Serializowalne]', gdy zamierzam je serializować (binarne, xml, json, itp.) Pozwala innym programistom wiedzieć, że będzie serializowany. To pozwala im podjąć środki ostrożności, jeśli wymagane są zmiany. Zwłaszcza jeśli programiści (tacy jak ja), którzy lubią patrzeć na zwinięty kod, mogę powiedzieć, że powinien być możliwy serializowanie bez sprawdzania w klasie. –

Powiązane problemy