web-dev-qa-db-ja.com

C ++でファイルコンテンツを文字列に読み取ります

可能性のある複製:
c ++でファイルをstd :: stringに変換する最良の方法は何ですか?

Perlなどのスクリプト言語では、ファイルを一度に変数に読み込むことができます。

    open(FILEHANDLE,$file);
    $content=<FILEHANDLE>;

C++でこれを行う最も効率的な方法は何ですか?

72
sonofdelphi

このような:

#include <fstream>
#include <string>

int main(int argc, char** argv)
{

  std::ifstream ifs("myfile.txt");
  std::string content( (std::istreambuf_iterator<char>(ifs) ),
                       (std::istreambuf_iterator<char>()    ) );

  return 0;
}

声明

  std::string content( (std::istreambuf_iterator<char>(ifs) ),
                       (std::istreambuf_iterator<char>()    ) );

に分割することができます

std::string content;
content.assign( (std::istreambuf_iterator<char>(ifs) ),
                (std::istreambuf_iterator<char>()    ) );

既存のstd :: string変数の値を単に上書きしたい場合に便利です。

156
Maik Beckmann

最も効率的ですが、C++ではありません。

   FILE* f = fopen(filename, "r");

   // Determine file size
   fseek(f, 0, SEEK_END);
   size_t size = ftell(f);

   char* where = new char[size];

   rewind(f);
   fread(where, sizeof(char), size, f);

   delete[] where;

#EDIT-2

std::filebufバリアントもテストしました。 C++のアプローチではなく、むしろラッパーであるにもかかわらず、最高のC++アプローチと呼ぶことができるようです。とにかく、ここに、普通のCとほぼ同じ速度で動作するコードの塊があります。

   std::ifstream file(filename, std::ios::binary);
   std::streambuf* raw_buffer = file.rdbuf();

   char* block = new char[size];
   raw_buffer->sgetn(block, size);
   delete[] block;

ここで簡単なベンチマークを行いましたが、結果は次のとおりです。テストは、適切な(std::ios:binaryおよびrb)モードで65536Kバイナリファイルを読み取ることで行われました。

[==========] Running 3 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 4 tests from IO
[ RUN      ] IO.C_Kotti
[       OK ] IO.C_Kotti (78 ms)
[ RUN      ] IO.CPP_Nikko
[       OK ] IO.CPP_Nikko (106 ms)
[ RUN      ] IO.CPP_Beckmann
[       OK ] IO.CPP_Beckmann (1891 ms)
[ RUN      ] IO.CPP_Neil
[       OK ] IO.CPP_Neil (234 ms)
[----------] 4 tests from IO (2309 ms total)

[----------] Global test environment tear-down
[==========] 4 tests from 1 test case ran. (2309 ms total)
[  PASSED  ] 4 tests.
39

最も効率的なのは、正しいサイズのバッファーを作成してから、ファイルをバッファーに読み込むことです。

#include <fstream>
#include <vector>

int main()
{
    std::ifstream       file("Plop");
    if (file)
    {
        /*
         * Get the size of the file
         */
        file.seekg(0,std::ios::end);
        std::streampos          length = file.tellg();
        file.seekg(0,std::ios::beg);

        /*
         * Use a vector as the buffer.
         * It is exception safe and will be tidied up correctly.
         * This constructor creates a buffer of the correct length.
         * Because char is a POD data type it is not initialized.
         *
         * Then read the whole file into the buffer.
         */
        std::vector<char>       buffer(length);
        file.read(&buffer[0],length);
    }
}
12
Martin York

テキストファイルに\0が存在しないようにする必要があります。

#include<iostream>
#include<fstream>

using namespace std;

int main(){
  fstream f(FILENAME, fstream::in );
  string s;
  getline( f, s, '\0');

  cout << s << endl;
  f.close();
}
6
Draco Ater

これは、ファイルのサイズ、種類(テキスト/バイナリ)など、多くのことに依存します。先ほど、streambufイテレータを使用したバージョンに対して次の関数のベンチマークを行いました。

unsigned int FileRead( std::istream & is, std::vector <char> & buff ) {
    is.read( &buff[0], buff.size() );
    return is.gcount();
}

void FileRead( std::ifstream & ifs, string & s ) {
    const unsigned int BUFSIZE = 64 * 1024; // reasoable sized buffer
    std::vector <char> buffer( BUFSIZE );

    while( unsigned int n = FileRead( ifs, buffer ) ) {
        s.append( &buffer[0], n );
    }
}
2
anon

おそらく最も効率的ではありませんが、1行でデータを読み取ります。

#include<iostream>
#include<vector>
#include<iterator>

main(int argc,char *argv[]){
  // read standard input into vector:
  std::vector<char>v(std::istream_iterator<char>(std::cin),
                     std::istream_iterator<char>());
  std::cout << "read " << v.size() << "chars\n";
}
1
catwalk

反復子ベースのメソッドを次に示します。

ifstream file("file", ios::binary);
string fileStr;

istreambuf_iterator<char> inputIt(file), emptyInputIt
back_insert_iterator<string> stringInsert(fileStr);

copy(inputIt, emptyInputIt, stringInsert);
1
academicRobot