Enregistrement des données dans un fichier binaire
Je voudrais enregistrer un fichier en binaire, parce que j'ai entendu dire qu'il serait probablement plus petit que normal d'un fichier texte.
Maintenant, je suis en train d'enregistrer un fichier binaire avec un peu de texte, mais le problème est que le fichier contient uniquement le texte et NULL
à la fin. Je m'attends à voir seulement le zéro et l'un est à l'intérieur du fichier.
Toute explication ou suggestions sont très appréciés.
Voici mon code
#include <iostream>
#include <stdio.h>
int main()
{
/*Temporary data buffer*/
char buffer[20];
/*Data to be stored in file*/
char temp[20]="Test";
/*Opening file for writing in binary mode*/
FILE *handleWrite=fopen("test.bin","wb");
/*Writing data to file*/
fwrite(temp, 1, 13, handleWrite);
/*Closing File*/
fclose(handleWrite);
/*Opening file for reading*/
FILE *handleRead=fopen("test.bin","rb");
/*Reading data from file into temporary buffer*/
fread(buffer,1,13,handleRead);
/*Displaying content of file on console*/
printf("%s",buffer);
/*Closing File*/
fclose(handleRead);
std::system("pause");
return 0;
}
- C'est C pas du C++, en plus de votre un std::appel système
- Bon, d'accord, C ensuite. Mais pourquoi n'est-il pas de travail?
Vous devez vous connecter pour publier un commentaire.
Tous les fichiers contiennent uniquement des zéros et des uns, sur les ordinateurs binaires c'est de jouer avec.
Lorsque vous enregistrez du texte, vous permet d'économiser de la représentation binaire de ce texte, dans un encodage qui définit la façon dont chaque lettre est mappé à bits.
Donc pour le texte, un fichier texte ou un fichier binaire presque n'importe pas; les économies de l'espace que vous avez entendu parler généralement entrent en jeu pour d'autres types de données.
Considérer un nombre à virgule flottante, comme 3.141592653589. Si enregistré en tant que texte, qui permettrait de prendre un personnage par chiffre (juste de les compter), plus la période. S'il est enregistré dans le fichier binaire comme juste une copie de la
float
's bits, il faudra quatre personnages (quatre octets, soit 32 bits) sur un système 32 bits. Le nombre exact de bits stockés par un appel tel que:est
CHAR_BIT * sizeof x
, voir<stdlib.h>
pourCHAR_BIT
.Le problème que vous décrivez est une chaîne de (très fréquent1, malheureusement) d'erreurs et de malentendus. Je vais essayer de m'entièrement en détail ce qui se passe, j'espère que vous prendrez le temps de lire tout le matériel: il est long, mais elles sont très importantes notions de base que tout programmeur doit maîtriser. S'il vous plaît ne désespérez pas si vous ne comprenez pas parfaitement tout cela: juste essayer de jouer un peu avec elle, de revenir dans une semaine ou deux, en pratique, voir ce qui se passe 🙂
Il y a une différence cruciale entre les concepts d'un personnage encodage et un caractère ensemble. À moins que vous vraiment comprendre cette différence, vous ne serez jamais vraiment ce qui se passe, ici. Joel Spolsky (l'un des fondateurs de Stackoverflow, venez pour penser à elle) a écrit un article expliquant la différence il y a un moment: Le Minimum Absolu que Tout Développeur Doit Absolument, Positivement Savoir Sur Unicode et les Jeux de Caractères (Pas d'Excuses!). Avant de poursuivre la lecture de cet, avant de continuer la programmation, même, de le lire. Honnêtement, le lire, le comprendre: le titre n'est pas exagéré. Vous devez absolument savoir ce genre de choses.
Après cela, laissez-nous procéder:
Quand un C programme s'exécute, un emplacement mémoire qui est supposé détenir une valeur de type "char" contient, comme n'importe quel autre emplacement de mémoire, une série de uns et de zéros. "type" d'une variable que signifie quelque chose pour le compilateur, pas pour le programme en cours d'exécution qui ne voit que des zéros et des uns et ne sait pas plus que ça. En d'autres termes: où vous avez l'habitude de penser à une "lettre" (un élément à partir d'un caractère ensemble) résidant en mémoire quelque part, qu'est-ce que réellement il y a une séquence de bits (un élément à partir d'un caractère encodage).
Chaque compilateur est libre d'utiliser tout codage qu'ils souhaitent représenter des caractères dans la mémoire. En conséquence, il est libre de représenter ce que nous appelons un "saut de ligne" à l'interne comme à n'importe quel nombre il choisit. Par exemple, dis-je écrire un compilateur, j'ai peut convenir avec moi que chaque fois que je veux stocker un "saut de ligne" le plan interne, je le stocke en tant que nombre de six (6), qui est juste 0x6 en binaire (ou 110 en binaire).
L'écriture d'un fichier se fait par dire le système d'exploitation2 quatre choses en même temps:
fwrite()
)fwrite
)Remarque que cela n'a rien à voir avec le "type" de données: exploitation n'a aucune idée, et ne se soucie pas. Il ne sait rien au sujet de jeux de caractères et il ne se soucie pas: il voit juste une séquence de uns et de zéros de commencer quelque chose et de copies que pour un fichier.
L'ouverture d'un fichier en "binaire", le mode est en fait normal, intuitive façon de traiter avec les fichiers d'un programmeur novice pourrait s'attendre: à l'emplacement de mémoire sélectionné est copié l'un-à-un pour le fichier. Si vous écrivez un emplacement de mémoire utilisé pour contenir des variables que le compilateur a décidé de magasin de type "char", ces valeurs sont écrits l'un-à-un pour le fichier. Sauf si vous savez comment le compilateur magasins de valeurs à l'intérieur (la valeur qu'elle associe avec un saut de ligne, avec une lettre 'a', 'b', etc), il n'en EST rien. Comparez cela à Joël le même sens, à propos d'un fichier texte inutile sans savoir ce que son codage est: de la même chose.
L'ouverture d'un fichier en mode "texte" est presque égale à la mode binaire, avec un (et un seul) différence: à chaque fois qu'une valeur est écrite qui a une valeur égale à ce que le compilateur utilise en INTERNE pour le retour à la ligne (6, dans notre cas), il écrit quelque chose de différent pour le fichier: pas de valeur, mais quel que soit le système d'exploitation vous êtes sur la considère comme un retour à la ligne. Sur windows, c'est deux octets (13 et 10, ou 0x0d 0x0a, sur Windows). Remarque, encore une fois, si vous ne savez pas à propos de le compilateur est le choix de la représentation interne des autres personnages, c'est TOUJOURS de SENS.
Noter à ce stade qu'il est assez clair qu'écrire n'importe quoi, mais les données que le compilateur désignés comme des caractères d'un fichier en mode texte est une mauvaise idée: dans notre cas, un 6 peut juste arriver à être parmi les valeurs que l'on écrit, auquel cas la sortie est modifié d'une manière que nous n'avons absolument pas dire.
(Onu)Heureusement, la plupart (tous?) les compilateurs en fait utiliser la même représentation interne de caractères: cette représentation est de US-ASCII, et c'est la mère de toutes les valeurs par défaut. C'est la raison pour laquelle vous pouvez écrire des "personnages" pour un fichier dans votre programme compilé avec n'importe quel compilateur, puis de l'ouvrir avec un éditeur de texte: ils utilisent tous/comprendre les US-ASCII, et il arrive à travailler.
OK, maintenant pour le connecter à votre exemple: pourquoi il n'y a pas de différence entre l'écriture de "test" en mode binaire et en mode texte? Car il n'y a pas de saut de ligne dans "test", c'est pourquoi!
Et ce que cela signifie quand vous "ouvrir un fichier", puis "voir" les personnages? Cela signifie que le programme que vous avez utilisé pour inspecter la séquence de uns et de zéros dans ce fichier (parce que tout est de uns et de zéros sur votre disque dur) a décidé d'interpréter que US-ASCII, et qui est arrivé à être ce que votre compilateur a décidé de coder cette chaîne, dans son mémoire.
Points Bonus: écrire un programme qui lit les uns et de zéros à partir d'un fichier dans la mémoire et imprime tous les BITS (il y a plusieurs bits pour faire un octet, de les extraire vous avez besoin de savoir "bit à bit" opérateur astuces, google!) comme un "1" ou "0" pour l'utilisateur. Notez que "1" est le CARACTÈRE 1, le point dans le jeu de caractères de votre choix, de sorte que votre programme doit prendre un peu de temps (1 ou 0) et de la transformer en une séquence de bits nécessaires pour représenter le caractère 1 ou 0 dans le codage de l'émulateur de terminal utilise que de la visualisation de la norme du programme sur oh mon Dieu. Bonne nouvelle: vous pouvez prendre beaucoup de raccourcis en supposant US-ASCII partout. Ce programme va vous montrer ce que vous vouliez: la série de uns et de zéros que votre compilateur utilise pour représenter "test" à l'interne.
Ce genre de choses est vraiment intimidant pour les débutants, et je sais qu'il m'a fallu du temps même de savoir qu'il y était une différence entre un jeu de caractères et un encodage, et encore moins comment tout cela fonctionnait. J'espère ne pas vous démotiver, si je l'ai fait, rappelez-vous juste que vous ne pouvez jamais perdre de connaissances que vous avez déjà, seulement de le gagner (ok pas toujours vrai :P). Il est normal dans la vie qu'une déclaration soulève plus de questions qu'il n'en résout, Socrate savait cela, et sa sagesse toute transparence s'applique à la technologie moderne de jour 2.4 k ans plus tard.
Bonne chance, n'hésitez pas à continuer à poser. Pour les autres lecteurs: n'hésitez à améliorer ce post si vous voyez des erreurs.
Hraban
1 La personne qui vous a dit que "l'enregistrement d'un fichier en binaire est probablement les plus petits", par exemple, probablement gravement méconnaît ces principes fondamentaux. Sauf qu'il faisait allusion à compresser les données avant de vous enregistrer, dans ce cas, il utilise simplement une confusion de mots ("binaire") pour "comprimé".
2 "raconter le système d'exploitation de quelque chose" est ce qui est communément connu comme un appel système.
Bien, la différence entre les indigènes et binaire est la façon la fin de la ligne est gérée.
Si vous écrivez une chaîne de caractères dans un fichier binaire, il restera la chaîne.
Si vous voulez faire plus court, vous devez en quelque sorte le compresser (cherchez libz par exemple).
Ce qui est petit, c'est: lorsque l'on veut enregistrer des données binaires (comme un tableau d'octets), il est plus petit pour l'enregistrer en tant que binaire plutôt que de le mettre dans une chaîne de caractères (soit en hexa représentation ou base64). J'espère que cette aide.
zlib
oulibz
?Je pense que vous êtes un peu confus, ici.
L'ASCII-chaîne "Test" sera toujours un ASCII chaîne lorsque vous écrire dans le fichier (même en mode binaire). Les cas où il est logique d'écrire binaires sont pour d'autres types de caractères (par exemple, un tableau d'entiers).
essayez de remplacer
avec
La fonction printf("%s",buffer); imprimés tampon comme le zéro de fin de chaîne.
Essayez d'utiliser:
char temp[20]="Test\n\rTest";
printf()
ici.