在C中以相反的顺序将字节从一个文件复制到另一个文件
copy bytes from one file to another in reverse order in C
在我的环境中检查 answer here 和 运行 后,我发现代码仍然遇到与我的代码相同的问题。
这个问题是每当我有一个类似于这个的输入文件时...
FILE A
|---------------------|
| ABCDE |
| abcde |
|---------------------|
我在目标文件中生成了额外的白色换行符 space。
FILE B
|---------------------|
| edcba |
| |
| EDCBA |
|---------------------|
调试我的代码后,我可以看到“\n”被复制到目标文件两次,我想了解为什么 lseek 这样做。
附件是我的代码。有问题的关键部分在 do/while 循环中。我非常确定我的思考过程是合理的,因为我查找的answer中的代码会输出完全相同的结果。
#define CHAR_SIZE 2048
#define BUFF_SIZE 1
#define PERMS 0666
int main(int argc, char* argv[]){
if (argc < 3) {
return 1;
printf ("ERROR: not enough arguments\n");
}
int src_file = 0; int dest_file = 0;
int n = -1;
if((src_file=open(argv[1],O_RDONLY)) < -1) return 1;
if((dest_file = creat(argv[2], PERMS)) < -1) return 1;
printf ("The filesize is: %d\n", lseek(src_file, (off_t) 0, SEEK_END));
char buffer[BUFF_SIZE];
lseek (src_file,n--,SEEK_END);
do {
read(src_file,buffer,BUFF_SIZE);
printf ("%s", buffer);
write(dest_file,buffer,BUFF_SIZE);
}while (lseek (src_file,n--,SEEK_END) > -1);
printf("\n");
return 0;
}
你有很多问题。您的额外换行符来自 POSIX 将行尾定义为 newline
的事实(尽管并非所有文件都符合)。因此,要摆脱额外的换行符,您需要:
int n = -2;
而不是
int n = -1;
(显式读取 POSIX 行尾并将其写入输出文件)
您的其他问题是您不知道文件打开是否失败,因为您检查 return 不正确:
// if ((src_file = open (argv[1],O_RDONLY)) < -1) return 1;
// if ((dest_file = creat (argv[2], PERMS)) < -1) return 1;
return 是 -1
失败。因此你需要:
if ((src_file = open (argv[1],O_RDONLY)) == -1) return 1;
if ((dest_file = creat (argv[2], PERMS)) == -1) return 1;
接下来,您的缓冲区将不会保存字符串。至少您需要一个 2-char
数组来保存 1-char
加上 nul-terminating
字符。以下将不起作用:
#define BUFF_SIZE 1
...
char buffer[BUFF_SIZE];
...
printf ("%s", buffer);
您向 printf
发送了一个未终止的字符。如果您在启用 warnings(例如 -Wall -Wextra
)的情况下进行编译,您会知道,因为编译器会警告您(即使没有正确的警告标志,它也可能会警告您,具体取决于您的编译器) .至少要完成上述工作,您需要:
#define BUFF_SIZE 2
并且您必须确保在调用 printf
之前 nul-terminate buffer
。您可以通过以下方式完成:
char buffer[BUFF_SIZE] = "";
...
read (src_file, buffer, BUFF_SIZE - 1);
buffer[1] = 0;
printf ("%s", buffer);
write (dest_file, buffer, BUFF_SIZE - 1);
(您应该检查 read
和 write
的 return 以验证您是 reading/writing 您认为的字节数...)
将更正放在一起(并显示您可以完全消除缓冲区并简单地使用 int
作为 buf 字符)您可以执行以下操作:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define CHAR_SIZE 2048
#define BUFF_SIZE 2
#define PERMS 0666
int main(int argc, char **argv) {
if (argc < 3) {
return 1;
printf ("ERROR: not enough arguments\n");
}
int src_file = 0;
int dest_file = 0;
int n = -2;
int nl = '\n'; /* explicit newline when writing in reverse */
// if ((src_file = open (argv[1],O_RDONLY)) < -1) return 1;
// if ((dest_file = creat (argv[2], PERMS)) < -1) return 1;
if ((src_file = open (argv[1],O_RDONLY)) == -1) return 1;
if ((dest_file = creat (argv[2], PERMS)) == -1) return 1;
printf ("The filesize is: %ld\n", lseek(src_file, (off_t) 0, SEEK_END));
lseek (src_file, n--, SEEK_END);
#ifdef WBUFCHAR
int bufchar;
do { /* validate both read and write */
if (read (src_file, &bufchar, BUFF_SIZE - 1) == 0) {
fprintf (stderr, "error: read failure.\n");
return 1;
}
putchar (bufchar);
if (write (dest_file, &bufchar, BUFF_SIZE - 1) == 0) {
fprintf (stderr, "error: write failure.\n");
return 1;
}
} while (lseek (src_file, n--, SEEK_END) > -1);
#else
char buffer[BUFF_SIZE];
do { /* validate both read and write */
if (read (src_file, buffer, BUFF_SIZE - 1) == 0) {
fprintf (stderr, "error: read failure.\n");
return 1;
}
buffer[1] = 0; /* nul-terminate */
printf ("%s", buffer);
if (write (dest_file, buffer, BUFF_SIZE - 1) == 0) {
fprintf (stderr, "error: write failure.\n");
return 1;
}
} while (lseek (src_file, n--, SEEK_END) > -1);
#endif
/* explicity write the newline you removed earlier */
if (write (dest_file, &nl, BUFF_SIZE - 1) == 0) {
fprintf (stderr, "error: write failure.\n");
return 1;
}
putchar ('\n');
return 0;
}
注意: 正常编译以使用您的 buffer
。使用 -DWBUFCHAR
编译以使用 bufchar
代码。
示例编译和输出
$ cat testabcde.txt
ABCDE
abcde
$ gcc -Wall -Wextra -Ofast -o bin/extranl extranl.c
$ ./bin/extranl testabcde.txt testrev.txt
The filesize is: 12
edcba
EDCBA
$ cat testrev.txt
edcba
EDCBA
$ gcc -Wall -Wextra -Ofast -DWBUFCHAR -o bin/extranlwbc extranl.c
$ ./bin/extranlwbc testabcde.txt testrevwbc.txt
The filesize is: 12
edcba
EDCBA
$ cat testrevwbc.txt
edcba
EDCBA
试一试,如果您还有其他问题,请告诉我。
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#define CHAR_SIZE 2048
#define BUFF_SIZE 1
#define PERMS 0666
int main(int argc, char* argv[]){
if (argc < 3) {
printf ("ERROR: not enough arguments\n");
return 1;
}
int src_file = 0; int dest_file = 0;
int n = -1;
if((src_file=open(argv[1],O_RDONLY)) == -1) return 1;
if((dest_file = creat(argv[2], PERMS)) == -1) return 1;
printf ("The filesize is: %d\n", lseek(src_file, (off_t) 0, SEEK_END));
char buffer[BUFF_SIZE];
lseek (src_file,n--,SEEK_END);
do {
read(src_file,buffer,BUFF_SIZE);
printf("%02x\n", *buffer);
if (*buffer == '\n')
n--;
write(dest_file,buffer,BUFF_SIZE);
}while (lseek (src_file,n--,SEEK_END) > -1);
printf("\n");
return 0;
}
此解决方案是修复输出文件中额外的白色换行符 space (\n\n) 的最佳方法。
通过将此部分添加到 do/while 循环中,我可以补偿添加的额外 \n。
if (*buffer == '\n')
n--;
在我的环境中检查 answer here 和 运行 后,我发现代码仍然遇到与我的代码相同的问题。 这个问题是每当我有一个类似于这个的输入文件时...
FILE A
|---------------------|
| ABCDE |
| abcde |
|---------------------|
我在目标文件中生成了额外的白色换行符 space。
FILE B
|---------------------|
| edcba |
| |
| EDCBA |
|---------------------|
调试我的代码后,我可以看到“\n”被复制到目标文件两次,我想了解为什么 lseek 这样做。
附件是我的代码。有问题的关键部分在 do/while 循环中。我非常确定我的思考过程是合理的,因为我查找的answer中的代码会输出完全相同的结果。
#define CHAR_SIZE 2048
#define BUFF_SIZE 1
#define PERMS 0666
int main(int argc, char* argv[]){
if (argc < 3) {
return 1;
printf ("ERROR: not enough arguments\n");
}
int src_file = 0; int dest_file = 0;
int n = -1;
if((src_file=open(argv[1],O_RDONLY)) < -1) return 1;
if((dest_file = creat(argv[2], PERMS)) < -1) return 1;
printf ("The filesize is: %d\n", lseek(src_file, (off_t) 0, SEEK_END));
char buffer[BUFF_SIZE];
lseek (src_file,n--,SEEK_END);
do {
read(src_file,buffer,BUFF_SIZE);
printf ("%s", buffer);
write(dest_file,buffer,BUFF_SIZE);
}while (lseek (src_file,n--,SEEK_END) > -1);
printf("\n");
return 0;
}
你有很多问题。您的额外换行符来自 POSIX 将行尾定义为 newline
的事实(尽管并非所有文件都符合)。因此,要摆脱额外的换行符,您需要:
int n = -2;
而不是
int n = -1;
(显式读取 POSIX 行尾并将其写入输出文件)
您的其他问题是您不知道文件打开是否失败,因为您检查 return 不正确:
// if ((src_file = open (argv[1],O_RDONLY)) < -1) return 1;
// if ((dest_file = creat (argv[2], PERMS)) < -1) return 1;
return 是 -1
失败。因此你需要:
if ((src_file = open (argv[1],O_RDONLY)) == -1) return 1;
if ((dest_file = creat (argv[2], PERMS)) == -1) return 1;
接下来,您的缓冲区将不会保存字符串。至少您需要一个 2-char
数组来保存 1-char
加上 nul-terminating
字符。以下将不起作用:
#define BUFF_SIZE 1
...
char buffer[BUFF_SIZE];
...
printf ("%s", buffer);
您向 printf
发送了一个未终止的字符。如果您在启用 warnings(例如 -Wall -Wextra
)的情况下进行编译,您会知道,因为编译器会警告您(即使没有正确的警告标志,它也可能会警告您,具体取决于您的编译器) .至少要完成上述工作,您需要:
#define BUFF_SIZE 2
并且您必须确保在调用 printf
之前 nul-terminate buffer
。您可以通过以下方式完成:
char buffer[BUFF_SIZE] = "";
...
read (src_file, buffer, BUFF_SIZE - 1);
buffer[1] = 0;
printf ("%s", buffer);
write (dest_file, buffer, BUFF_SIZE - 1);
(您应该检查 read
和 write
的 return 以验证您是 reading/writing 您认为的字节数...)
将更正放在一起(并显示您可以完全消除缓冲区并简单地使用 int
作为 buf 字符)您可以执行以下操作:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define CHAR_SIZE 2048
#define BUFF_SIZE 2
#define PERMS 0666
int main(int argc, char **argv) {
if (argc < 3) {
return 1;
printf ("ERROR: not enough arguments\n");
}
int src_file = 0;
int dest_file = 0;
int n = -2;
int nl = '\n'; /* explicit newline when writing in reverse */
// if ((src_file = open (argv[1],O_RDONLY)) < -1) return 1;
// if ((dest_file = creat (argv[2], PERMS)) < -1) return 1;
if ((src_file = open (argv[1],O_RDONLY)) == -1) return 1;
if ((dest_file = creat (argv[2], PERMS)) == -1) return 1;
printf ("The filesize is: %ld\n", lseek(src_file, (off_t) 0, SEEK_END));
lseek (src_file, n--, SEEK_END);
#ifdef WBUFCHAR
int bufchar;
do { /* validate both read and write */
if (read (src_file, &bufchar, BUFF_SIZE - 1) == 0) {
fprintf (stderr, "error: read failure.\n");
return 1;
}
putchar (bufchar);
if (write (dest_file, &bufchar, BUFF_SIZE - 1) == 0) {
fprintf (stderr, "error: write failure.\n");
return 1;
}
} while (lseek (src_file, n--, SEEK_END) > -1);
#else
char buffer[BUFF_SIZE];
do { /* validate both read and write */
if (read (src_file, buffer, BUFF_SIZE - 1) == 0) {
fprintf (stderr, "error: read failure.\n");
return 1;
}
buffer[1] = 0; /* nul-terminate */
printf ("%s", buffer);
if (write (dest_file, buffer, BUFF_SIZE - 1) == 0) {
fprintf (stderr, "error: write failure.\n");
return 1;
}
} while (lseek (src_file, n--, SEEK_END) > -1);
#endif
/* explicity write the newline you removed earlier */
if (write (dest_file, &nl, BUFF_SIZE - 1) == 0) {
fprintf (stderr, "error: write failure.\n");
return 1;
}
putchar ('\n');
return 0;
}
注意: 正常编译以使用您的 buffer
。使用 -DWBUFCHAR
编译以使用 bufchar
代码。
示例编译和输出
$ cat testabcde.txt
ABCDE
abcde
$ gcc -Wall -Wextra -Ofast -o bin/extranl extranl.c
$ ./bin/extranl testabcde.txt testrev.txt
The filesize is: 12
edcba
EDCBA
$ cat testrev.txt
edcba
EDCBA
$ gcc -Wall -Wextra -Ofast -DWBUFCHAR -o bin/extranlwbc extranl.c
$ ./bin/extranlwbc testabcde.txt testrevwbc.txt
The filesize is: 12
edcba
EDCBA
$ cat testrevwbc.txt
edcba
EDCBA
试一试,如果您还有其他问题,请告诉我。
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#define CHAR_SIZE 2048
#define BUFF_SIZE 1
#define PERMS 0666
int main(int argc, char* argv[]){
if (argc < 3) {
printf ("ERROR: not enough arguments\n");
return 1;
}
int src_file = 0; int dest_file = 0;
int n = -1;
if((src_file=open(argv[1],O_RDONLY)) == -1) return 1;
if((dest_file = creat(argv[2], PERMS)) == -1) return 1;
printf ("The filesize is: %d\n", lseek(src_file, (off_t) 0, SEEK_END));
char buffer[BUFF_SIZE];
lseek (src_file,n--,SEEK_END);
do {
read(src_file,buffer,BUFF_SIZE);
printf("%02x\n", *buffer);
if (*buffer == '\n')
n--;
write(dest_file,buffer,BUFF_SIZE);
}while (lseek (src_file,n--,SEEK_END) > -1);
printf("\n");
return 0;
}
此解决方案是修复输出文件中额外的白色换行符 space (\n\n) 的最佳方法。
通过将此部分添加到 do/while 循环中,我可以补偿添加的额外 \n。
if (*buffer == '\n')
n--;