利用io实现linux中的head -n 功能,将文件中的前n行数据输入到终端上。
1.标准IO实现
步骤:
(1)打开要进行操作的文件(只读)
(2)将输入的行数转换为数字,因为我们输入的是数字,但是系统会认为是字符,需要利用atoi进行转换
(3)循环读取文件中的字符,fgets读到‘\n’会结束,所以刚好一次读取一行,通过对行数进行循环,每读取一行就向终端写入一行
注意:可以在代码前边加入正确的输入格式,当输入错误的时候,进行提示。
// 标准io实现head -n 功能
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
if (argc != 3) // 判断是否输入了进行操作的文件与行数
{
printf("format:%s <filename> <int n>\n", argv[0]);
return -1;
}
// 打开要操作的文件,只读打开
FILE *fp;
char buf[100] = "";
fp = fopen(argv[1], "r");
if (fp == NULL)
{
perror("fopen error");
return -1;
}
// 字符转换为数字
int n = atoi(argv[2]);
// 循环读取打印到终端
// 遇到'\n'结束,一次读一行
for (int i = 1; i <= n; i++)
{
fgets(buf, 100, fp);
fputs(buf, stdout);
sleep(1);
}
// 关闭文件
fclose(fp);
return 0;
}
2.文件IO实现
思想:
文件io的写法,跟标准io比起来只在读取的时候有区别,标准io中fgets读取的时候,读取到行尾自动结束,但是文件io读取时无法一次性标准的读取一行。
所以我们换一个思路,一个字符一个字符的读取,然后对读取到的字符进行判断,当读取到'\n'的时候,就代表读取完了一整行,那么循环中的行数就加一,通过此方式控制循环的行数,可以做到输出固定的行数。
// 文件IO实现head -n 文件名 命令功能
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
if (argc != 3) // 判断是否输入了行数与进行操作的文件
{
printf("format:%s <hangshu> <destfile>\n", argv[0]);
return -1;
}
// 只读打开文件
int fd = open(argv[2], O_RDONLY);
if (fd < 0)
{
printf("open err");
return -1;
}
char buf[1000] = {}; // 存放读到的数据
int n = atoi(argv[1]); // 确定打几行
long s = 0;
int len = 0;
// 一个字符一个字符的读
// 每读到一个'\n',就代表读到了行尾,行数加一,直到读取到n行
while (len != n)
{
// 读取fp中 1个字符暂存在 buf中
s = read(fd, buf, 1);
if (buf[0] == '\n')
{
len++;
}
// 写入 buf 中 暂存的 s 个字符
write(1, buf, s);
}
close(fd);
return 0;
}
3.标准IO实现第二种写法
这个写法跟第二种是差不多肯定,只不过上一种是一次读取一个,一个一个的判断写入到终端,第二种方法是一次读取固定个数的字符,然后对读取的字符进行判断,如果一次性读取的字符串里包含换行符,那么就把换行符之前的字符串写入到终端,同时行数加一,如果一次性读取的字符串中没有换行符,那么就把这次读取到的字符全部写入到终端。
// 文件IO实现head -n 文件名 命令功能
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
if (argc != 3) // 判断是否输入了行数与进行操作的文件
{
printf("err,format:%s -n <filename>\n", argv[0]);
return -1;
}
// 只读打开文件
int fd = open(argv[2], O_RDONLY);
if (fd < 0)
{
perror("open error");
return -1;
}
// 暂存读取的数据
char buf[32] = "";
ssize_t r;
int n = atoi(argv[1]);
int h = 0;
// 只要读到内容
while ((r = read(fd, buf, 32)) > 0)
{
// 循环对比读取到的字符,当发现'\n'时,就代表一行结束
// 将换行之前的字符写入到终端进行输出
// 如果读取到的字符串中没有换行,那么就把这次读取到的字符都写到终端上
for (int i = 0; i < 32; i++)
{
if (buf[i] == '\n')
{
h++;
if (h == n)
{
write(1, buf, i);
printf("\n");
close(fd);
return 0;
}
}
}
write(1, buf, 32);
}
printf("\n");
close(fd);
return 0;
}