需要将文本的特定行写入新文本

Posted

技术标签:

【中文标题】需要将文本的特定行写入新文本【英文标题】:Need to write specific lines of a text into a new text 【发布时间】:2011-08-05 07:28:03 【问题描述】:

我有大小在 1mb - 150 mb 之间的数字文本数据行,我需要编写与高度相关的数字行,例如:heights=4,新文本必须包含行:1、5、9、13、 17,21.... 因此。

我一直在尝试找到一种方法来执行此操作,尝试使用列表而不是向量,但最终出现编译错误。

我已按照建议清理了代码。它现在写入所有行 sample2 文本,都在此处完成。谢谢大家

只要能满足我的需要,我愿意改变方法,感谢您的时间和帮助。

以下是我目前所拥有的:

#include <iostream>
#include <fstream>
#include <string>
#include <list>
#include <vector>

using namespace std;

int h,n,m;
int c=1;

int main () 

cout<< "Enter Number Of Heights: ";
cin>>h;

ifstream myfile_in ("C:\\sample.txt");
ofstream myfile_out ("C:\\sample2.txt");
string line;
std::string str;
vector <string> v;
if (myfile_in.is_open()) 
myfile_in >> noskipws;
int i=0;
int j=0;
while (std::getline(myfile_in, line)) 
v.push_back( line );
++n;
if (n-1==i) 
myfile_out<<v[i]<<endl;
i=i+h;
++j;

    
cout<<"Number of lines in text file: "<<n<<endl;


else cout << "Unable to open file(s) ";

cout<< "Reaching here, Writing one line"<<endl;

system("PAUSE");
return 0; 

【问题讨论】:

“恒定高度增加” ???请改写您的问题。目前无法理解 【参考方案1】:

您需要使用 seekg 设置文件开头的位置,一旦你读过它(你读过一次,计算行数(我认为你实际上不需要,因为这个size 从未使用过,至少在这段代码中)

如果内部while 有什么意义?在每个循环中,您都有

int i=1;
myfile_out<<v[i]; //Not writing to text
i=i+h;

所以在每个循环中,i 得到 1,因此您始终输出索引为 1 的元素。这不是第一个元素,因为索引从0 开始。因此,一旦您输入seekg 或删除第一个while,您的程序就会开始崩溃。

所以,让i0 开始。并从两个while 循环中取出它,就在if-statement 的开头。

啊,第二个while也不需要了。只留下第一个。


编辑: 添加

myfile_in.clear();

seekg 之前清除标志。

另外,你的算法是错误的。如果 h > 1,你会得到段错误,因为你会超出(向量的)范围。我建议这样做:读取while 中的文件,它计算行数。并将每一行存储在向量中。这样您就可以删除第二个读数seekgclear 等。此外,由于您已经将文件内容存储到vector 中,因此您不会丢失任何内容。然后只需使用for 循环和步骤h


再次编辑,关于您的编辑:不,它与任何标志无关。与i==j 进行比较的if 在while 之外。把它加进去。此外,在if 之外增加j。或者只是删除j 并改用n-1。喜欢

if ( n-1 == i )

【讨论】:

【参考方案2】:

几件事。

首先你完全阅读文件,只是为了计算行数, 然后你第二次阅读它来处理它,在内存中建立一个 图片在v。为什么不第一时间阅读它,然后做所有事情 其他在内存图像上? (v.size() 会给你号码 行数,因此您不必计算它们。)

而且你从来没有真正使用过计数。

其次,一旦您第一次到达文件末尾, failbit 已设置;所有进一步的操作都是无操作的,直到它被重置。 如果您必须阅读文件两次(比如说因为您取消了v 完全),那么你必须在第一个之后做myfile_in.clear() 循环,但在寻找开始之前。

您只在读取文件一次后测试is_open。本次测试 应该是在打开之后立即。

您还设置了noskipws,尽管您没有进行任何格式化输入 会受到影响。

最后的while 非常可疑。因为你没有完成 clear,你可能永远不会进入循环,但如果你这样做了,你会非常 快速开始越界访问:读取n行后,大小 的v 将是n,但您使用索引i 读取它,这将是n * h

最后,您应该明确关闭输出文件并检查 结束后出错,以防万一。

我不清楚你想做什么。如果你想做的只是 在每个现有行之间插入 h 空行,例如:

std::string separ( h + 1, '\n' );
std::string line;
while ( std::getline( myfile_in, line ) ) 
    myfile_out << line << separ;

应该可以解决问题。无需将完整的输入存储在内存中。 (就此而言,您甚至不必为此编写程序。 像sed 's:$:\n\n\n\n:' &lt; infile &gt; outfile 这样简单的事情就可以了 诀窍。)

编辑:

阅读其他回复后,我发现我可能误解了 问题,并且他只想输出每个h-th 行。如果这是 案例:

std::string line;
while ( std::getline( myfile_in, line ) ) 
    myfile_out << line << '\n';
    for ( int count = h - 1; h > 0; -- h ) 
        std::getline( myfile_in, line );
        //  or myfile_in.ignore( INT_MAX, '\n' );
    

但同样,其他工具似乎更合适。 (我会按照 thiton 的 建议并使用 AWK。)为什么要使用您不使用的语言编写程序 知道什么时候已经可以使用工具来完成这项工作。

【讨论】:

感谢您的输入,我正在尝试从文本中提取一些行并将其写入另一个...我已经清理了我之前只读一次的代码 system("pause") 表示提问者在windows上运行。因此,使用sed 是一个奇怪的建议 :-) 遵循 thiton 的建议可能是最容易做的事情,但是我对 awk 一无所知。它会从我的文本文件中读取并写入新文件吗? @tyz 我经常在 Windows 上使用sed:-)。毫无疑问,有一些原生的 Windows 等价物可以用来代替它,但我还没有找到。如果你要在平台上开发软件,你肯定需要某种具有这种功能的工具包。【参考方案3】:

如果没有绝对令人信服的理由在 C++ 中执行此操作,则说明您为此使用了错误的编程语言。在 awk 中,你的整个程序是:

 if ( FNR % 4 == 1 ) print; 

或者,给出整个命令行,例如在 sh 中过滤第 1、5、9、13 行,...:

awk ' if ( FNR % 4 == 1 ) print; ' a.txt > b.txt

【讨论】:

这可能是最简单的事情,但是我对 awk 一无所知。它会从我的文本文件中读取并写入新文件吗? 是的,这是基本的操作模式。假设你有一个文本文件 a.txt 并想写入 b.txt,命令行 awk ' if ( FNR % 4 == 1 ) print; ' a.txt > b.txt 完成这项工作。

以上是关于需要将文本的特定行写入新文本的主要内容,如果未能解决你的问题,请参考以下文章

满足特定条件时如何将行写入文本文件

使用 VB.Net 2 读取和写入文本文件中的特定行

VB 写入文件写入特定一行

在 C# 中拆分文本文件无法正常工作

Qt,QFile 写入特定行

C ++ - 在文本文件上写入时代码无法交替行