web-dev-qa-db-fra.com

Écrire un fichier dans un chemin spécifique en C++

J'ai ce code qui écrit avec succès un fichier:

    ofstream outfile (path);
    outfile.write(buffer,size);
    outfile.flush();
    outfile.close();

le tampon et la taille sont corrects dans le reste du code. Comment est-il possible de placer le fichier dans un chemin spécifique?

7
user840718

Spécifiez le chemin complet dans le constructeur du flux, il peut s'agir d'un chemin absolu ou relatif. (par rapport à l'endroit où le programme est exécuté.

Le destructeur de flux ferme le fichier pour vous, les fermetures explicites sont PLUS susceptibles d'introduire des bogues (l'écriture après la fermeture du fichier).

#include <fstream>
#include <string>

int main()
{
    const char *path="/home/user/file.txt";
    std::ofstream file(path); //open in constructor
    std::string data("data to write to file");
    file << data;
}//file destructor

Notez que vous pouvez utiliser std :: string dans le constructeur de fichier en C++ 11 et est préférable à un const char * dans la plupart des cas.

10
111111

Justification de poster une autre réponse

Je poste car aucune des autres réponses ne couvre l’espace problématique.

La réponse à votre question dépend de la façon dont vous obtenez le chemin. Si vous construisez le chemin entièrement dans votre application, consultez la réponse de @James Kanze. Toutefois, si vous lisez le chemin ou les composants du chemin à partir de l'environnement dans lequel votre programme est exécuté (par exemple, variable d'environnement, ligne de commande, fichiers de configuration, etc.), la solution est différente. Afin de comprendre pourquoi, nous devons définir ce qu'est un chemin.

Aperçu rapide des chemins

Sur les systèmes d'exploitation (à ma connaissance), un chemin est une chaîne conforme à un mini-langage spécifié par le système d'exploitation et le système de fichiers (système en abrégé). Des chemins peuvent être fournis à IO fonctions sur un système donné afin d'accéder à certaines ressources. Par exemple, voici certains chemins que vous pourriez rencontrer sous Windows:

\file.txt
\\bob\admin$\file.txt
C:..\file.txt
\\?\C:\file.txt
.././file.txt
\\.\PhysicalDisk1\bob.txt
\\;WebDavRedirector\bob.com\xyz
C:\PROGRA~1\bob.txt
.\A:B

Résoudre le problème via la manipulation du chemin

Imaginez le scénario suivant: votre programme prend en charge un argument de ligne de commande, --output-path=<path>, qui permet aux utilisateurs de fournir un chemin dans lequel votre programme doit créer des fichiers de sortie. Une solution pour créer des fichiers dans le répertoire spécifié serait:

  1. Analyser le chemin spécifié par l'utilisateur en fonction de la mini-langue du système dans lequel vous opérez. 
  2. Construisez un nouveau chemin dans le mini-langage qui spécifie l'emplacement correct pour écrire le fichier à l'aide du nom de fichier et des informations que vous avez analysées à l'étape 1.
  3. Ouvrez le fichier en utilisant le chemin généré à l'étape 2.

Un exemple de faire ceci:

Sous Linux, disons que l'utilisateur a spécifié --output-path=/dir1/dir2

Analyser cette mini-langue:

/dir1/dir2
--> "/" root
--> "dir1" directory under root
--> "/" path seperator
--> "dir2" directory under dir1

Ensuite, lorsque nous voulons sortir un fichier dans le répertoire spécifié, nous construisons un nouveau chemin. Par exemple, si nous voulons sortir un fichier appelé bob.txt, nous pouvons construire le chemin suivant:

/dir1/dir2/bob.txt
--> "/" root
--> "dir1" directory under root
--> "/" path separator
--> "dir2" directory under dir1
--> "/" path seperator
--> "bob.txt" file in directory dir2

Nous pouvons ensuite utiliser ce nouveau chemin pour créer le fichier.

En général, il est impossible de mettre en œuvre cette solution complètement. Même si vous pouviez écrire du code pouvant décoder avec succès tous les mini-langages de chemins existants et représenter correctement les informations relatives à chaque système, de sorte qu'un nouveau chemin puisse être construit correctement. À l'avenir, votre programme pourra être construit ou exécuté sur de nouveaux systèmes dotés de nouveau chemin mini-langues que votre programme ne peut pas gérer. Par conséquent, nous devons utiliser une stratégie prudente pour gérer les chemins.

Stratégies de gestion de chemin

1. Évitez complètement la manipulation de chemin

