web-dev-qa-db-ja.com

C ++の特定のパスにファイルを書き込む

ファイルを正常に書き込む次のコードがあります。

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

残りのコードでは、バッファとサイズは問題ありません。ファイルを特定のパスに配置するにはどうすればよいですか?

9
user840718

ストリームのコンストラクターで絶対パスを指定します。これは、絶対パスまたは相対パスにすることができます。 (プログラムがどこから実行されるかを基準とします。

ストリームデストラクタはファイルを閉じます。明示的な閉じは、バグを引き起こす可能性が高くなります(ファイルが閉じた後に書き込みます)。

#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

C++ 11のファイルコンストラクターではstd :: stringを使用でき、ほとんどの場合、const char *よりも優先されることに注意してください。

12
111111

別の回答を投稿する根拠

他のどの回答も問題の領域をカバーしていないので、私は投稿しています。

あなたの質問への答えは、あなたがどのように道を辿るかによって異なります。アプリケーション内で完全にパスを構築している場合は、@ James Kanzeからの回答を参照してください。ただし、プログラムが実行されている環境(たとえば、環境変数、コマンドライン、構成ファイルなど)からパスまたはパスのコンポーネントを読み取っている場合、解決策は異なります。理由を理解するために、パスとは何かを定義する必要があります。

パスの概要

(私が知っている)オペレーティングシステムでは、パスはオペレーティングシステムとファイルシステム(略してシステム)で指定されたミニ言語に準拠した文字列です。特定のリソースにアクセスするために、特定のシステムのIO関数にパスを指定できます。たとえば、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

パス操作による問題の解決

次のシナリオを想像してみてください。プログラムがコマンドライン引数--output-path=<path>をサポートしているため、ユーザーはプログラムが出力ファイルを作成するパスを指定できます。指定されたディレクトリにファイルを作成するための解決策は次のとおりです。

  1. 操作しているシステムのミニ言語に基づいて、ユーザーが指定したパスを解析します。
  2. 手順1で解析したファイル名と情報を使用して、ファイルを書き込むための正しい場所を指定する新しいパスをミニ言語で作成します。
  3. 手順2で生成されたパスを使用してファイルを開きます。

これを行う例:

Linuxでは、ユーザーが--output-path=/dir1/dir2を指定したとしましょう

このミニ言語を解析します:

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

次に、指定したディレクトリにファイルを出力する場合、新しいパスを作成します。たとえば、bob.txtというファイルを出力する場合は、次のパスを作成できます。

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

次に、この新しいパスを使用してファイルを作成できます。

一般に、このソリューションを完全に実装することは不可能です。存在するすべてのパスミニ言語を正常にデコードし、各システムに関する情報を正しく表すことができるコードを記述して、新しいパスを正しく構築できるようにしたとしても、将来的には、プログラムが新しいシステムで構築または実行される可能性がありますプログラムが処理できない新しいパスのミニ言語。したがって、パスを管理するための慎重な戦略を使用する必要があります。

パス処理戦略

1.パス操作を完全に回避する

プログラムへの入力であるパスを操作しようとしないでください。これらの文字列は、正しく処理できるAPI関数に直接渡す必要があります。これは、C++ファイルを直接回避するOS固有のAPIを使用する必要があることを意味しますIO抽象化(またはこれらの抽象化が各OSでどのように実装されるかを確実に確認する必要があります)。インターフェイスを設計してください。パスの操作を余儀なくされる可能性がある状況を回避するために、慎重にプログラムに追加してください。同様にパスを操作する必要性を回避するために、プログラムのアルゴリズムを実装してみてください。プログラムが各OSで使用するAPI関数をユーザーに文書化してください-これこれは、OS api関数自体が時間の経過とともに非推奨になるため、将来、プログラムはパスの操作を回避するように注意しても、すべての可能なパスと互換性がない可能性があるためです。

2.プログラムがパスを操作するために使用する関数を文書化する

パスがどのように操作されるかをユーザーに正確に文書化します。次に、文書化されたプログラムの動作で正しく機能するパスを指定するのはユーザーの責任であることを明確にしてください。

3.パスの制限されたセットのみをサポートします

この一連の制限を満たすパスのサブセットを正しく操作できると確信できるまで、プログラムが受け入れるパスのミニ言語を制限します。これをユーザーに文書化します。パスが適合しない入力である場合はエラー。

4.問題を無視する

あまり心配することなく、基本的なパス操作を行ってください。入力された一部のパスに対して、プログラムが未定義の動作を示すことを受け入れます。プログラムへのパスを入力するときにプログラムが機能する場合と機能しない場合があること、およびプログラムが入力パスを正しく処理したことを確認するのはユーザーの責任です。ただし、何も文書化できませんでした。ユーザーは通常、プログラムが一部のパスを正しく処理しない(多くの場合はそうではない)ことを期待しているため、ドキュメントがなくても十分に対応できます。

終わりに

プログラムのライフサイクルの早い段階でパスを操作するための効果的な戦略を決定することが重要です。後でパスの処理方法を変更する必要がある場合、既存のユーザーのプログラムを破壊する可能性のある動作の変更を回避するのは難しい場合があります。

5
user1976

あなたが何を求めているのかはあまり明確ではありません。私が正しく理解していれば、ファイル名が与えられ、特定のディレクトリにファイルを作成したいとします。その場合は、ofstreamのコンストラクターへの完全なパスを指定するだけで済みます。文字列の連結を使用してこのパスを構築できますが、boost::filesystem::pathを強くお勧めします。これは、これを移植可能に実行するためのすべての機能を備えています。さもなければ、(多くの努力なしに)移植性がなくなり、ファイル名に対する単純な操作でさえかなりの考慮が必要になります。

0
James Kanze

私はしばらくこれにこだわっていて、それからそれを理解しました。パスは、実行可能ファイルの場所に基づいており、多少異なります。この例では、実行可能ディレクトリでlsを実行し、以下を参照するとします。

_myprogram.out  Saves  
_

Savesはフォルダーで、myprogram.outは実行中のプログラムです。

コードで、charをc_str()に次のような方法で変換する場合:

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

ユーザーがsavefileに入力すると、

_"Saves/savefile.txt"   
_

これは、Savesフォルダーのsavefile.txtに到達するために機能します。プレスラッシュはなく、フォルダ名から始めることに注意してください。

ただし、次のような文字列リテラルを使用している場合

_ifstream thefile;
thefile.open("./Saves/savefile.txt");
_

同じフォルダに移動するには、次のようになります。

_"./Saves/savefile.txt"  
_

フォルダー名の前の_./_で始まることに注意してください。

0
StackAttack

これを試して:

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

これは、ファイルを開くときに行う必要があります。_std::ofstream_ constructor または open() メンバーを参照してください。

0