如何在c++; 我的目标是在文件中搜索特定的行,修改它并保存文件在C++中。我正试图通过fstream这样做,如下所示 fstream someFile(fileName, filestream::ate | filestream::in | filestream::out); streampos endPos = someFile.tellg(); streampos.seekg(0, fstream::beg); string line; while(someFile && someFile.tellg() != endPos && getline(somefile, line)) { if(correctLine(line)) { modifyLine(line); //save Line.. How do i do this? } }
我的问题是如何用修改后的行替换从getline函数获得的行?如何在c++; 我的目标是在文件中搜索特定的行,修改它并保存文件在C++中。我正试图通过fstream这样做,如下所示 fstream someFile(fileName, filestream::ate | filestream::in | filestream::out); streampos endPos = someFile.tellg(); streampos.seekg(0, fstream::beg); string line; while(someFile && someFile.tellg() != endPos && getline(somefile, line)) { if(correctLine(line)) { modifyLine(line); //save Line.. How do i do this? } },c++,C++,我的问题是如何用修改后的行替换从getline函数获得的行? 另外,在getline之后,文件位置是在当前行的开头还是放在当前行的末尾?行是长度未知的东西。因此,你不能只是更换它。您需要有一个源文件流和一个目标文件流。复制流时,您可以替换任何需要的行。首先将put指针放在要开始替换的所需位置。 fileobj.seekp(fileobj.tellp(-lengthOfLine,ios::cur),ios::beg) 然后简单地写一行 Fileobj@harper是正确的,除非新行的大小与旧行的大
另外,在getline之后,文件位置是在当前行的开头还是放在当前行的末尾?行是长度未知的东西。因此,你不能只是更换它。您需要有一个源文件流和一个目标文件流。复制流时,您可以替换任何需要的行。首先将put指针放在要开始替换的所需位置。 fileobj.seekp(fileobj.tellp(-lengthOfLine,ios::cur),ios::beg) 然后简单地写一行
Fileobj@harper是正确的,除非新行的大小与旧行的大小相同,否则不能仅更改文件。您可以做的是读入,然后将
stringstream
写回,用新版本完全覆盖文件
下面是一个从替换一行的示例。在您的例子中,您只需要做一些比行==target
更复杂的事情,但基本上是一样的
请注意,这会将整个文件读入内存,因此如果文件较大,则会占用大量内存
#include <fstream>
#include <iostream>
#include <sstream>
int main(int argc, char** argv) {
/* Accept filename, target and replacement string from arguments for a more
useful example. */
if (argc != 4) {
std::cout << argv[0] << " [file] [target string] [replacement string]\n"
<< " Replaces [target string] with [replacement string] in [file]" << std::endl;
return 1;
}
/* Give these arguments more meaningful names. */
const char* filename = argv[1];
std::string target(argv[2]);
std::string replacement(argv[3]);
/* Read the whole file into a stringstream. */
std::stringstream buffer;
std::fstream file(filename, std::fstream::in);
for (std::string line; getline(file, line); ) {
/* Do the replacement while we read the file. */
if (line == target) {
buffer << replacement;
} else {
buffer << line;
}
buffer << std::endl;
}
file.close();
/* Write the whole stringstream back to the file */
file.open(filename, std::fstream::out);
file << buffer.str();
file.close();
}
#包括
#包括
#包括
int main(int argc,字符**argv){
/*接受参数中的文件名、目标和替换字符串以获得更多
有用的例子*/
如果(argc!=4){
std::cout如果两行的长度完全相同,您可以返回开始的位置并再次写出该行。我认为代码如下所示:
// we need to go back 1 extra to take the line break into account
someFile.seekp(-line.size() - 1, std::ios_base::cur);
someFile.write(line.data(), line.size());
如果使用内存映射文件,则可能会减少实际磁盘访问(写访问)。如果匹配行位于“延迟”块中,则可以避免(重新)写入前面的任何块
下面的代码
- 为了不依赖于平台,使用boost
- 允许比匹配的目标线短或长的替换
- 就地调整文件大小
- 演示如何通过正则表达式查找行
- 在这里发布之前,它经过了很好的测试(在linux上)
有关基本原理,请参见内联注释。代码:
#include <boost/iostreams/device/mapped_file.hpp>
#include <boost/regex.hpp>
#include <boost/filesystem.hpp>
using namespace boost;
const auto MAX_INCREASE = 1024; // allow 1 kilobyte room to grow
void process(
filesystem::path const& spec,
std::string const& pattern,
std::string const& replace)
{
// get current size of file on disk
auto const cur_size = file_size(spec);
// map, with MAX_INCREASE room to spare
iostreams::mapped_file mmap(
spec.native(),
iostreams::mapped_file::readwrite,
cur_size+MAX_INCREASE);
// find the line matching 'pattern'
char *bof = mmap.data();
char *eof = bof + cur_size; // don't read beyond cur_size!
regex re(pattern);
match_results<char*> match;
if (regex_search(bof, eof, match, re))
{
// replace the matched contents!
auto b = match[0].first,
e = match[0].second;
std::cout << "Matching line: '" << std::string(b, e) << "'\n";
// figure out whether we need to grow/shrink
auto delta = (b + replace.size()) - e;
std::cout << "Delta: " << delta << "\n";
if (delta < 0)
{
// shrinking
std::copy(replace.begin(), replace.end(), b); // replacement
std::copy(e, eof, e + delta); // shift back
resize_file(filesystem::path(spec), cur_size + delta);
}
else if (delta < MAX_INCREASE)
{
// growing
resize_file(filesystem::path(spec), cur_size + delta);
std::copy_backward(b, eof, eof + delta); // shift onwards
std::copy(replace.begin(), replace.end(), b); // insert replacement
}
else
{
// error handling (MAX_INCREASE exceeded)
}
}
// TODO error handling (no match)?
}
int main()
{
process("input.txt", "^int .*?$", "void foo()\n// mmap was here");
//process("input.txt", "^int .*?$", "");
}
#包括
#包括
#包括
使用名称空间boost;
const auto MAX_INCREASE=1024;//允许1 KB的空间增长
空洞过程(
文件系统::路径常量和规范,
std::字符串常量和模式,
标准::字符串常量和替换)
{
//获取磁盘上文件的当前大小
自动常量当前大小=文件大小(规格);
//地图,最大可用空间增加
iostreams::映射的_文件mmap(
spec.native(),
iostreams::映射的_文件::读写,
电流大小+最大增加);
//查找与“模式”匹配的行
char*bof=mmap.data();
char*eof=bof+cur\u size;//不要读取超过cur\u size的内容!
正则表达式re(模式);
匹配结果匹配;
if(正则表达式搜索(bof、eof、匹配、re))
{
//替换匹配的内容!
自动b=匹配[0]。首先,
e=匹配[0]。秒;
Std::CUT替换文件中的行已经被覆盖了很多次。你做了哪些研究?强烈的建议:考虑使用两个流:一个用于读取,另一个用于写入。我看了C++文件,FFLAST使用内存映射文件可能更高效,发布基于THATI不想复制源文件的解决方案。目标文件。相反,我想对文件进行修改并将修改保存回去。getline返回一个字符串,我可以调用length()在字符串上确定行length@Jimm-您将有效地执行您不想执行的操作,没有其他方法,即使您重写了文件,它将创建一个新版本,您也无法将此类数据插入到文件中。@Jimm您只能在修改行的长度与未修改行的长度相同的情况下执行此操作。接受这样一个事实,即您几乎肯定需要将全部内容写回一个文件。@CaptainObvlious在我的情况下,前后行大小是相同的。在这种情况下,我如何替换?如果这样做,您很可能会损坏您的文件。请您详细说明上述建议如何损坏文件?因为您正在寻求当前位置,而不是行的开头。我不相信任何操作符,甚至更聪明的做法似乎是将不需要修改的部分保留在磁盘上。我相信内存映射文件可以实现这一点(请参阅我的答案,它还允许任意长度的替换)