将文件内容读取到动态分配的 char* 数组中 - 我可以读取 std::string 吗?
Reading contents of file into dynamically allocated char* array- can I read into std::string instead?
我发现自己在写代码看起来像这样
// Treat the following as pseudocode - just an example
iofile.seekg(0, std::ios::end); // iofile is a file opened for read/write
uint64_t f_len = iofile.tellg();
if(f_len >= some_min_length)
{
// Focus on the following code here
char *buf = new char[7];
char buf2[]{"MYFILET"}; // just some random string
// if we see this it's a good indication
// the rest of the file will be in the
// expected format (unlikely to see this
// sequence in a "random file", but don't
// worry too much about this)
iofile.read(buf, 7);
if(memcmp(buf, buf2, 7) == 0) // I am confident this works
{
// carry on processing file ...
// ...
// ...
}
}
else
cout << "invalid file format" << endl;
这段代码可能是我们在打开文件时可能想要做什么的草图,该文件具有某种指定的格式(我已经口述(。我们做了一些初步检查,以确保字符串"MYFILET"
位于文件的开头 - 因为我已经决定我正在做的工作的所有文件都将从这个字符序列开始。
我认为如果我们不必使用"c 样式"字符数组,而是在任何地方使用字符串,这段代码会更好。这将是有利的,因为我们可以做一些事情,比如if(buf == buf2)
如果buf
和buf2
std::string
在哪里。
一个可能的替代方案可能是,
// Focus on the following code here
std::string buf;
std::string buf2("MYFILET"); // very nice
buf.resize(7); // okay, but not great
iofile.read(buf.data(), 7); // pretty awful - error prone if wrong length argument given
// also we have to resize buf to 7 in the previous step
// lots of potential for mistakes here,
// and the length was used twice which is never good
if(buf == buf2) then do something
这有什么问题?
- 我们不得不使用长度变量
7
(在本例中为常量(两次。这介于"不理想"和"潜在容易出错"之间。 - 我们必须使用
.data()
访问buf
的内容,我假设这里实现它是为了返回某种原始指针。我个人不太介意这一点,但其他人可能更喜欢更内存安全的解决方案,也许暗示我们应该使用某种迭代器?我认为在Visual Studio中(对于我不是的Windows用户(,那么无论如何这都可能会返回一个迭代器,它会给出[?]警告/错误[?] - 不确定这一点。 - 我们必须为
buf
有一个额外的调整大小语句。如果可以以某种方式自动设置buf
的大小会更好。
std::string::data()
返回的const char*
是未定义的行为。 但是,您可以通过这种方式自由使用std::vector::data()
。
如果你想使用 std::string,并且不喜欢自己设置大小,你可以考虑是否可以使用 std::getline()
. 这是免费功能,不是std::istream::getline()
。 std::string
版本将读取指定的分隔符,因此如果您有文本格式,您可以告诉它读取直到' '
或其他一些永远不会出现的字符,它将自动调整给定字符串的大小以保存内容。
如果你的文件本质上是二进制的,而不是文本,我想大多数人会发现std::vector<char>
比std::string
更自然。
我们不得不使用长度变量 7(在本例中为常数(两次。 这介于"不理想"和"潜在容易出错"之间。
第二次可以使用buf.size()
iofile.read(buf.data(), buf.size());
我们必须使用 .data(( 访问 buf 的内容,我将 假设此处实现为返回某种原始指针。
并由约翰·兹温克指出,.data()
返回指向const
的指针。
我想你可以buf
定义为std::vector<char>
;对于vector
(如果我没记错的话(,.data()
返回一个指向char
(在这种情况下(的指针,而不是指向const char
的指针。
size()
和resize()
的工作方式相同。
我们必须为 buf 提供一个额外的调整大小语句。这将是 如果可以以某种方式自动设置 BUBF 的大小,那就更好了。
我认为read()
不允许这样做。
PS:对不起,我的英语不好。
我们可以在没有双重缓冲(rdbuf 和字符串(的情况下验证签名并从堆中分配......
// terminating null not included
constexpr char sig[] = { 'M', 'Y', 'F', 'I', 'L', 'E', 'T' };
auto ok = all_of(begin(sig), end(sig), [&fs](char c) { return fs.get() == (int)c; });
if (ok) {}
template<class Src>
std::string read_string( Src& src, std::size_t count){
std::string buf;
buf.resize(count);
src.read(&buf.front(), 7); // in C++17 make it buf.data()
return buf;
}
现在auto read = read_string( iofile, 7 );
在使用点是干净的。
buf2
是一个糟糕的计划。 我会做的:
if(read=="MYFILET")
直接,或使用const char myfile_magic[] = "MYFILET";
.
上面例子中的许多想法,但我并不完全满意有一个答案可以为 C++11 和 C++17 生成无定义行为的代码。我目前用 C++11 编写大部分代码 - 因为我预计将来不会在没有 C++11 编译器的机器上使用它。
如果没有,那么我会添加新的编译器或更换机器。
然而,在我看来,编写我知道在C++17 下可能不起作用的代码确实是一个坏主意......这只是我个人的看法。我预计不会再次使用此代码,但我不想将来给自己带来潜在的问题。
因此,我想出了以下代码。我希望其他用户能提供反馈以帮助改进这一点。(例如,尚无错误检查。
std::string
fstream_read_string(std::fstream& src, std::size_t n)
{
char *const buffer = new char[n + 1];
src.read(buffer, n);
buffer[n] = ' ';
std::string ret(buffer);
delete [] buffer;
return ret;
}
这似乎是一种基本的,可能是万无一失的方法......遗憾的是,似乎没有办法让 std::string 使用与调用 new
分配的相同内存。
请注意,我们必须在 C 样式字符串中添加一个额外的尾随 null 字符,该字符在 C++ 样式std::string
中被切掉。
- 我可以读取静态对象中的文件.txt吗?C++
- 如果需要转换,我可以在读取参数的同时将其移动到另一个参数吗?
- 为什么我可以从C++文件中读取 int 值,但不能浮点?
- 我可以从具有不同数字分隔符的istream中读取双值吗
- 我可以在Windows(Visual C++)中读取bin文件,但不能在linux(GCC)上读取bin文件
- 有没有办法我可以从 istringstream 中读取两个字符
- 我可以在没有任何锁的情况下从不同的线程读取内存缓冲区吗?
- 我可以配置"stdin"以从 c++ 字符串中读取吗?
- 我可以在中断中写入向量,然后以安全的方式仅在主线程内读取吗?
- 我可以在C 中的Windows中读取一个文件,而无需锁定包含文件的文件夹
- 我可以多快读取 /dev/ttyACM0 文件
- 我可以在没有静音的线程中读取线程中的bool变量
- 如何读取纹理数据,以便我可以编辑它
- 我可以在不知道文本文件的列数的情况下读取二维数组中的文件吗?
- 我可以通过z3c++接口将SMT2文件读取到求解器中吗
- 我可以做一个不形式的写入文件,然后从文件中进行整体类型的格式读取
- 我可以读取向量<string>::迭代器的数字位置吗?
- 我可以在一个线程中写入变量并在 c++ 中的另一个线程中读取它吗?
- 重载 C++ 运算符>>,以便我可以读取向量(向量<int>向量;
- Linux 串行端口读取 - 我可以更改输入缓冲区的大小吗?