Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Contribuez Discussion :

Buffer E/S rapide pour fichier


Sujet :

Contribuez

  1. #1
    Membre du Club
    Buffer E/S rapide pour fichier
    Bonjour !

    Dans certaines applications qui doivent charger, interpréter, écrire des fichiers, les opérations de lecture/écriture prennent parfois beaucoup de temps si on écrit caractère par caractère par exemple.
    J'ai donc progammé une bibliothèque de fonctions de lecture/écriture dans des fichiers, avec un buffer. Par exemple dans le cas de l'importation d'un fichier WAV avec traitement et écriture à la volée, j'ai diminué le temps d'exécution par 4.

    Je donne les sources ici, c'est une archive 7-zip.

    Je me demande quand même si ce que j'ai fait n'existe pas déjà dans des librairies +/- standard, c'est quand même pratique.

    J'ai créé 2 structures de données, une pour le buffer en lecture et une pour le buffer en écriture. Principalement parce que c'est beaucoup plus facile comme ça plutôt que de faire un unique type de buffer qui fonctionnerait en lecture et en écriture, et qui aussi consommerait un peu plus de CPU. Enfin ça viendra peut-être, mais pour l'instant moi je n'en ai pas besoin...

    Les fonctions disponibles sont :
    - écriture/lecture d'un unique caractère
    - écriture/lecture d'une plage entière
    - positionnement à un endroit particulier dans le fichier
    - récupérer la position courante

  2. #2
    Expert éminent sénior
    Quelques remarques (en commentaires) après une lecture rapide :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    filebufw *filebuf_openw(char *nom, int param, int size) {
    	filebufw *fb;
    	if((fb=malloc(sizeof(*fb))) == NULL) return NULL;
    	fb->file = fopen(nom, (param ? "wb+":"wb"));
    	if(fb->file == NULL) return NULL;           // perte mémoire
    ....


    idem dans filebufr *filebuf_openr(char *nom, int size)

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    int filebuf_addm(void *ptr, int size, filebufw *fb) {
    ....
    	ptr+=towrite; ....                         //ptr est void *


    idem dans filebuf_popm(void *ptr, int size, filebufr *fb)
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  3. #3
    Membre du Club
    Bonjour !

    En effet diogene, je m'étais aperçu de la perte de mémoire mais je n'avais pas internet pendant ces vacances alors je n'ai pas encore actualisé le code. Je crois bien que j'ai aussi fait une ou deux retouches plus esthétiques qu'autre chose, en tout cas ce sera dans le nouveau code. Je préviendrai quand il sera disponible.

    Remplacer
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    	if(fb->file == NULL) return NULL;           // perte mémoire

    par
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    	if(fb->file == NULL) {free(fb); return NULL;}


    Mais pour le void* moi j'aime bien parce que ça évite les warnings du compilateur. Je veux dire, la fonction n'est pas faite pour écrire des char* uniquement, mais n'importe quelle donnée.

    Si on veut écrire des données int ou double ou n'importe quelle structure exotique on met tranquilement :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    filebuf_addm(&ma_donnee, sizeof(ma_donnee), fb)

    et le tour est joué...

  4. #4
    Expert éminent sénior
    Le passage d'un void * en paramètre est logique. C'est l'incrément du void *,qui me gène :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    ptr+=towrite; ....
    Du fait que le type (donc la taille) de l'objet pointé est inconnu, de combien sera incrémenté ptr ? En bonne logique, ce devrait être interdit.
    J'ai testé sur 2 compilateurs. Le premier me donne une erreur et le second un warning (ce qui est le moins qu'on puisse attendre).
    Je n'ai pas trouvé de comportement clairement défini dans la norme sur la question de l'arithmétique mettant en cause un pointeur sur void.

    Pour ces raisons, j'éviterais ce genre d'écriture.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  5. #5
    Membre du Club
    J'ai actualisé les sources avec les modifications que j'ai indiquées dans mon dernier post.
    Je donne les sources ici, c'est une archive 7-zip.

    Pourtant, je n'ai aucune erreur ni aucun warning de compilation (avec mingw sous windows) alors je ne me suis pas préoccupé du tout de la manipulation du void*. Peux-tu indiquer les compilateurs que tu as utilisé ?

    En tout cas si on fait comme ça le problème doit être réglé :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    ptr=(char*)ptr+towrite;

    Je vais me documenter un peu avant de faire la modif dans le code. En tout cas il y a plusieurs endroits à modifier.

    Mais quand même, vu que l'unité élémentaire de mémoire c'est l'octet, mon void* pointe vers un certain octet, alors en incrémentant de N on va aller N octets plus loin... et comme sizeof() renvoie un nombre d'octets, tout le monde doit être content ! en fait je ne vois pas trop comment il faut se représenter ce fameux void* si tu dis que ça pose problème... pour moi c'est de le transtyper en char* qui n'est pas logique parce que la nature des données manipulées on s'en moque pas mal.

    Est-ce que tu peux expliquer ? et dire dire ce qui ne va pas dans mon avis ?

  6. #6
    Expert éminent sénior
    Un compilateur Borland (Builder 6) indiquait une erreur. Mingw émettait un warning. Ca doit dépendre des options de warnings à la compilation si le tien était muet sur le sujet.
    Pour info, l'unité de mémoire est le byte (qui correspond souvent à un octet).

    La norme dit
    A pointer to void shall have the same representation and alignment requirements as a pointer to a character type
    Mais elle ne dit pas (ou du moins je ne sais pas où) que l'arithmétique des void* est celle des char*.

    Normalement, incrémenter un pointeur augmente l'adresse concernée du nombre de bytes égal à la taille de l'objet pointé. Dans le cas de void *, cette taille est inconnue et on ne devrait pas faire d'arithmétique sur ces pointeurs (ni les déréférencer). C'est leur différence par rapport à un char*.

    A ta place, j'opérerais un transtypage tant que ce point est incertain.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  7. #7
    Membre du Club
    Aah bah si c'est la norme qui le dit
    J'ai mis à jour le code, toujours dispo ici en archive 7-zip.

    Mais quand je compile j'active TOUS les warnings pourtant (-Wall), sous MingW et rien n'apparaît à ce sujet. J'ai une version plutôt récente de MingW, celle incluse dans CodeBlocks 8.02

  8. #8
    Expert éminent
    Citation Envoyé par komput Voir le message
    J'ai une version plutôt récente de MingW, celle incluse dans CodeBlocks 8.02
    Et qui est la même que celle incluse depuis C:B 1.0 .

  9. #9
    Membre confirmé
    Citation Envoyé par komput Voir le message
    Je me demande quand même si ce que j'ai fait n'existe pas déjà dans des librairies +/- standard, c'est quand même pratique.
    Il y a les fonctions setbuf() et setvbuf().
    :wq

  10. #10
    Membre du Club
    Et qui est la même que celle incluse depuis C:B 1.0 .
    moi qui pensais qu'ils suivaient un minimum, je vais regarder ça

    Il y a les fonctions setbuf() et setvbuf().
    Oui, mais j'ai fait l'essai sur ma machine et ça marche pas. Je veux dire mon petit code est toujours 2-3 fois plus rapide quand j'écris caractère par caractère. Je ne l'ai toujours pas testé sous linux, ma machine a trop de mal. Mais si vous avez des chiffres, c'est toujours bienvenu...

###raw>template_hook.ano_emploi###