2015-07-28 2 views
1

Je n'arrive pas à faire fonctionner le modèle MemoryMappedFile. J'ai un répertoire avec 25 feuilles de calcul Excel que je veux charger en utilisant MemoryMappedFile. Le MemoryMappedFile.CreateFromFile fonctionne très bien, mais quand je l'appelle MemoryMappedFile.OpenExisting (prêteur), il lit les 3 premiers fichiers, puis sur la 4ème tentative, il échoue à l'exception:MemoryMappedFile: Impossible de trouver le fichier spécifié

Impossible de trouve le fichier spécifié.

public static void Main() 
{ 
    var files = System.IO.Directory.EnumerateFiles(@"lendersheets", "*.xls*").ToList(); 
    foreach (var file in files) 
    { 
     var lender = System.IO.Path.GetFileNameWithoutExtension(file); 

     MemoryMappedFile.CreateFromFile(file, FileMode.Open, lender); 
    } 

    foreach (var file in files) 
    { 
     var lender = System.IO.Path.GetFileNameWithoutExtension(file); 

     using (var mmfExisting = MemoryMappedFile.OpenExisting(lender)) 
     { 
      var stream = mmfExisting.CreateViewStream(); 
      if (stream.CanRead && stream.CanWrite) 
      { 
       LoadFromStream(stream); 
      } 
     }        
    } 
} 

MISE À JOUR:

J'ai remarqué que lorsque je retire l'appel de méthode LoadFromStream, l'exception ne se produit plus. Voici la logique pour LoadFromStream:

private static object LoadFromStream(Stream stream) 
    { 
     hssfwb = new HSSFWorkbook(stream); 
     evaluator = new HSSFFormulaEvaluator(hssfwb); 

     return hssfwb; 
    } 
+0

Quelle est la raison pour laquelle vous utilisez des mappages de mémoire? Ce code particulier ne semble pas les exiger. – usr

+0

Pour la performance, je suppose. Il faut environ 5 secondes pour charger les 25 feuilles de calcul en mémoire. Une fois en mémoire, j'appelle chaque flux, j'entre les valeurs dans la feuille Excel, puis je lis les valeurs des cellules calculées. Je ne veux pas charger les 25 fichiers Excel chaque fois que j'ai besoin de faire des calculs. Je pensais que l'utilisation de MemoryMappedFiles était la voie à suivre? – FaNIX

+0

Vous ne savez pas ce que vous voulez dire. La lecture d'un fichier deux fois le met en cache. Probablement que le temps des OI est de 5% de votre temps total, tout ceci est discutable. Mesure. – usr

Répondre

0

J'ai fini par faire ce qui suit. J'ai une instance singleton d'une collection de tous les fichiers dans la mémoire. Je crée ensuite une nouvelle instance du flux de mémoire lorsque j'ai besoin d'utiliser le fichier spécifique dans la mémoire pour les calculs:

private static readonly Dictionary<string, MemoryStream> _lenderPolicyFileStreams = new Dictionary<string, MemoryStream>(); 

     private static void CreateLenderPolicyFileStreams() 
     { 
      string appDataPath = HostingEnvironment.MapPath("~/App_Data"); 
      var files = Directory.EnumerateFiles(appDataPath, "*.xls*").ToList(); 

      foreach (var file in files) 
      { 
       var lenderName = Path.GetFileNameWithoutExtension(file); 

       // Create a file stream 
       var bytes = File.ReadAllBytes(file); 
       var stream = new MemoryStream(bytes); 

       // Add file stream to singleton collection 
       if (lenderName != null) 
        _lenderPolicyFileStreams.Add(lenderName, stream); 
      } 
     } 

     public static Stream GetMemoryStreamByLenderName(string lender) 
     { 
      MemoryStream fetchedStream; 
      _lenderPolicyFileStreams.TryGetValue(lender, out fetchedStream); 

      if (fetchedStream == null) 
       throw new Exception("Cannot find specified file stream by lender name"); 

      var clone = CloneStream(fetchedStream); 
      return clone; 
     } 

     private static MemoryStream CloneStream(MemoryStream fileStream) 
     { 
      var memoryStream = new MemoryStream(); 

      fileStream.Position = 0; 
      fileStream.CopyTo(memoryStream); 
      memoryStream.Position = 0; 

      return memoryStream; 
     }