N'essayez pas de manipuler les chemins qui sont entrés dans votre programme. Vous devriez passer ces chaînes directement aux fonctions api qui peuvent les gérer correctement. Cela signifie que vous devez utiliser des api spécifiques à un système en évitant directement les abstractions du fichier C++ IO (ou vous devez être absolument sûr de la manière dont ces abstractions sont implémentées sur chaque système d'exploitation). Assurez-vous de concevoir l'interface avec votre programme avec soin afin d'éviter une situation dans laquelle vous pourriez être forcé de manipuler des chemins. Essayez d'implémenter les algorithmes pour votre programme afin d'éviter de manière similaire la nécessité de manipuler des chemins. Documentez à l'utilisateur les fonctions api que votre programme utilise sur chaque système d'exploitation. En effet, les fonctions api de système d'exploitation elles-mêmes deviennent obsolètes au fil du temps. Par conséquent, il est possible que votre programme ne soit plus compatible avec tous les chemins possibles, même en évitant de les manipuler.

2. Documentez les fonctions utilisées par votre programme pour manipuler les chemins

Documentez à l'utilisateur comment les chemins seront manipulés. Puis indiquez clairement que c’est la responsabilité de l’utilisateur de spécifier les chemins qui fonctionneront correctement avec le comportement du programme documenté.

3. Supporte seulement un ensemble restreint de chemins

Limitez le nombre de mini-langues de chemin acceptées par votre programme jusqu'à ce que vous soyez certain de pouvoir manipuler correctement le sous-ensemble de chemins répondant à cet ensemble de restrictions. Documentez ceci à l'utilisateur. Erreur si les chemins d'entrée ne sont pas conformes.

4. Ignorer les problèmes

Faites quelques manipulations de base sans trop vous inquiéter. Acceptez le comportement indéfini de votre programme pour certains chemins d'entrée. Vous pouvez indiquer à l'utilisateur que le programme peut fonctionner ou ne pas fonctionner lorsqu'il entre des chemins, et qu'il incombe aux utilisateurs de veiller à ce que le programme gère correctement les chemins d'accès. Cependant, vous pouvez également ne rien documenter. Les utilisateurs s'attendent généralement à ce que votre programme ne gère pas certains chemins correctement (beaucoup ne le font pas) et, par conséquent, ils se débrouilleront bien même sans documentation.

Pensées de clôture

Il est important de choisir une stratégie efficace pour travailler avec des chemins dès le début du cycle de vie de votre programme. Si vous devez modifier la manière dont les chemins sont gérés plus tard, il peut être difficile d'éviter un changement de comportement susceptible de compromettre le programme des utilisateurs existants.

5
user1976

Ce que vous demandez n'est pas trop clair. si je comprends bien, vous donnez un nom de fichier à et vous souhaitez créer le fichier dans un répertoire spécifique . Si c'est le cas, il suffit de spécifier le chemin d'accès Complet au constructeur de ofstream. Vous pouvez utiliser la concaténation de chaînes Pour créer ce chemin, mais je vous recommande fortement boost::filesystem::path. Il a toutes les fonctions pour le faire De manière portable, et beaucoup plus; sinon, vous ne serez pas portable (sans beaucoup d’efforts), et même des opérations simples sur le nom de fichier nécessiteront une réflexion approfondie. 

0
James Kanze

Je suis resté coincé là-dessus pendant un moment et je l'ai compris depuis. Le chemin est basé sur votre exécutable et varie un peu. Pour cet exemple, supposons que vous faites une ls dans votre répertoire exécutable et que:

myprogram.out  Saves  

Où Saves est un dossier et myprogram.out est le programme que vous exécutez.

Dans votre code, si vous convertissez des caractères en c_str() de la manière suivante:

string file;
getline(cin, file, '\n');
ifstream thefile;
thefile.open( ("Saves/" + file + ".txt").c_str() );

et l'utilisateur tape dans savefile, ce serait 

"Saves/savefile.txt"   

qui fonctionnera pour arriver à arriver à savefile.txt dans votre dossier de sauvegardes. Notez qu'il n'y a pas de pré-slash et que vous commencez simplement par le nom du dossier. 

Cependant, si vous utilisez un littéral de chaîne comme 

ifstream thefile;
thefile.open("./Saves/savefile.txt");

ce serait comme ça pour accéder au même dossier: 

"./Saves/savefile.txt"  

Notez que vous commencez avec un ./ devant le nom de dossier. 

0
StackAttack

Essaye ça:

ofstream outfile;
string createFile = "";    
string path="/FULL_PATH";

createFile = path.as<string>() + "/" + "SAMPLE_FILENAME" + ".txt";          
outfile.open(createFile.c_str());       
outfile.close();

//It works like a charm.
0
Gelo

Cela doit être fait lorsque vous ouvrez le fichier, voir std::ofstreamconstructeur ou open() membre.

0
Nikolai Fetissov