1.统计文件的字节数目大小
#include <stdio.h>
#include <stdlib.h>
/*
使用方法:./a.out file
*/
int main(int argc, char *argv[])
{
if(argc != 2) {
fprintf(stderr, "Error used!");
exit(-1);
}
FILE *fd;
int ch = 0; //统计字节数目
fd = fopen(argv[1], "r"); //以只读的方式打开
if(fd == NULL) {
perror("fopen() failed!");
exit(-1);
}
/* 方式1
while(fgetc(fd) != EOF) {
ch++;
}
printf("Count = %d\n", ch);
*/
/* 方式2
fseek(fd, 0, SEEK_END);
printf("Count = %ld\n", ftell(fd));
*/
fclose(fd);
exit(0);
}
方式③:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
static off_t flen(const char *filename)
{
struct stat buf;
if(stat(filename, &buf) < 0) {
perror("stat()");
exit(-1);
}
return buf.st_size;
}
int main(int argc, char *argv[])
{
if(argc != 2) {
fprintf(stderr, "Error used!\n");
exit(-1);
}
printf("cnt = %lld\n", (long long)flen(argv[1]));
exit(0);
}
效果:
2.按行读取文件内容,并打印每行大小和申请的存储空间大小
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
if(argc != 2) {
fprintf(stderr, "Error used!\n");
exit(-1);
}
FILE *fd;
char *linebuf = NULL; //保存读取文件
size_t linesize = 0; //保存存储空间大小
fd = fopen(argv[1], "r");
if(fd == NULL) {
perror("fopen()!");
exit(-1);
}
while(1) {
if(getline(&linebuf, &linesize, fd) < 0) break; //终止条件
printf("strlen = %ld\n", strlen(linebuf)); //实际大小
printf("size = %ld\n", linesize);
}
free(linebuf);
fclose(fd); //关闭
exit(0);
}
效果:
testd.c文件内容
3.实现文件的copy
标准IO:
#include <stdio.h>
#include <stdlib.h>
#define BUFFSIZE 1024
int main(int argc, char *argv[])
{
FILE *fds, *fdd; //源和目标文件
char buf[BUFFSIZE];
if(argc != 3) {
fprintf(stderr, "Erroe used:%s\n", argv[0]);
exit(-1);
}
fds = fopen(argv[1], "r");
if(fds == NULL) {
perror("fopen() fds");
exit(-1);
}
fdd = fopen(argv[2], "w");
if(fdd == NULL) {
perror("fopen() fdd");
exit(-1);
}
while(fgets(buf, BUFFSIZE, fds) != NULL) {
fputs(buf, fdd);
}
fclose(fdd);
fclose(fds);
exit(0);
}
文件IO:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define BUFSIZE 1024
//argv[1]:源文件
//argv[2]:目标文件
int main(int argc, char *argv[])
{
if(argc != 3) {
fprintf(stderr, "Usage failed!\n");
exit(-1);
}
int fds, fdd; //定义文件描述符
int len, ret, pos;
char buf[BUFSIZE];
fds = open(argv[1], O_RDONLY);
if(fds == -1) { //打开失败
perror("open fds failed!");
exit(-1);
}
fdd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666);
if(fdd == -1) { //打开失败
perror("open fdd failed!");
exit(-1);
}
pos = 0;
while(1) {
len = read(fds, buf, BUFSIZE); //从fds中读取BUFSIZE个字节到buf中
if(len < 0) {
perror("read");
exit(-1);
}
if(len == 0) break; //len = 0表示没东西可以读了
while(len) {
ret = write(fdd, buf + pos, len); //从buf中写len长度个字节到fdd中
if(ret < 0) {
perror("write");
exit(-1);
}
pos += ret;
len -= ret;
}
pos = 0;
}
close(fds);
close(fdd);
exit(0);
}
4.打印文件的类型
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
static int ftype(const char *filename)
{
struct stat buf;
stat(filename, &buf);
if(S_ISREG(buf.st_mode)) return '-'; //常规文件
else if(S_ISDIR(buf.st_mode)) return 'd'; //目录文件
else if(S_ISCHR(buf.st_mode)) return 'c'; //字符设备文件
else if(S_ISBLK(buf.st_mode)) return 'b'; //块设备文件
else if(S_ISFIFO(buf.st_mode)) return 'f'; //管道文件
else if(S_ISLNK(buf.st_mode)) return 'l'; //链接文件
else if(S_ISSOCK(buf.st_mode)) return 's'; //socket文件
else return '?'; //异常
}
int main(int argc, char *argv[])
{
if(argc != 2) {
fprintf(stderr, "Errur used!\n");
exit(-1);
}
printf("type = %c\n",ftype(argv[1]));
exit(0);
}
效果:
5.读取目录文件
方法一:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <glob.h>
#define PAT "/etc/*"
int main(int argc, char *argv[])
{
glob_t globes;
int err;
err = glob(PAT, 0, NULL, &globes); //模式为PAT,不追加功能,不保存错误路径和错误码,将目录解析后存入globes
if(err) {
printf("Error code = %d\n",err);
exit(-1);
}
for(int i = 0;i < globes.gl_pathc;i++)
puts(globes.gl_pathv[i]); //打印解析后的目录
globfree(&globes);
exit(0);
}
方法二:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#define PAT "/etc"
int main()
{
DIR *dp;
struct dirent *cur;
dp = opendir(PAT);
if(dp == NULL) {
perror("opendir()");
exit(-1);
}
while((cur = readdir(dp)) != NULL)
puts(cur->d_name);
closedir(dp);
exit(0);
}
6.模擬du命令
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <glob.h>
#define PATHSIZE 1024
/* 判断是否为“.”或者“..” */
static int path_noloop(const char *path)
{
char *pos;
pos = strrchr(path, '/'); //找到最右边的'/'
if(strcmp(pos+1, ".") == 0 || strcmp(pos+1, "..") == 0)
return 0;
return 1;
}
static int64_t mydu(const char *pathname)
{
struct stat statres;
static char nextpath[PATHSIZE];
glob_t globres;
int i;
int64_t sum;
if(lstat(pathname, &statres) < 0) {
perror("lstat()");
exit(-1);
}
/*mydu分为两种情况,非目录和目录*
非目录文件可以直接返回文件大小
目录文件需要对目录进行解析
*/
if(!S_ISDIR(statres.st_mode)) { /*非目录直接返回*/
return statres.st_blocks;
}
/*是目录,进行解析 *和.* */
strncpy(nextpath, pathname, PATHSIZE);
strncat(nextpath, "/*", PATHSIZE - 1);
glob(nextpath, 0, NULL, &globres);
strncpy(nextpath, pathname, PATHSIZE);
strncat(nextpath, "/.*", PATHSIZE - 1);
// 把解析到的结果追加到globres中
glob(nextpath, GLOB_APPEND, NULL, &globres);
sum = 0;
for(i = 0; i < globres.gl_pathc; i++)
{
if(path_noloop(globres.gl_pathv[i]))
sum += mydu(globres.gl_pathv[i]);
}
sum += statres.st_blocks;
globfree(&globres);
return sum;
}
int main(int argc, char *argv[])
{
if(argc < 2) {
fprintf(stderr, "Used errod()!\n");
exit(-1);
}
printf("%lld\n", mydu(argv[1]) / 2);
exit(0);
}