我试图用缓冲区将整个文件读入缓冲区 std::ifstream该失败没有明显的原因,所以我构建了一个演示问题的最小代码示例:
std::vector<char> vec;
vec.resize(1000);
std::ifstream file("G:/Pictures/Webcam/Snapshot_20110209.jpg");
file.exceptions(std::ifstream::badbit | std::ifstream::failbit | std::ifstream::eofbit);
std::cout << file.good() << std::endl;
try {
file.read(vec.data(), 100);
} catch (std::ios_base::failure f) {
std::cout << f.what() << " Characters extracted: " << file.gcount() << std::endl;
} catch (...) {
std::cout << "Some other error" << std::endl;
}
std::cout << "Done" << std::endl;
file.close();
Run Code Online (Sandbox Code Playgroud)
我正在尝试读取的文件大小为48kb,因此读取100个字节应该不是问题.1000字节的缓冲区很大,所以也应该没问题.现在,发生的是流只读取61个字节,然后设置failbit.生成的输出如下:
1
ios_base::failbit set: iostream stream error Characters extracted: 61
Done
Run Code Online (Sandbox Code Playgroud)
因此,出于某种原因,故障位置设置在61个字节之后.如果我读取少于61个字节,它的工作原理.如果我尝试阅读更多,它也会在61处失败.我也尝试过类似大小,同样问题的其他文件.一些完全不同的不同大小的文件显示相同的行为,但在166字节之后.
现在,如果我使用Qt的QFile类来读取数据,一切正常,我可以读取完整的文件.代码如下所示:
QFile file(path);
std::vector<char> buffer;
buffer.resize(file.size());
if (!file.open(QIODevice::ReadOnly)) return; …Run Code Online (Sandbox Code Playgroud) 我正在编写一个C++ 14程序来从文件中加载文本字符串,对它们进行一些计算,然后写回另一个文件.我正在使用Linux,文件相对较大(O(10 ^ 6行)).我的典型方法是使用旧的C getline和sscanf实用程序来读取和解析输入,以及fprintf(FILE*, …)编写输出文件.这是有效的,但我想知道是否有更好的方法来实现高性能和通常推荐的方法与我正在使用的现代C++标准.我听说这iostream很慢; 如果这是真的,我想知道是否有更推荐的方法.
更新:为了澄清一下用例:对于输入文件的每一行,我将进行一些文本操作(数据清理等).每条线都是独立的.因此,加载整个输入文件(或者至少是它的大块),逐行处理,然后编写它,似乎最有意义.对此的理想抽象是获取读入缓冲区的迭代器,每行都是一个条目.有没有推荐的方法用std :: ifstream做到这一点?
通常我会使用C样式文件IO,但我正在尝试一种现代C++方法,包括使用C++ 17特定的功能std::byte和std::filesystem.
将整个文件读入内存,传统方法:
#include <stdio.h>
#include <stdlib.h>
char *readFileData(char *path)
{
FILE *f;
struct stat fs;
char *buf;
stat(path, &fs);
buf = (char *)malloc(fs.st_size);
f = fopen(path, "rb");
fread(buf, fs.st_size, 1, f);
fclose(f);
return buf;
}
Run Code Online (Sandbox Code Playgroud)
将整个文件读入内存,现代方法:
#include <filesystem>
#include <fstream>
#include <string>
using namespace std;
using namespace std::filesystem;
auto readFileData(string path)
{
auto fileSize = file_size(path);
auto buf = make_unique<byte[]>(fileSize);
basic_ifstream<byte> ifs(path, ios::binary);
ifs.read(buf.get(), fileSize);
return buf;
}
Run Code Online (Sandbox Code Playgroud)
这看起来对吗?这可以改善吗?
这两种读取输入文件的方法有什么区别?
1)使用 'ifstream.get()'
和
2)使用vector<char>with ifstreambuf_iterator<char> (我不太了解!)
(除了使用漂亮的矢量方法的明显答案)
输入文件是XML,如下所示,立即解析为rapidxml文档.(在其他地方初始化,参见示例main函数.)
首先,让我向您展示两种编写'load_config'函数的方法,一种使用ifstream.get(),一种使用vector<char>
方法1 ifstream.get()提供了工作代码和一个安全的rapidXML文档对象:
rapidxml::xml_document<> *load_config(rapidxml::xml_document<> *doc){
ifstream myfile("inputfile");
//read in config file
char ch;
char buffer[65536];
size_t chars_read = 0;
while(myfile.get(ch) && (chars_read < 65535)){
buffer[chars_read++] = ch;
}
buffer[chars_read++] = '\0';
cout<<"clearing old doc"<<endl;
doc->clear();
doc->parse<0>(buffer);
//debug returns as expected here
cout << "load_config: Name of my first node is: " << doc->first_node()->name() << "\n";
return doc;
}
Run Code Online (Sandbox Code Playgroud)
方法2导致另一个库的cloberred rapidXML文档 - 特别是对curl_global_init(CURL_GLOBAL_SSL)的调用[参见下面的主要代码] - 但我还没有把它归咎于curl_global_init. …
terminate called after throwing an instance of 'nlohmann::detail::parse_error'
what(): [json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing object key - unexpected end of input; expected string literal
Run Code Online (Sandbox Code Playgroud)
尝试使用data.jsonC++ 从本地文件解析 JSON。
代码如下:
#include <iostream>
#include <stdio.h>
#include <string>
#include <fstream>
#include "json.hpp"
using namespace std;
using json = nlohmann::json;
int main() {
string text;
int x;
string jsonguy[5];
ifstream i("data.json");
i >> text;
json data = json::parse(text);
i.close();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我有本地进口的 Nlohmann json.hpp。它继续报告这些错误,我该如何修复它?
我试图将整个文本文件存储为字符串,如何动态存储文本文件可能包含的任何数量的字符?
我在PHP和带有Boost的C ++中都具有以下实现。它只是将文件读取为字符串,将其用空格分隔(我希望能够选择此字符),然后在具有20万个以空格分隔的随机数(称为“空格”)的文件上运行:
在PHP中:
<?php
$a = explode(" ", file_get_contents("spaces"));
echo "Count: ".count($a)."\n";
foreach ($a as $b) {
echo $b."\n";
}
Run Code Online (Sandbox Code Playgroud)
在C ++中:
#include <boost/algorithm/string.hpp>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <sstream>
#include <stdio.h>
using namespace boost;
using namespace std;
int main(int argc, char* argv[])
{
// ifstream ifs("spaces");
// string s ((istreambuf_iterator<char>(ifs)), (istreambuf_iterator<char>()));
char * buffer = 0;
long length;
string filename = "spaces";
FILE * f = fopen (filename.c_str(), "rb");
if (f)
{
fseek (f, 0, …Run Code Online (Sandbox Code Playgroud) 我正在尝试模仿PHP的C++文件_get_contents()函数.
但是,当我将char数组转换为字符串时,它将停止在nullbyte:
fread(charbuf, 1, file_size, fp);
string str(charbuf);
Run Code Online (Sandbox Code Playgroud)
如何将字符串初始化为静态大小数组,并将文件内容直接读取到该容器?另外,如何检查错误,例如,如果没有足够的内存来初始化该字符串.这也可以让我摆脱我目前正在使用的临时内存分配,我想摆脱它.
安全怎么样?是否有可能许多进程同时读取同一个文件和/或其中一个在我阅读时同时写入其中?我该如何避免这种情况发生?
我希望你能回答"字符串不是二进制容器"的其他方式.
我要求重新打开这个问题: "显然,这个问题与以往一样重要:两年后,两个最有效的解决方案仍然将整个文件内容复制到内存中,优化器无法忽略此副本.是一个非常不令人满意的事态. - Konrad Rudolph 2010年10月25日6:25" 在C++中将整个文件读入std :: string的最佳方法是什么?或者您是否希望我创建一个新问题,要求在没有额外字符串副本的情况下读取文件?
我正在Visual C ++项目中编写一个函数,该函数以2000字节为增量通过WinAPI读取文件的内容,并将其作为std :: string返回。
当文件远大于缓冲区(例如100 KB)时,会出现问题,在有效数据中间,我在文件中的多个位置添加了垃圾。这是一个长0xcccccccc...序列,由3-4个其他字节终止,通常出现在一个单词的中间。否则,该功能不会失败,并且不会丢失任何有效数据。
我没有检查确切的位置,但似乎这发生在缓冲区大小增加(或缓冲区大小增加的乘数)上。如果我将缓冲区的大小增加到大于测试文件的大小,那么问题就消失了。是什么原因导致这种情况发生?我究竟做错了什么?
std::string read_file(std::string filename) {
HANDLE hFile = CreateFile(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
std::string errortext("Error opening " + filename + ", bad handle value: " + to_string((int)hFile));
MessageBox(hwnd, errortext.c_str(), "Error", 0);
return "";
}
char buffer[2000] = "";
std::string entire_file = "";
DWORD dwBytesRead = 0;
while (ReadFile(hFile, buffer, sizeof(buffer), &dwBytesRead, NULL))
{
if (!dwBytesRead)
break;
entire_file += buffer;
}
CloseHandle(hFile);
return entire_file;
}
Run Code Online (Sandbox Code Playgroud)