C 函数在文件中的特定位置插入文本而不覆盖现有文本
我编写了一个程序,它接受一个文件作为输入,每当它找到长度>的行时80,它会向该文件添加 \ 和 \n,使其最大宽度为 80 个字符。
问题是,只要长度超过 80,我就使用 fseek 插入 \ 和 \n,因此它会覆盖长度超过 80 的该行的两个字符。有没有一种方法可以插入文本而不覆盖现有文本?
这是我的代码:-
#include<stdio.h>
#include<string.h>
int main(int argc, char *argv[])
{
FILE *fp1,*fp2;
int prev=0,now=0;
char ch;
int flag=0;
long cur;
fp1=fopen(argv[1],"r+");
if(fp1==NULL){
printf("Unable to open the file to read. Program will exit.");
exit(0);
}
else{
while((ch=fgetc(fp1))!=EOF){
if(ch!=' ' && ch!='\n'){
now=now+1;
}
else{
if(now>=80){
fseek(fp1,cur,SEEK_SET);
fputc('\\',fp1);
fputc('\n',fp1);
now=0;
continue;
}
if(ch=='\n'){
flag=0;
now=0;
continue;
}
else{
prev=now;
cur=ftell(fp1);
}
now=now+1;
}
}
}
fclose(fp1);
return 0;
}
要运行它,您需要执行以下操作:-
user@ubuntu$ cc xyz.c
user@ubuntu$ ./a.out file_to_check.txt
I have written a program which takes a file as input and whenever it finds a line with length > 80, it adds \ and \n to that file to make it 80 chars in width max.
The problem is that I have used fseek to insert \ and \n whenever the length exceeds 80, so it overrides two characters of that line which exceeds length 80. Is there a way using which I can insert text without overriding the existing text?
Here is my code:-
#include<stdio.h>
#include<string.h>
int main(int argc, char *argv[])
{
FILE *fp1,*fp2;
int prev=0,now=0;
char ch;
int flag=0;
long cur;
fp1=fopen(argv[1],"r+");
if(fp1==NULL){
printf("Unable to open the file to read. Program will exit.");
exit(0);
}
else{
while((ch=fgetc(fp1))!=EOF){
if(ch!=' ' && ch!='\n'){
now=now+1;
}
else{
if(now>=80){
fseek(fp1,cur,SEEK_SET);
fputc('\\',fp1);
fputc('\n',fp1);
now=0;
continue;
}
if(ch=='\n'){
flag=0;
now=0;
continue;
}
else{
prev=now;
cur=ftell(fp1);
}
now=now+1;
}
}
}
fclose(fp1);
return 0;
}
To run it, you need to do following:-
user@ubuntu$ cc xyz.c
user@ubuntu$ ./a.out file_to_check.txt
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
虽然有多种技术可以就地完成此操作,但您正在使用文本文件并希望执行插入。操作系统通常不支持将文本文件插入作为文件系统原语,并且它们没有理由这样做。
执行此类操作的最佳方法是打开文件进行读取,打开一个新文件进行写入,复制插入点之前的文件部分,插入数据,复制其余部分,然后将新文件移到旧文件上。
这是一种常见的技术,并且有其目的。如果出现任何问题(例如您的系统),您仍然拥有原始文件,并且可以稍后重复交易。如果您启动该流程的两个实例并使用特定模式,则第二个实例能够检测到事务已启动。通过独占文件访问,它甚至可以检测事务是否已中断或仍在运行。
这种方式比直接在原始文件上执行的任何技术更不容易出错,并且由所有这些传统工具(如
sed
)使用,即使您要求它们就地工作(sed -i
)。另一个好处是,您始终可以在覆盖原始文件之前将其重命名为带有备份后缀的文件(sed
也提供了这样的选项)。即使您的程序正在编写全新版本并且不使用原始文件,同样的技术也经常用于配置文件。不久前,许多网络杂志声称 ext4 意外地将配置文件截断为零长度。这正是因为某些应用程序在系统强制关闭时保持配置文件打开并被截断。这些应用程序经常在数据准备好之前就篡改原始配置文件,甚至在不同步它们的情况下保持打开状态,这使得数据损坏的窗口变得更大。
TL;DR 版本:
当您重视数据时,在准备好替换数据之前不要销毁它。
While there are a couple of techniques to do it in-place, you're working with a text file and want to perform insertions. Operating systems typically don't support text file insertions as a file system primitive and there's no reason they should do that.
The best way to do that kind of thing is to open your file for reading, open a new file for writing, copy the part of the file before the insertion point, insert the data, copy the rest, and then move the new file over the old one.
This is a common technique and it has a purpose. If anything goes wrong (e.g. with your system), you still have the original file and can repeat the transaction later. If you start two instances of the process and use a specific pattern, the second instance is able to detect that the transaction has already been started. With exclusive file access, it can even detect whether the transaction was interrupted or is still running.
That way is much less error prone than any of the techniques performed directly on the original file and is used by all of those traditional tools like
sed
even if you ask them to work in-place (sed -i
). Another bonus is that you can always rename the original file to one with a backup suffix before overwriting it (sed
offers such an option as well).The same technique is often used for configuration files even if your program is writing an entirely new version and doesn't use the original file for that. It hasn't been long since many internet magazines claimed that ext4 accidentally truncates configuration files to zero length. This was exactly because some applications kept the configuration files open and truncated while the system was forcedly shut down. Those application often tampered with the original configuration files before they had the data ready and then even kept them open without syncing them, which made the window for data corruption much larger.
TL;DR version:
When you value your data, don't destroy it before you have the replacement data ready.
不,无法将字符插入现有文件中。您将需要使用第二个文件来执行此操作。
No, there's no way to insert characters into an existing file. You will need to use a second file to do that.
这是我用于此类事情的函数:
像这样使用它:
理论上,如果出现错误,这(正如其他人提到的那样)可能会损坏文件,但这里有一些实际执行此操作的代码...像这样就地通常没问题,但如果您担心的话,应该备份文件......
This is the function I use for this kind of thing:
Use it like this:
This (as others here have mentioned) can theoretically corrupt a file if there is an error, but here is some code to actually do it... Doing it in-place like this is usually fine, but you should backup the file if you are worried about it...
不,没有办法。您必须创建一个新文件或将文件内容向后移动 2 个字符。
No, there is no way. You have to create a new file or move the contents of the file 2 characters backwards.
您可以将文件作为块加载(在您的情况下为 80 个字符),然后附加两个字符(换行)并将内容写入另一个文件中。
You can load the file as chunks (in your case is 80 characters) and then append two character (new line) and write the content into anohter file.
另一个实现使用
在 Cygwin64 中测试的
tmpfile()
another implementation use
tmpfile()
tested in Cygwin64