Re: [问题] C++ 将档案读入 std::string

楼主: dirkc (3781615)   2015-05-23 02:46:26
直接回一篇好了
答案如同其他版友已经提供的,我只想补充严格说来 '\0' 也是 ASCII 字符
如果你的输入档案里面原先有 '\0' 字符,你的方法“有可能”会失败
举例来说,如果输入档案 test.in 内容以十六进制显示如下
68 65 6c 6c 6f 00 20 77 6f 72 6c 64 21 0a
以可显示的 ASCII 字符就会如下:
hello. world!.
第一个 . 是 '\0'
第二个 . 是 '\n'
显示不出来我们暂时用 . 来代表
如果以你的读档方式,在 linux/g++ 4.8.2 上面只会读到 hello,
getline() 碰到档案中的 '\0' 就停止了
上面提到的“有可能”是因为 text mode 开档会做一些 ASCII 特殊字符的转换,
至于会做哪方面的转换,则要看作业系统和/或函数库的实作而定,
或许以上的例子在 Windows/VC++ 上面跑会跳过 '\0' 继续读到档案结尾也不一定
(我没有在 Windows 上实验过)
我自己不会太建议用 getline() 来读整个档案,毕竟它是一个字符一个字符去做
判断,直觉上读取速度会很慢,尤其档案大的时候
版友提的 iterator 或 streambuf 的作法很简洁漂亮,不过档案大速度可能也会慢
(抱歉单纯就事论事)
通常判断完档案的大小之后,一次将档案读取进来,速度通常会比较快
举例来说,稍微小修一下你的程式:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(int argc, char **argv) {
string str;
ifstream fin(argv[1]);
if(!fin) return 1;
fin.seekg(0, ios::end);
str.resize(fin.tellg());
fin.seekg(0, ios::beg);
fin.read(&str[0], str.size());
fin.close();
cout << str;
}
以上我在 linux 实验可以,但据说有人用 text mode 使用 seekg(0, ios::end) 会失
败,所以另一种作法也提供给你参考,就是使用 POSIX 的 stat() 函数和 struct stat
来取得档案大小,再一次将档案读取进来
(在 Windows 下是 _stat() 函数和 struct _stat)
举例:
#include <sys/types.h>
#include <sys/stat.h>
#include <fstream>
#include <string>
#include <iostream>
using namespace std;
int main(int argc, char **argv) {
ifstream fin(argv[1]);
if(!fin) return 1;
struct _stat s;
string str;
if(_stat(argv[1], &s)) return 1;
str.resize(s.st_size);
fin.read(&str[0], str.size());
fin.close();
cout << str;
}
记得最前面的两个 #include
上例我在 linux 实验可以运作,于是直接把程式码 stat 前面加底线变成 Windows 版本
没意外的话应该可以用
以上提供给你参考
※ 引述《out99 ( )》之铭言:
: 开发平台(Platform): (Ex: VC++, GCC, Linux, ...)
: VC++
: 额外使用到的函数库(Library Used): (Ex: OpenGL, ...)
: 问题(Question):
: 我想要一次将整个档案读进 std::string
: 而不是用 while 一行一行读取再 append string
: 我直接使用 std::getline() 第三个参数 delim 丢入 '\0' 处理
: 测试过几个档案“看起来”没有问题
: 我想问的是会不会有特殊情形导致这个方式读出来的内容是错误的?
: 直接假设“档案的第一个 '\0' 字符就是整个档案的结尾”是正确的吗?
: 谢谢
: 喂入的资料(Input):
: 内容为 ASCII 字符,不包含其它特殊字符的文字档。
: 预期的正确结果(Expected Output):
: 错误结果(Wrong Output):
: 程式码(Code):(请善用置底文网页, 记得排版)
: #include <iostream>
: #include <string>
: #include <fstream>
: using namespace std;
: int main(int argc, char** argv)
: {
: string str;
: ifstream fin(argv[1], ios::in);
: if (fin.fail())
: return 1;
: getline(fin, str, '\0');
: fin.close();
: cout << str;
: return 0;
: }
: 补充说明(Supplement):
作者: out99 ( )   2015-05-23 09:34:00
_stat在Windows下正常运作,而且速度也比较快受教了,感谢!我刚刚用stat在Windows下测试一样能运作我是用VS2013
作者: Killercat (杀人猫™)   2015-05-23 11:54:00
我倒是没有碰过ASCII档案里面夹\0的例子就是(抓头如果夹\0 我想fstream的<<应该会死光才对

Links booklink

Contact Us: admin [ a t ] ucptt.com