Lecture et écriture de vecteur C ++ dans un fichier
Pour certains, le travail graphique j'ai besoin de lire une grande quantité de données aussi rapidement que possible et l'idéal serait de directement lire et écrire les structures de données sur le disque. Fondamentalement, j'ai un chargement des modèles 3d dans divers formats de fichiers qui prennent trop de temps à charger donc je veux les écrire dans leur "préparé" format comme un cache qui se chargent beaucoup plus rapidement sur les exécutions ultérieures du programme.
Est-il sécuritaire de le faire de cette façon?
Mes soucis sont directement autour de la lecture des données du vecteur? J'ai enlevé la vérification des erreurs, codé en dur 4 que la taille de l'int et ainsi de suite afin que je puisse donner un court exemple de travail, je sais que c'est un mauvais code, ma question est vraiment s'il est sûr en c++ pour lire toute une gamme de structures directement dans un vecteur comme cela? Je crois qu'il en soit ainsi, mais le c++ a beaucoup de pièges et indéfini comportements quand vous commencez à aller de bas niveau et de traiter directement avec la mémoire brute comme ça.
Je me rends compte que nombre de formats et de tailles peuvent changer à travers les plates-formes et les compilateurs, mais cela ne pourra même être lu et écrit par le même compilateur programme pour mettre en cache les données nécessaires sur un plus tard l'exécution du même programme.
#include <fstream>
#include <vector>
using namespace std;
struct Vertex
{
float x, y, z;
};
typedef vector<Vertex> VertexList;
int main()
{
//Create a list for testing
VertexList list;
Vertex v1 = {1.0f, 2.0f, 3.0f}; list.push_back(v1);
Vertex v2 = {2.0f, 100.0f, 3.0f}; list.push_back(v2);
Vertex v3 = {3.0f, 200.0f, 3.0f}; list.push_back(v3);
Vertex v4 = {4.0f, 300.0f, 3.0f}; list.push_back(v4);
//Write out a list to a disk file
ofstream os ("data.dat", ios::binary);
int size1 = list.size();
os.write((const char*)&size1, 4);
os.write((const char*)&list[0], size1 * sizeof(Vertex));
os.close();
//Read it back in
VertexList list2;
ifstream is("data.dat", ios::binary);
int size2;
is.read((char*)&size2, 4);
list2.resize(size2);
//Is it safe to read a whole array of structures directly into the vector?
is.read((char*)&list2[0], size2 * sizeof(Vertex));
}
source d'informationauteur jcoder
Vous devez vous connecter pour publier un commentaire.
Comme Laurynas dit,
std::vector
est garanti d'être contiguës, donc ça devrait fonctionner, mais il est potentiellement non-portable.Sur la plupart des systèmes,
sizeof(Vertex)
sera de 12, mais il n'est pas rare pour les struct être rembourré, de sorte quesizeof(Vertex) == 16
. Si vous souhaitez écrire les données sur un système et lire ce fichier sur un autre, il n'y a aucune garantie que cela fonctionnera correctement.Vous pourriez être intéressé par le Coup de pouce.La sérialisation de la bibliothèque. Il sait comment enregistrer/charger des conteneurs STL vers/à partir du disque, entre autres choses. Il serait peut-être exagéré pour votre exemple simple, mais il pourrait être plus utile si vous faites d'autres types de sérialisation dans votre programme.
Voici un exemple de code qui fait ce que vous cherchez:
Que j'ai eu à mettre en œuvre un
serialize
fonction de votreVertex
dans leboost::serialization
espace de noms. Cela permet à la bibliothèque de sérialisation savoir comment sérialiserVertex
membres.J'ai parcouru les
boost::binary_oarchive
code source et il semble que l'on lit/écrit les premières vecteur de la matrice de données directement à partir de/vers la mémoire tampon du flux. Il devrait donc être assez rapide.std::vector
est garanti d'être en continu dans la mémoire, donc, oui.Je viens de tomber sur exactement le même problème.
Tout d'abord, ces déclarations sont cassés
Il y a d'autres trucs dans le Vecteur structure de données, ce qui permettra de faire de votre nouveau vecteur d'obtenir rempli d'ordures.
Solution:
Lorsque vous écrivez votre vecteur dans un fichier, ne vous inquiétez pas au sujet de la taille de votre Sommet de la classe, juste écrire directement la totalité du vecteur dans la mémoire.
Et puis vous pouvez lire l'intégralité de vecteur en mémoire à la fois
Une autre alternative explicite de la lecture et de l'écriture de votre
vector<>
depuis et vers un fichier est de remplacer le sous-jacent de l'allocateur avec celui qui alloue de la mémoire à partir d'un fichier mappé en mémoire. Cela vous permettra d'éviter un intermédiaire en lecture/écriture liées à la copie. Cependant, cette approche n'ont que des frais généraux. À moins que votre fichier est très volumineux, il ne peut faire sens pour votre cas particulier. Profil comme d'habitude pour déterminer si cette approche est un bon ajustement.Il y a aussi quelques mises en garde de cette approche sont très bien traitée par le Coup de pouce.Interprocessus de la bibliothèque. D'un intérêt particulier pour vous peut-être, son allocateurs et conteneurs.
Si ce est utilisé pour la mise en cache par le même code, je ne vois pas de problème avec cela. J'ai utilisé cette technique sur plusieurs systèmes sans problème (Unix). Comme précaution supplémentaire, vous pourriez écrire un struct avec les valeurs connues au début du fichier, et de vérifier qu'il est ok. Vous pouvez également enregistrer la taille de la structure dans le fichier. Cela permettra d'économiser beaucoup de temps de débogage dans l'avenir si le rembourrage ne change jamais.