2010-05-24 5 views
0

Je voudrais créer une simple visionneuse de fichiers texte et je voudrais qu'elle soit capable de gérer de gros fichiers (peut-être plus gros que la mémoire de l'ordinateur).Visionneuse de fichiers avec tampon coulissant

Je sais que j'ai besoin de mettre en œuvre quelque chose comme un tampon glissant, qui contiendra la partie actuellement visible du fichier. Le problème principal est de déterminer la relation entre les lignes et les décalages de fichiers. Si je devais juste être en mesure de naviguer par lignes, j'aurais juste besoin d'une liste chaînée des lignes et en ligne haut/bas, il suffit de lire la nouvelle ligne du fichier. Mais que dois-je faire quand je veux aussi aller, disons 50% du fichier? J'ai besoin de montrer les lignes à partir de la moitié du fichier, donc si le fichier est long de 10000 octets, je chercherais à byte 5000, chercher un saut de ligne et afficher des trucs à partir de là. Le problème est que je ne sais pas dans quelle ligne je suis quand je cherche comme ça. Donc, ce que je voudrais savoir, c'est ce que serait une structure de données appropriée pour garder ces quelques lignes en mémoire (celles qui seront peintes à l'écran). Gardez à l'esprit que je n'ai pas besoin d'éditer les fichiers, il suffit de les voir, donc je n'ai pas besoin de m'inquiéter de l'efficacité de l'approche choisie pour l'édition.

Répondre

0

Si vous lisez dans un morceau défini d'octets via un FileStream, vous pouvez garder une trace de l'octet que vous avez lu en dernier afin que vous sachiez où aller pour lire plus de morceaux de données du fichier. FileStream expose Read() qui vous permet de spécifier un octet de décalage (position à démarrer) et aussi combien d'octets lire à la fois. Après avoir lu dans vos octets, vous pouvez les décoder en UTF8 avec un décodeur, par exemple, puis récupérer un tableau char. Tout cela devrait initialiser vos données initiales. Ce que je ferais puisque ce sera affiché quelque part est la configuration des gestionnaires d'événements liés au défilement. Lorsque vous commencez à défiler vers le bas, vous pouvez supprimer les lignes supérieures de la mémoire (en même temps, compter leurs octets avant de les supprimer pour pouvoir lire dynamiquement les octets suivants avec la même taille) et ajouter de nouvelles lignes en bas. De même pour le défilement vers le haut. Si vous souhaitez déterminer la moitié de vos données, vous pouvez essayer quelque chose avec un objet FileInfo sur le chemin du fichier texte, puis en utilisant la méthode Length() pour renvoyer le nombre d'octets. Puisque les flux traitent en octets, cela est pratique lorsque vous essayez de lire un pourcentage. Vous pouvez l'utiliser pour définir le nombre d'octets à lire. Vous devez lire les données pour déterminer où sont les sauts de ligne et définir le dernier octet lu comme CR-LF à ramasser à la ligne suivante lorsque vous récupérez des données.

Voici ce que je ferais pour lire un nombre prédéfini d'octets à partir d'un fichier.

public static LastByteRead = 0; // keep it zero indexed 

public String[] GetFileChunk(String path, long chunkByteSize) 
{ 
    FileStream fStream; 
    String[] FileTextLines; 
    int SuccessBytes = 0; 
    long StreamSize; 
    byte[] FileBytes; 
    char[] FileTextChars; 
    Decoder UtfDecoder = Encoding.UTF8.GetDecoder(); 
    FileInfo TextFileInfo = new FileInfo(path); 

    if(File.Exists(path)) 
    { 
     try { 
      StreamSize = (TextFileInfo.Length >= chunkByteSize) ? chunkByteSize : TextFileInfo.Length; 
      fStream = new FileStream(path, FileMode.Open, FileAccess.Read); 
      FileBytes = new byte[ StreamSize ]; 
      FileTextChars = new char[ StreamSize ]; // this can be same size since it's UTF-8 (8bit chars) 

      SuccessBytes = fStream.Read(FileBytes, 0, (Int32)StreamSize); 

      if(SuccessBytes > 0) 
      { 
       UtfDecoder.GetChars(FileBytes, 0, StreamSize, FileTextChars, 0); 
       LastByteRead = SuccessBytes - 1; 

       return 
        String.Concat(fileTextChars.ToArray<char>()).Split('\n'); 
      } 

      else 
       return new String[1] {""}; 
     } 

     catch { 
      var errorException = "ERROR: " + ex.Message; 
      Console.Writeline(errorException); 
     } 

     finally { 
      fStream.Close(); 
     } 
    } 
} 

Peut-être que cela vous mènera au moins dans la bonne direction.