int main (int argc, char **argv)
{
string filename;
// If there is no command-line filename, have the user enter one
if(argc < 2)
{
cout << "Enter a filename: ";
cin >> filename;
cout << "Filename is: " << filename << endl;
cout << endl;
}
else
{
filename = argv[1];
}
// Set number of parts of file and offset
unsigned int part;
long offset;
offset = 0;
do {
part = 1;
cout << "Enter Number of parts into file is split (Enter 1 to exit)
[1-99] : ";
cin >> part;
}
while (part < 1 || part > 99);
if ( part == 1 ) return 1;
cout << "Number of parts is: " << setfill('0') << setw(2) << part << endl;
offset = lengthFile / part;
cout << "Length part of file is: " << offset << " bytes." << endl;
cout << endl;
// Create parts of file
stringstream ss;
string partfilename;
beginPos = 0;
endPos = 0;
for (unsigned int counter = 0; counter < part; counter++)
{
ss.clear();
ss << filename << setfill('0') << setw(2) << counter + 1.0 ;
ss >> partfilename;
cout << "Create " << partfilename;
int main (int argc, char **argv)
{
string baseFilename;
// If there is no command-line filename, have the user enter one
if(argc < 2)
{
cout << "Enter base of split filename ( foo for foo01): ";
cin >> baseFilename;
cout << "BaseFilename is: " << baseFilename << endl;
cout << endl;
}
else
{
baseFilename = argv[1];
}
unsigned int part;
do {
part = 1;
cout << "Enter Number of parts file is split (Enter 1 to exit) [1-99] : ";
cin >> part;
}
while (part < 1 || part > 99);
if ( part == 1 ) return 1;
// Test all part filename
stringstream ss;
string partfilename;
for (unsigned int counter = 0; counter < part; counter++)
{
ss.clear();
ss << baseFilename << setfill('0') << setw(2) << counter + 1.0 ;
ss >> partfilename;
buffer = new char [size];
infile.read (buffer,size);
ofstream outfile;
// ios::app open for writing,add to end of file(append).
outfile.open(baseFilename.c_str(), ios::app | ios::binary);
beginPos = outfile.tellp();
cout << beginPos << endl;
int main (int argc, char **argv) { string filename;
// If there is no command-line filename, have the user enter one if(argc < 2) { cout << "Enter a filename: "; cin >> filename; cout << "Filename is: " << filename << endl; cout << endl; } else { filename = argv[1]; }
// Determine length of file long beginPos, endPos, lengthFile;
Ici commence mes doutes. Qu'est-ce qui te fait penser que la taille d'un fichier peut se tenir sur un long. (Ce n'est le cas sur aucun système que moi, je connais. Mais peut-être Windows...)
Mais enfin, ça ne doit poser de problème en fait que si tu as des fichiers plus grand que 2Go.
infile.seekg(0,ios::beg);
Tu y est déjà. Pas besoin d'un seek.
beginPos = infile.tellg();
Ici, c'est plus grave. Le type renvoyait par tellg() n'est pas un type numérique. Selon la norme, il n'y a même pas de garantie qu'on peut le convertir en type numérique. C'est donc possible que cette ligne ne passe même pas le compilateur.
Même si la conversion est légale, rien ne prouve que la valeur numérique qu'on en obtient signifie quelque chose.
En fait, dans toutes les implémentations Unix et Windows que je connais, ça va marcher. Mais si on veut restreindre la portabilité, dans toutes les implémentations que je connais où ça marche, le résultat est 0.
Sous Solaris, j'y aurais -1 si le fichier a plus de 4 Go. Et une valeur négative si le fichier a entre 2 Go et 4 Go.
cout << endPos << endl;
lengthFile = endPos - beginPos;
Ici surtout, tu suppose que les « étiquettes » de position correspond au nombre d'octets. Rien ne l'impose, et il existe bien des implémentations où ce n'est pas le cas.
Mais enfin, sous Windows ou sous Unix, pour des fichiers pas trop grands... Seulement, si tu n'insistes pas sur la portabilité, il existe une fonction stat sous les deux (ou peut-être _stat ou __stat sous Windows) qui donne le résultat que tu veux, correctement, et sans tout ces soucis. Quand on n'est pas portable, ce n'est pas la peine d'en donner l'air.
(Note bien que je ne critique pas la manque de portabilité en soi. Tous les programmes n'ont pas besoin d'être 100% portables, et j'ai prèsque toujours des choses non portable dans les applications que j'écris.)
// Set number of parts of file and offset unsigned int part; long offset;
offset = 0;
do { part = 1; cout << "Enter Number of parts into file is split (Enter 1 to exit) [1-99] : "; cin >> part; } while (part < 1 || part > 99);
C'est un peu dure pour le type qui entre une valeur invalide. Une boucle sans fin.
if ( part == 1 ) return 1; cout << "Number of parts is: " << setfill('0') << setw(2) << part << endl; offset = lengthFile / part;
Je crois qu'il y a un véritable problème ici. La division des entiers tronque. Donc, si j'ai un fichier qui fait 109 octets, et je dis que je veux 10 parties, chaque partie va faire 10 octets. Et les 9 derniers octets seront perdus. (En supposant que offset doit signifier la longueur de chaque partie. Personellement, j'aurais choisi un nom plutôt comme subfile_length.)
cout << "Length part of file is: " << offset << " bytes." << endl; cout << endl;
// Create parts of file stringstream ss; string partfilename;
beginPos = 0; endPos = 0;
for (unsigned int counter = 0; counter < part; counter++) { ss.clear();
Franchement, j'aurais défini ss ici, pour en avoir une nouvelle instance à chaque passage dans la boucle. C'est la façon la plus sûre d'avoir un objet dans son état initial.
Et même, je me démande si tu sais ce que signifie ios::clear(). Il remet à zéro l'état d'erreur, c'est tout.
J'aurais laissé infile ouvert. J'aurais simplement fait un seekg() au début après avoir détermié la longueur. Et une fois la longueur déterminée, je n'en aurais lu autant chaque fois dans la boucle, sans m'occuper du positionnement. Jusqu'à la fin de fichier, sans faire d'autres calculs.
Sans souci de delete à la fin de la boucle. (Mais ça, c'est moins évident, et je pourrais bien t'excuser de ne pas avoir su que les éléments d'un std::vector sont garanti contigus. Ça ne me serait jamais venu à l'esprit non plus en lisant la norme.)
Pas nécessaire avec std::vector. Mais voir ci-dessus.
outfile.close(); infile.close();
beginPos = ++endPos;
beginPos += size ;
? Et il n'y a pas besoin d'un endPos de tout.
}
cout << "End of fltkSplit" << endl; return 0; }
En fait, je me serais plutôt servi des streambuf derrière des iostream ; l'interface des istream et des ostream est extrèmement mal conçue pour des entrées/sorties binaires. Ce qui donnerait. Ce qui donnerait quelque chose du genre :
filebuf in( filename.c_str(), ios::in | ios::binary ) ; streamsize lu = in.sgetn( &buffer[ 0 ], buffer.size() ) ; int segmentId = 0 ; while ( lu != 0 ) { ++ segmentId ; ostringstream segmentName ; segmentName.fill( '0' ) ; segmentName << filename << setw( 2 ) << segmentId ; filebuf out( segmentName.c_str(), ios::out | ios::binary ) ; if ( ! out.is_open() ) { // Erreur fatale, n'a pas pu créer segmentName. } if ( out.sputn( &buffer[ 0 ], lu ) != lu || ! out.close() ) { // Erreur fatale, erreur d'écriture. } }
Je n'ai pas le temps de faire un analyse pareil sur merge, mais tu dois avoir déjà pas mal de choses à faire.
-- James Kanze home: www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
hackervalley wrote:
je code un petit example de partitionneur/ reconstituant de
fichiers.
Mais j'ai des pertes d'octets lors de ces manipulations. Faut
- il que je considère en mode binaire le EOF ?
Certainement. Que le fichier soit binaire ou non, il a bien une
fin.
int main (int argc, char **argv)
{
string filename;
// If there is no command-line filename, have the user enter one
if(argc < 2)
{
cout << "Enter a filename: ";
cin >> filename;
cout << "Filename is: " << filename << endl;
cout << endl;
}
else
{
filename = argv[1];
}
// Determine length of file
long beginPos, endPos, lengthFile;
Ici commence mes doutes. Qu'est-ce qui te fait penser que la
taille d'un fichier peut se tenir sur un long. (Ce n'est le cas
sur aucun système que moi, je connais. Mais peut-être
Windows...)
Mais enfin, ça ne doit poser de problème en fait que si tu as
des fichiers plus grand que 2Go.
infile.seekg(0,ios::beg);
Tu y est déjà. Pas besoin d'un seek.
beginPos = infile.tellg();
Ici, c'est plus grave. Le type renvoyait par tellg() n'est pas
un type numérique. Selon la norme, il n'y a même pas de garantie
qu'on peut le convertir en type numérique. C'est donc possible
que cette ligne ne passe même pas le compilateur.
Même si la conversion est légale, rien ne prouve que la valeur
numérique qu'on en obtient signifie quelque chose.
En fait, dans toutes les implémentations Unix et Windows que je
connais, ça va marcher. Mais si on veut restreindre la
portabilité, dans toutes les implémentations que je connais où
ça marche, le résultat est 0.
Sous Solaris, j'y aurais -1 si le fichier a plus de 4 Go. Et une
valeur négative si le fichier a entre 2 Go et 4 Go.
cout << endPos << endl;
lengthFile = endPos - beginPos;
Ici surtout, tu suppose que les « étiquettes » de position
correspond au nombre d'octets. Rien ne l'impose, et il existe
bien des implémentations où ce n'est pas le cas.
Mais enfin, sous Windows ou sous Unix, pour des fichiers pas
trop grands... Seulement, si tu n'insistes pas sur la
portabilité, il existe une fonction stat sous les deux (ou
peut-être _stat ou __stat sous Windows) qui donne le résultat
que tu veux, correctement, et sans tout ces soucis. Quand on
n'est pas portable, ce n'est pas la peine d'en donner l'air.
(Note bien que je ne critique pas la manque de portabilité en
soi. Tous les programmes n'ont pas besoin d'être 100% portables,
et j'ai prèsque toujours des choses non portable dans les
applications que j'écris.)
// Set number of parts of file and offset
unsigned int part;
long offset;
offset = 0;
do {
part = 1;
cout << "Enter Number of parts into file is split (Enter 1 to exit)
[1-99] : ";
cin >> part;
}
while (part < 1 || part > 99);
C'est un peu dure pour le type qui entre une valeur invalide.
Une boucle sans fin.
if ( part == 1 ) return 1;
cout << "Number of parts is: " << setfill('0') << setw(2) << part <<
endl;
offset = lengthFile / part;
Je crois qu'il y a un véritable problème ici. La division des
entiers tronque. Donc, si j'ai un fichier qui fait 109 octets,
et je dis que je veux 10 parties, chaque partie va faire 10
octets. Et les 9 derniers octets seront perdus. (En supposant
que offset doit signifier la longueur de chaque partie.
Personellement, j'aurais choisi un nom plutôt comme
subfile_length.)
cout << "Length part of file is: " << offset << " bytes." << endl;
cout << endl;
// Create parts of file
stringstream ss;
string partfilename;
beginPos = 0;
endPos = 0;
for (unsigned int counter = 0; counter < part; counter++)
{
ss.clear();
Franchement, j'aurais défini ss ici, pour en avoir une nouvelle
instance à chaque passage dans la boucle. C'est la façon la plus
sûre d'avoir un objet dans son état initial.
Et même, je me démande si tu sais ce que signifie ios::clear().
Il remet à zéro l'état d'erreur, c'est tout.
J'aurais laissé infile ouvert. J'aurais simplement fait un
seekg() au début après avoir détermié la longueur. Et une fois
la longueur déterminée, je n'en aurais lu autant chaque fois
dans la boucle, sans m'occuper du positionnement. Jusqu'à la fin
de fichier, sans faire d'autres calculs.
Sans souci de delete à la fin de la boucle. (Mais ça, c'est
moins évident, et je pourrais bien t'excuser de ne pas avoir su
que les éléments d'un std::vector sont garanti contigus. Ça ne
me serait jamais venu à l'esprit non plus en lisant la norme.)
Pas nécessaire avec std::vector. Mais voir ci-dessus.
outfile.close();
infile.close();
beginPos = ++endPos;
beginPos += size ;
? Et il n'y a pas besoin d'un endPos de tout.
}
cout << "End of fltkSplit" << endl;
return 0;
}
En fait, je me serais plutôt servi des streambuf derrière des
iostream ; l'interface des istream et des ostream est
extrèmement mal conçue pour des entrées/sorties binaires. Ce qui
donnerait. Ce qui donnerait quelque chose du genre :
filebuf in( filename.c_str(), ios::in | ios::binary ) ;
streamsize lu = in.sgetn( &buffer[ 0 ], buffer.size() ) ;
int segmentId = 0 ;
while ( lu != 0 ) {
++ segmentId ;
ostringstream segmentName ;
segmentName.fill( '0' ) ;
segmentName << filename << setw( 2 ) << segmentId ;
filebuf out( segmentName.c_str(),
ios::out | ios::binary ) ;
if ( ! out.is_open() ) {
// Erreur fatale, n'a pas pu créer segmentName.
}
if ( out.sputn( &buffer[ 0 ], lu ) != lu
|| ! out.close() ) {
// Erreur fatale, erreur d'écriture.
}
}
Je n'ai pas le temps de faire un analyse pareil sur merge, mais
tu dois avoir déjà pas mal de choses à faire.
--
James Kanze home: www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
int main (int argc, char **argv) { string filename;
// If there is no command-line filename, have the user enter one if(argc < 2) { cout << "Enter a filename: "; cin >> filename; cout << "Filename is: " << filename << endl; cout << endl; } else { filename = argv[1]; }
// Determine length of file long beginPos, endPos, lengthFile;
Ici commence mes doutes. Qu'est-ce qui te fait penser que la taille d'un fichier peut se tenir sur un long. (Ce n'est le cas sur aucun système que moi, je connais. Mais peut-être Windows...)
Mais enfin, ça ne doit poser de problème en fait que si tu as des fichiers plus grand que 2Go.
infile.seekg(0,ios::beg);
Tu y est déjà. Pas besoin d'un seek.
beginPos = infile.tellg();
Ici, c'est plus grave. Le type renvoyait par tellg() n'est pas un type numérique. Selon la norme, il n'y a même pas de garantie qu'on peut le convertir en type numérique. C'est donc possible que cette ligne ne passe même pas le compilateur.
Même si la conversion est légale, rien ne prouve que la valeur numérique qu'on en obtient signifie quelque chose.
En fait, dans toutes les implémentations Unix et Windows que je connais, ça va marcher. Mais si on veut restreindre la portabilité, dans toutes les implémentations que je connais où ça marche, le résultat est 0.
Sous Solaris, j'y aurais -1 si le fichier a plus de 4 Go. Et une valeur négative si le fichier a entre 2 Go et 4 Go.
cout << endPos << endl;
lengthFile = endPos - beginPos;
Ici surtout, tu suppose que les « étiquettes » de position correspond au nombre d'octets. Rien ne l'impose, et il existe bien des implémentations où ce n'est pas le cas.
Mais enfin, sous Windows ou sous Unix, pour des fichiers pas trop grands... Seulement, si tu n'insistes pas sur la portabilité, il existe une fonction stat sous les deux (ou peut-être _stat ou __stat sous Windows) qui donne le résultat que tu veux, correctement, et sans tout ces soucis. Quand on n'est pas portable, ce n'est pas la peine d'en donner l'air.
(Note bien que je ne critique pas la manque de portabilité en soi. Tous les programmes n'ont pas besoin d'être 100% portables, et j'ai prèsque toujours des choses non portable dans les applications que j'écris.)
// Set number of parts of file and offset unsigned int part; long offset;
offset = 0;
do { part = 1; cout << "Enter Number of parts into file is split (Enter 1 to exit) [1-99] : "; cin >> part; } while (part < 1 || part > 99);
C'est un peu dure pour le type qui entre une valeur invalide. Une boucle sans fin.
if ( part == 1 ) return 1; cout << "Number of parts is: " << setfill('0') << setw(2) << part << endl; offset = lengthFile / part;
Je crois qu'il y a un véritable problème ici. La division des entiers tronque. Donc, si j'ai un fichier qui fait 109 octets, et je dis que je veux 10 parties, chaque partie va faire 10 octets. Et les 9 derniers octets seront perdus. (En supposant que offset doit signifier la longueur de chaque partie. Personellement, j'aurais choisi un nom plutôt comme subfile_length.)
cout << "Length part of file is: " << offset << " bytes." << endl; cout << endl;
// Create parts of file stringstream ss; string partfilename;
beginPos = 0; endPos = 0;
for (unsigned int counter = 0; counter < part; counter++) { ss.clear();
Franchement, j'aurais défini ss ici, pour en avoir une nouvelle instance à chaque passage dans la boucle. C'est la façon la plus sûre d'avoir un objet dans son état initial.
Et même, je me démande si tu sais ce que signifie ios::clear(). Il remet à zéro l'état d'erreur, c'est tout.
J'aurais laissé infile ouvert. J'aurais simplement fait un seekg() au début après avoir détermié la longueur. Et une fois la longueur déterminée, je n'en aurais lu autant chaque fois dans la boucle, sans m'occuper du positionnement. Jusqu'à la fin de fichier, sans faire d'autres calculs.
Sans souci de delete à la fin de la boucle. (Mais ça, c'est moins évident, et je pourrais bien t'excuser de ne pas avoir su que les éléments d'un std::vector sont garanti contigus. Ça ne me serait jamais venu à l'esprit non plus en lisant la norme.)
Pas nécessaire avec std::vector. Mais voir ci-dessus.
outfile.close(); infile.close();
beginPos = ++endPos;
beginPos += size ;
? Et il n'y a pas besoin d'un endPos de tout.
}
cout << "End of fltkSplit" << endl; return 0; }
En fait, je me serais plutôt servi des streambuf derrière des iostream ; l'interface des istream et des ostream est extrèmement mal conçue pour des entrées/sorties binaires. Ce qui donnerait. Ce qui donnerait quelque chose du genre :
filebuf in( filename.c_str(), ios::in | ios::binary ) ; streamsize lu = in.sgetn( &buffer[ 0 ], buffer.size() ) ; int segmentId = 0 ; while ( lu != 0 ) { ++ segmentId ; ostringstream segmentName ; segmentName.fill( '0' ) ; segmentName << filename << setw( 2 ) << segmentId ; filebuf out( segmentName.c_str(), ios::out | ios::binary ) ; if ( ! out.is_open() ) { // Erreur fatale, n'a pas pu créer segmentName. } if ( out.sputn( &buffer[ 0 ], lu ) != lu || ! out.close() ) { // Erreur fatale, erreur d'écriture. } }
Je n'ai pas le temps de faire un analyse pareil sur merge, mais tu dois avoir déjà pas mal de choses à faire.
-- James Kanze home: www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Tiens. C'est idiomatique, ça, la conversion de booléen en entier ? Personnellement, j'aurais tendance à expliciter au moyen de l'opérateur ternaire.
C'est une question de religion. Pour beaucoup de programmeurs qui ont leurs racines dans C c'est idiomatique parce que TRUE|FALSE y sont représentés littéralement par 1|0 et la conversion automatique true->1|false->0 existe en C++ justement pour des raisons de compatibilité avec C. (C++ is a better C ;-)
Enfin, c'est une question de gout. Quand tu utilises l'opérateur ternaire il faut introduire des expressions redondantes.
Tiens. C'est idiomatique, ça, la conversion de booléen en entier ?
Personnellement, j'aurais tendance à expliciter au moyen de
l'opérateur ternaire.
C'est une question de religion. Pour beaucoup de programmeurs qui ont
leurs racines dans C c'est idiomatique parce que TRUE|FALSE y sont
représentés littéralement par 1|0 et la conversion automatique
true->1|false->0 existe en C++ justement pour des raisons de
compatibilité avec C. (C++ is a better C ;-)
Enfin, c'est une question de gout. Quand tu utilises l'opérateur
ternaire il faut introduire des expressions redondantes.
Tiens. C'est idiomatique, ça, la conversion de booléen en entier ? Personnellement, j'aurais tendance à expliciter au moyen de l'opérateur ternaire.
C'est une question de religion. Pour beaucoup de programmeurs qui ont leurs racines dans C c'est idiomatique parce que TRUE|FALSE y sont représentés littéralement par 1|0 et la conversion automatique true->1|false->0 existe en C++ justement pour des raisons de compatibilité avec C. (C++ is a better C ;-)
Enfin, c'est une question de gout. Quand tu utilises l'opérateur ternaire il faut introduire des expressions redondantes.
En fait, dans le premier cas, on profite de la conversion implicite entier -> booléen, mais on est explicite sur la valeur de l'expression. Dans le second, on doit explicitement convertir le test en un booléen, et on profite de sa conversion implicite vers un entier.
En fait, dans le premier cas, on profite de la conversion implicite
entier -> booléen, mais on est explicite sur la valeur de
l'expression. Dans le second, on doit explicitement convertir le test
en un booléen, et on profite de sa conversion implicite vers un
entier.
En fait, dans le premier cas, on profite de la conversion implicite entier -> booléen, mais on est explicite sur la valeur de l'expression. Dans le second, on doit explicitement convertir le test en un booléen, et on profite de sa conversion implicite vers un entier.
long segmentSize = size / Count; if (size % Count != 0) { segmentSize++; }
Vous aimez faire dans le compliqué... Pourquoi pas ceci :
long segmentSize = (size+Count-1) / Count;
-- Michel Michaud http://www.gdzid.com FAQ de fr.comp.lang.c++ : http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/
hackervalley
Bonjour à tous,
James Kanze wrote:
Je n'ai pas le temps de faire un analyse pareil sur merge, mais tu dois avoir déjà pas mal de choses à faire.
Effectivement, j'ai pas mal de choses à comprendre.
La proposition d'utiliser la class filebuf conjointement avec la container vector est beaucoup plus élégante.
Mais je ne suis pas arrivé jusqu'à ce point.
Je me suis attardé sur la détermination de la longueur d'un fichier.
L'indication d'utilisation de stat est une piste. En regardant boost/filesystem/operation.. il y a la fonction file_size
BOOST_FILESYSTEM_DECL boost::intmax_t file_size( const path & ph ) { # ifdef BOOST_POSIX struct stat path_stat; if ( ::stat( ph.string().c_str(), &path_stat ) != 0 ) boost::throw_exception( filesystem_error( "boost::filesystem::file_size", ph, fs::detail::system_error_code() ) ); if ( S_ISDIR( path_stat.st_mode ) ) boost::throw_exception( filesystem_error( "boost::filesystem::file_size", ph, "invalid: is a directory", is_directory_error ) ); return static_cast<boost::intmax_t>(path_stat.st_size); # else // by now, intmax_t is 64-bits on all Windows compilers WIN32_FILE_ATTRIBUTE_DATA fad; if ( !::GetFileAttributesExA( ph.string().c_str(), ::GetFileExInfoStandard, &fad ) ) boost::throw_exception( filesystem_error( "boost::filesystem::file_size", ph, fs::detail::system_error_code() ) ); if ( (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) !=0 ) boost::throw_exception( filesystem_error( "boost::filesystem::file_size", ph, "invalid: is a directory", is_directory_error ) ); return (static_cast<boost::intmax_t>(fad.nFileSizeHigh) << (sizeof(fad.nFileSizeLow)*8)) + fad.nFileSizeLow; # endif }
La portabilité est assuré en prenant les cas POSIX et windows. Mais, pour mon utilisation , j'ai essayé de touver une autre façon de déterminer la taille d'un fichier. je suis arrivé à ce code :
// Determine length of file cout << "Number of characters " << buffer.size() << endl; cout << "char is " << sizeof(char) << " bytes " << endl; cout << "Size of " << filename << " is " << buffer.size()*sizeof(char) << " bytes." << endl;
infile.close();
return 0; }
Voilà, hormis l'utilisation processeur puisque je n'utilise pas de buffer , cette façon me donne enfin la bonne taille des fichiers.
J'ai essayé d'imaginer comment utiliser un buffer, mais j'arrive pas à faire la même chose, et le code devient beaucoup trop complexe pour la fonctionnalité.
Je pense utiliser le buffer pour réaliser, le split des fichiers de sortie.
A bientôt, lorsque j'aurai assimilé le reste.
http://hackervalley.free.fr
Bonjour à tous,
James Kanze wrote:
Je n'ai pas le temps de faire un analyse pareil sur merge, mais
tu dois avoir déjà pas mal de choses à faire.
Effectivement, j'ai pas mal de choses à comprendre.
La proposition d'utiliser la class filebuf conjointement avec la
container vector est beaucoup plus élégante.
Mais je ne suis pas arrivé jusqu'à ce point.
Je me suis attardé sur la détermination de la longueur d'un fichier.
L'indication d'utilisation de stat est une piste.
En regardant boost/filesystem/operation.. il y a la fonction file_size
BOOST_FILESYSTEM_DECL boost::intmax_t file_size( const path & ph )
{
# ifdef BOOST_POSIX
struct stat path_stat;
if ( ::stat( ph.string().c_str(), &path_stat ) != 0 )
boost::throw_exception( filesystem_error(
"boost::filesystem::file_size",
ph, fs::detail::system_error_code() ) );
if ( S_ISDIR( path_stat.st_mode ) )
boost::throw_exception( filesystem_error(
"boost::filesystem::file_size",
ph, "invalid: is a directory",
is_directory_error ) );
return static_cast<boost::intmax_t>(path_stat.st_size);
# else
// by now, intmax_t is 64-bits on all Windows compilers
WIN32_FILE_ATTRIBUTE_DATA fad;
if ( !::GetFileAttributesExA( ph.string().c_str(),
::GetFileExInfoStandard, &fad ) )
boost::throw_exception( filesystem_error(
"boost::filesystem::file_size",
ph, fs::detail::system_error_code() ) );
if ( (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) !=0 )
boost::throw_exception( filesystem_error(
"boost::filesystem::file_size",
ph, "invalid: is a directory",
is_directory_error ) );
return (static_cast<boost::intmax_t>(fad.nFileSizeHigh)
<< (sizeof(fad.nFileSizeLow)*8))
+ fad.nFileSizeLow;
# endif
}
La portabilité est assuré en prenant les cas POSIX et windows. Mais,
pour mon utilisation , j'ai essayé de touver une autre façon de
déterminer la taille d'un fichier.
je suis arrivé à ce code :
// Determine length of file
cout << "Number of characters " << buffer.size() << endl;
cout << "char is " << sizeof(char) << " bytes " << endl;
cout << "Size of " << filename << " is " <<
buffer.size()*sizeof(char) << " bytes." << endl;
infile.close();
return 0;
}
Voilà, hormis l'utilisation processeur puisque je n'utilise pas de
buffer , cette façon me donne enfin la bonne taille des fichiers.
J'ai essayé d'imaginer comment utiliser un buffer, mais j'arrive pas à
faire la même chose, et le code devient beaucoup trop complexe pour la
fonctionnalité.
Je pense utiliser le buffer pour réaliser, le split des fichiers de sortie.
Je n'ai pas le temps de faire un analyse pareil sur merge, mais tu dois avoir déjà pas mal de choses à faire.
Effectivement, j'ai pas mal de choses à comprendre.
La proposition d'utiliser la class filebuf conjointement avec la container vector est beaucoup plus élégante.
Mais je ne suis pas arrivé jusqu'à ce point.
Je me suis attardé sur la détermination de la longueur d'un fichier.
L'indication d'utilisation de stat est une piste. En regardant boost/filesystem/operation.. il y a la fonction file_size
BOOST_FILESYSTEM_DECL boost::intmax_t file_size( const path & ph ) { # ifdef BOOST_POSIX struct stat path_stat; if ( ::stat( ph.string().c_str(), &path_stat ) != 0 ) boost::throw_exception( filesystem_error( "boost::filesystem::file_size", ph, fs::detail::system_error_code() ) ); if ( S_ISDIR( path_stat.st_mode ) ) boost::throw_exception( filesystem_error( "boost::filesystem::file_size", ph, "invalid: is a directory", is_directory_error ) ); return static_cast<boost::intmax_t>(path_stat.st_size); # else // by now, intmax_t is 64-bits on all Windows compilers WIN32_FILE_ATTRIBUTE_DATA fad; if ( !::GetFileAttributesExA( ph.string().c_str(), ::GetFileExInfoStandard, &fad ) ) boost::throw_exception( filesystem_error( "boost::filesystem::file_size", ph, fs::detail::system_error_code() ) ); if ( (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) !=0 ) boost::throw_exception( filesystem_error( "boost::filesystem::file_size", ph, "invalid: is a directory", is_directory_error ) ); return (static_cast<boost::intmax_t>(fad.nFileSizeHigh) << (sizeof(fad.nFileSizeLow)*8)) + fad.nFileSizeLow; # endif }
La portabilité est assuré en prenant les cas POSIX et windows. Mais, pour mon utilisation , j'ai essayé de touver une autre façon de déterminer la taille d'un fichier. je suis arrivé à ce code :
// Determine length of file cout << "Number of characters " << buffer.size() << endl; cout << "char is " << sizeof(char) << " bytes " << endl; cout << "Size of " << filename << " is " << buffer.size()*sizeof(char) << " bytes." << endl;
infile.close();
return 0; }
Voilà, hormis l'utilisation processeur puisque je n'utilise pas de buffer , cette façon me donne enfin la bonne taille des fichiers.
J'ai essayé d'imaginer comment utiliser un buffer, mais j'arrive pas à faire la même chose, et le code devient beaucoup trop complexe pour la fonctionnalité.
Je pense utiliser le buffer pour réaliser, le split des fichiers de sortie.
A bientôt, lorsque j'aurai assimilé le reste.
http://hackervalley.free.fr
Gabriel Dos Reis
"Michel Michaud" writes:
| Dans le message , | > drkm writes: | > | >> long segmentSize = size / Count + ( size % Count != 0 ? 1 : 0 | >> ) ; | > | > A vrai dire, j'aurais même écrit | > | > long segmentSize = size / Count; | > if (size % Count != 0) { | > segmentSize++; | > } | | Vous aimez faire dans le compliqué... Pourquoi pas ceci : | | long segmentSize = (size+Count-1) / Count;
Il manque un commentaire ;-)
-- Gaby
"Michel Michaud" <mm@gdzid.com> writes:
| Dans le message vpqoefpv2wf.fsf@ubaye.imag.fr,
| > drkm <usenet.fclcxx@fgeorges.org> writes:
| >
| >> long segmentSize = size / Count + ( size % Count != 0 ? 1 : 0
| >> ) ;
| >
| > A vrai dire, j'aurais même écrit
| >
| > long segmentSize = size / Count;
| > if (size % Count != 0) {
| > segmentSize++;
| > }
|
| Vous aimez faire dans le compliqué... Pourquoi pas ceci :
|
| long segmentSize = (size+Count-1) / Count;