CasFiles

lib et documentation rédigée par Julien P. (Orwell).

Télechargement

A propos de cette lib

Lorsqu’un programme est amené à manipuler beaucoup de données (sprites, maps, textes...), il est souvent pratique de placer ces données dans un fichier externe et de ne charger que ce qui est nécessaire pour le programme.

Le problème qui se pose alors c’est que les fonctions qu’on peut utiliser pour manipuler ces fichiers (généralement celles de stdio.h) sont assez lourdes et peuvent augmenter la taille de l’exécutable de façon non négligeable.

Le but de cette lib est de proposer des fonctions ayant un rôle similaire à celles de stdio.h, mais sans effectuer de gestion particulière pour la manipulation des fichiers. Ces fonctions se limitent en fait à effectuer des appels aux différents services de l’interruption 21h, afin que celle-ci soit facilement utilisable dans un programme écrit globalement en C ou C++.

Comme leur comportement est assez simple leur taille est nettement plus petite que celles de stdio.h, et elles pourront alors les remplacer afin de faire gagner quelques Kos à l’exécutable. Leur manipulation est globalement identique. Voici la liste des fonctions “réécrites”: fopen(), fclose(), fread(), fseek(), ftell(), fgetc(), fgets(), findfirst() et findnext(). Elles sont devenues cfopen(), cfclose(), cfread() etc dans cette lib. J’en ai également profité pour rendre cfread() capable d’écrire les données d’un fichier vers une adresse far (il est donc par exemple possible de charger un fichier dans une memzone sans passer par un buffer), et pour corriger le comportement de cfindfirst() lorsque le système rencontre une erreur due à une recherche de fichier dans un lecteur vide.

Utilisation

L’utilisation des fonctions est globalement identique à celles de stdio.h. Vous pouvez également vous reporter à leur documentation pour avoir des exemples d’utilisation.

Toutes les fonctions de la lib ont une macro correspondante dans casfiles.h. Si vous n’avez pas besoin de certaines fonctions dans votre programme, il vous suffit de mettre leurs macros en commentaires et elles seront ignorées par le compilateur, ce qui vous permettra de diminuer un peu la taille du programme.

Par exemple si vous n’avez pas besoin de cfgetc() et cfgets(), il suffit de mettre en commentaire les lignes suivantes:

 #define FUNC_CFGETC
 #define FUNC_CFGETS 

Toutes les fonctions renvoient un code d’erreur qui indique comment s’est déroulée l’opération. Cette valeur est nulle quand tout s’est passé correctement, et négative si une erreur est survenue.

Les codes d’erreurs sont également définis dans le fichier casfiles.h.

Ouverture et fermeture d'un fichier

On ouvre un fichier grâce à la fonction cfopen(), à laquelle on doit passer le chemin complet du fichier (par exemple “L:myfile.txt”) et un “handle” qui servira à identifier le fichier par la suite.

On peut alors accéder à son contenu en connaissant son handle.

Lorsque la lecture est terminée, il faut refermer le fichier avec la fonction cfclose() en luipassant le handle qui devient ainsi invalide.

 #include "casfiles.h"
 void main()
 {
    HANDLE leFichier; // le handle qui identifie le fichier
    if( cfopen("L:myfile.txt", leFichier) == DONE ) // si l'ouverture s'est bien passee
    {
       ... // traitement du contenu du fichier
       cfclose(leFichier); // fermeture
    }
 }

Lecture

La lecture du contenu d’un fichier se fait généralement avec les fonctions cfread() et cfcopy().

Il faut spécifier l’endroit où l’on veut enregistrer les données lues, le nombre d’octets à lire , la position dans le fichier des données en question dans le cas de cfcopy(), et bien entendu le handle du fichier ouvert. cfread() lit les données à partir de la position actuelle, tandis que cfcopy() lit donc à partir de la position spécifiée.

Notez que cfread() est plus rapide que cfcopy() puisqu’elle n’a pas à se soucier de la position du pointeur qui avance automatiquement.

L’enregistrement des données lues peut se faire directement vers le contenu d’une memzone par exemple. N’oubliez cependant pas que cette écriture dans la mémoire n’est pas protégée, et que vous risquez de provoquer la perte totale des données si vous n’écrivez pas au bon endroit!!

Pointeur courant

La position du pointeur dans le fichier avance au fur et à mesure qu’on en extrait des données (sauf en utilisant cfcopy()).

Il est possible de positionner ce pointeur à un endroit particulier du fichier afin d’accéder directement à certaines données, ou de récupérer son emplacement actuel.

Ceci se fait avec les fonctions cfseek() et cftell().

