0%

How to content from a file in C/C++

這題目雖然不怎麼困難,不過解法還蠻多的,雖然原理相同,不過根據編譯氣得能力,得到的結果也不同。
題目要求: 把讀到的內容當作一個string傳回來。
不考慮OS Level API(open/CreateFile)的方式,直接用C/C++的API來做。

fopen版

大家都很熟了,用fopen/fseek/fread/fclose來達成。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <cstdio>
using namespace std;
string get_file_content(const char *filename)
{
FILE *fp = fopen(filename, "rb");
if (fp)
{
string content;
fseek(fp, 0, SEEK_END);
content.resize(ftell(fp));
rewind(fp);
fread(&content[0], 1, content.size(), fp);
fclose(fp);
return content;
}
else return string();
}

fstream版

跟上面差不多,不過把C語言系列的函數全換掉了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <fstream>
using namespace std;
string get_file_content(const char *filename)
{
ifstream in(filename, ios::in | ios::binary);
if (in)
{
string content;
in.seekg(0, ios::end);
content.resize(in.tellg());
in.seekg(0, ios::beg);
in.read(&content[0], content.size());
in.close();
return content;
}
else return string();
}

ostringstream & rdbuf版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <fstream>
#include <sstream>
#include <string>
using namespace std;
string get_file_content(const char *filename)
{
ifstream in(filename, ios::in | ios::binary);
if (in)
{
ostringstream content;
content << in.rdbuf();
in.close();
return content.str();
}
else return string();
}

istreambuf_iterator版

昨天才看到這種方法,後知後覺。

1
2
3
4
5
6
7
8
9
10
#include <fstream>
using namespace std;
string get_file_content(const char *filename)
{
ifstream in(filename, ios::in | ios::binary);
if (in)
return string(istreambuf_iterator<char>(in), istreambuf_iterator<char>());
else
return string();
}

其他變形

結合 fstream 跟 istreambuf的作法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <string>
using namespace std;
string get_file_content(const char *filename)
{
ifstream in(filename, ios::in | ios::binary);
if (in)
{
string content;
in.seekg(0, ios::end);
content.resize(in.tellg());
in.seekg(0, ios::beg);
content.assign(istreambuf_iterator<char>(in), istreambuf_iterator<char>());
in.close();
return content;
}
else return string();
}

或是把上面assign那行換成

1
copy(istreambuf_iterator<char>(in), istreambuf_iterator<char>(), back_inserter(content));

也可以達成一樣的結果。

結論

雖然方法千奇百怪,不過越簡單的方式越快。
在GCC/Clang/VC++裡面,fopen都是最快的解決方案。