這題目雖然不怎麼困難,不過解法還蠻多的,雖然原理相同,不過根據編譯氣得能力,得到的結果也不同。
題目要求: 把讀到的內容當作一個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都是最快的解決方案。