cfseek() permet de deplacer le pointeur: il faut lui passer la valeur du déplacement a effectuer, la position relative du déplacement, et le handle du fichier. La position relative peut être le début du fichier (SEEK_SET), la position actuelle (SEEK_CUR) ou la fin du fichier (SEEK_END).

 cfseek(10, SEEK_SET, leFichier); // on se positionne 10 octets après le début du fichier
 cfseek(-3, SEEK_CUR, leFichier); // on recule de 3 octets, on est donc maintenant 7 
                                         //octets après le début

cftell() demande qu’on lui passe l’entier dans lequel il va enregistrer la position (sa valeur de retour étant toujours le code d’erreur), et le handle du fichier.

Extraction de (chaînes de) caractères

Les fonctions cfread() et cfcopy() sont particulièrement utiles pour lire des données dans des fichiers binaires; dans le cas de fichiers au format texte, les fonctions cfgetc() et cfgets() seront généralement plus pratiques. cfgetc() extrait un seul caractère du fichier à partir de la position courante: il faut lui passer un caractère dans lequel la donnée sera écrite, ainsi que le handle du fichier à lire.

cfgets() peut lire une chaîne de caractères entière terminée par un retour à la ligne ( ‘r’ ) ou une nouvelle ligne ( ‘n’ ).

La chaîne est écrite à l’emplacement spécifié (elle sera complétée par un caractère nul, le retour à la ligne n’étant pas recopié), et ne pourra pas dépasser la taille maximum indiquée, auquel cas elle sera simplement tronquée.

Recherche de fichiers

Il est possible de rechercher des fichiers dans un lecteur avec les fonctions cfindfirst() et cfindnext(). cfindfirst() effectue une première recherche à l’emplacement spécifié, tandis que cfindnext cherche les occurrences suivantes.

Il est possible d’utiliser des masques comme ‘?’ et ‘*’ dans le chemin d’accès, et de spécifier des attributs pour les fichiers (cachés, système, etc). Les informations sur les fichiers trouvés sont écrites dans une structure FILEDATA qui s’utilise de la même manière que les structures find_t et ffblk de stdio.h. Exemple d’utilisation:

 FILEDATA data;
 allowEmptyDrives(); // A appeler normalement une seule fois au début du prog
 if( cfindfirst("L:*.EXE", FA_NORMAL, &data) == DONE ) 
 {// on cherche tous les exécutables du lecteur L
    do { printf("trouvé: %s, taille %dn", data.name, data.size); }
    while( cfindnext(&data) == DONE ); 
 }

Il faut généralement être prudent lorsqu’on cherche des fichiers dans un lecteur vide, car il y a un risque de plantage de la machine.

Il est possible d’éviter le plantage grâce à des fonctions de dos.h et de faire en sorte que cfindfirst() renvoie une erreur “empty drive” en cas de problème.

Cette gestion se fait grâce à la fonction allowEmptyDrives() qu’il suffit d’appeler une fois au début du prog lorsqu’on prévoit un risque de problème. Si cette fonction n’a pas été appelée, le programme va planter en tombant sur un lecteur vide.

Notez que les routines de dos.h utilisées ont une taille non négligeable (~500 octets en tout) et qu’il est donc intéressant de désactiver cette fonction lorsqu’elle n’est pas utilisée.

Petit exemple

#include <stdio.h>
#include <conio.h>
#include "casfiles.h"
void main()
{
unsigned char i;
char temp[50];
char testPath[20]="L:EXAMPLE.TST";
FILEDATA fdata;
allowEmptyDrives();
	// I wanna find the file 'example.tst' on the root of a drive
	// I try all drives
for(; testPath[0]<='Q' && cfindfirst(testPath,FA_NORMAL,&fdata) != DONE ;
testPath[0]++);
if(testPath[0]<='Q') // I've found it!
{
	HANDLE myFile;
	int error;
	printf("Found: %sn",testPath);
	error = cfopen(testPath,myFile);	// I open it
	if(error < 0)
	{
		printf("Can't open the file!nReturned code: %dn",error);
	}
	else
	{
		error = cfgets(temp,50,myFile);	 // I read the first string (max 50 bytes)
		if(error < 0)
		{
			printf("Can't read the file!nReturned code: %dn",error);
		}
		else
		{
			printf("Read: %s|n",temp);
		}
		cfclose(myFile); // I have to close it now
	}
}
else
{
	printf("File not found :(n");
}
getch();
}

RFLlib

Lib implémenté par Julien

Télechargement

Role de cette Lib

 
lib_gestflash.txt · Dernière modification: 2007/07/08 11:28 par 193.250.238.185
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki