我有一个代码读取文件,然后将其内容复制到另一个文件。我需要让它只复制每20个符号,然后跳过10个符号,然后再跳过20个符号,依此类推。
我必须使用lseek()函数,但我不知道如何在循环中完成所有这些操作。
main (argc, argv)
int argc;
char *argv[];
{
int fd1, fd2;
int nbytes, mode;
char buf[BUFSIZ];
if(argc<3){
fprintf(stderr, "%s: nepareizs kopesanas parametrs\n", argv[0]);
exit(1);
}
if((fd1 = open(argv[1], O_RDONLY)) < 0){
fprintf(stderr, "Nevar atvert failu %s\n", argv[1]);
exit(1);
}
if((fd2 = open(argv[2], O_WRONLY | O_CREAT, mode))<0){
fprintf(stderr, "Nevar izveidot jaunu failu %s\n", argv[2]);
exit(1);
}
nbytes = lseek(fd1, 10, 0)
while((nbytes = read(fd1, buf, BUFSIZ))>0){
if(write(fd2, buf, nbytes) < 0){
fprintf(stderr, "не понимаю\n");
break;
}
}
if (nbytes<0)
fprintf(stderr, "не понимаю\n");
close(fd1);
close(fd2);
exit(0);
}
答案 0 :(得分:1)
替换
nbytes = lseek(fd1, 10, 0)
while((nbytes = read(fd1, buf, BUFSIZ))>0){
if(write(fd2, buf, nbytes) < 0){
fprintf(stderr, "не понимаю\n");
break;
}
}
与
while((nbytes = read(fd1, buf, BUFSIZ))>0){
/* first you write your 20 bytes */
if(write(fd2, buf, nbytes) < 0){
fprintf(stderr, "не понимаю\n");
break;
}
/* and then you move 10 bytes further */
if (lseek(fd1, 10, 0) < 0){
/* break if this is the eof */
break;
}
}
如果BUFSIZ是20。
或最简单,BUFSIZ = 30:
while((nbytes = read(fd1, buf, BUFSIZ))>0){
/* you only write the first 20 read bytes, or nbytes
if there are no much bytes in the buffer */
if(write(fd2, buf, nbytes < 20 ? nbytes : 20) < 0){
fprintf(stderr, "не понимаю\n");
break;
}
}
答案 1 :(得分:0)
另一种考虑的替代方案。您的问题的评论中提到了许多好处。下面的示例收集了各种注释,并提供了一种简洁的方法来读取30个字节并将前20个字节写入输出文件。
避免使用所有幻数(遍及代码的硬编码值)。验证读取和写入,使用流操作(例如fread
,fwrite
)而不是read
,write
)和输出的close
文件已经过验证:
#include <stdio.h>
enum { WRTSZ = 20, BUFSZ = 30 };
int main (int argc, char **argv) {
if (argc < 3 ) {
fprintf (stderr, "error: insufficient input, usage: %s ifile ofile\n",
argv[0]);
return 1;
}
FILE *ifp = fopen (argv[1], "rb");
FILE *ofp = fopen (argv[2], "w+");
char buf[BUFSZ] = "";
if (!ifp) { /* validate file open for reading (binary) */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
if (!ofp) { /* valdate file open for writing */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
/* read BUFSZ bytes (require at least WRTSZ), and output */
while (fread (buf, sizeof *buf, BUFSZ, ifp) >= WRTSZ)
if (fwrite (buf, sizeof *buf, WRTSZ, ofp) != WRTSZ)
fprintf (stderr, "error: fwrite of WRTSZ failed.\n");
fclose (ifp);
if (fclose (ofp)) /* validate close of output file */
fprintf (stderr, "error: on close of '%s'.\n", argv[2]);
return 0;
}
(注意:只写入完整的20字节块。如果最后一次读取的部分读取少于20字节,则该信息不会写入输出文件。您可以调整fread
和fwrite
周围的条件,以根据您的需要定制行为。)
示例输入文件(非POSIX,没有eol)
以下输入文件是用于示例目的的文本,它不包含POSIX 行尾('\n'
)。 (如果您愿意,可以包含换行符,只会导致换行符被写入输出文件)
$ cat dat/ruler.txt
........10........20........30........40........50........60........70........80........90
使用/输出文件
$ ./bin/rd30wrt20 dat/ruler.txt dat/rulerout.txt
$ cat dat/rulerout.txt
........10........20........40........50........70........80
仔细看看,如果您有任何问题,请告诉我。
写入所有字节(0 <部分字节&lt; = WRTSZ)
如果要编写在上一个fread
期间读取的任何部分字节,可以将条件调整为类似于以下内容:
size_t rdsz;
...
/* read BUFSZ bytes, write 0 < rdsz <= WRTSZ */
while ((rdsz = fread (buf, sizeof *buf, BUFSZ, ifp)))
if (fwrite (buf, sizeof *buf,
rdsz > WRTSZ ? WRTSZ : rdsz, ofp) != WRTSZ)
fprintf (stderr, "warning: fwrite of '%zu'.\n", rdsz);