2009-09-30 8 views
2

Considérez le code suivant:XmlMtomReader stratégie de lecture

Stream stream = GetStreamFromSomewhere(); 
XmlDictionaryReader mtomReader =XmlDictionaryReader.CreateMtomReader 
(
stream, 
Encoding.UTF8, 
XmlDictionaryReaderQuoatas.Max 
); 

/// ... 

/// is there best way to read binary data from mtomReader's element?? 
string elementString = mtomReader.XmlReader.ReadElementString(); 
byte[] elementBytes = Covert.FromBase64String(elementString); 
Stream elementFileStream = new FileStream(tempFileLocation); 
elementFileStream.Write(elementBytes,0,elementBytes.Length); 
elementFileStream.Close(); 

/// ... 

mtomReader.Close(); 

Le problème est que la taille de la pièce jointe binaire censé être sur 100Mb parfois. Existe-t-il un moyen de lire le bloc de pièces jointes d'un élément par bloc, puis de l'écrire dans le flux de fichier temporaire afin d'éviter d'allouer de la mémoire pour le trou? Le deuxième problème - encore plus spécifique - mtomReader crée-t-il un cache interne de la pièce jointe mime binaire avant de lire le contenu de l'élément, c'est-à-dire allouer de la mémoire pour les données binaires? Ou lit-il directement les octets du flux d'entrée?

Répondre

3

Pour ceux qui pourraient être intéressés par la solution:

using (Stream stream = GetStreamFromSomewhere()) 
{ 
    using (
    XmlDictionaryReader mtomReader = XmlDictionaryReader.CreateMtomReader(
     stream, Encoding.UTF8, XmlDictionaryReaderQuotas.Max)) 
{ 
    string elementString = mtomReader.ReadElementString(); 
    byte[] buffer = new byte[1024]; 
    using (
     Stream elementFileStream = 
      new FileStream(tempFileLocation, FileMode.Create)) 
    { 
     while(mtomReader.XmlReader.ReadElementContentAsBase64(buffer,0,buffer.Length) 
     { 
      elementFileStream.Write(buffer, 0, buffer.Length); 
     } 
    } 

    /// ... 

    mtomReader.Close(); 
} 
} 

ReadElementContentAsBase64 (...) aide à lire le bloc par bloc parties binaires. Le deuxième numéro de mon article a été parfaitement couvert ici: Does XmlMtomReader cache binary data from the input stream internally?

0

Pour une pièce jointe de cette taille, il serait préférable d'utiliser le streaming.

transferts peuvent streamées améliorer l'évolutivité d'un service en éliminant l'exigence pour les grands tampons de mémoire. Si le changement du mode de transfert améliore l'évolutivité dépend de la taille des messages en cours de transfert. Les grandes tailles de message favorisent l'utilisation de transferts en streaming.

Voir: http://msdn.microsoft.com/en-us/library/ms731913.aspx

+0

Merci. Mais cela n'influe pas non plus sur mes questions. Je travaille avec XmlMtomReader et non avec les services WCF. – sh0gged

0

Pour commencer, votre code devrait être plus comme ceci:

using (Stream stream = GetStreamFromSomewhere()) 
{ 
    using (
     XmlDictionaryReader mtomReader = XmlDictionaryReader.CreateMtomReader(
      stream, Encoding.UTF8, XmlDictionaryReaderQuotas.Max)) 
    { 
     string elementString = mtomReader.ReadElementString(); 
     byte[] elementBytes = Convert.FromBase64String(elementString); 
     using (
      Stream elementFileStream = 
       new FileStream(tempFileLocation, FileMode.Create)) 
     { 
      elementFileStream.Write(
       elementBytes, 0, elementBytes.Length); 
     } 

     /// ... 

     mtomReader.Close(); 
    } 
} 

Sans les using blocs, vous êtes à risque de fuites de ressources.

+0

C'est vrai. Mais cela ne résout pas mon problème de toute façon. :( – sh0gged

+0

J'avais espéré que la réponse serait évidente, mais je ne pensais pas que l'utilisation de la méthode 'ReadSubTree' avec la lecture du contenu en morceaux pourrait aider, mais je ne sais pas –