系统文件操作开发

1、系统文件读写

任务描述:

编写程序,读取linux系统文件"/etc/passwd"内容,并输出到屏幕上.同时在程序目录新建文件passwd,将"/etc/passwd"系统文件内容复制到新建的passwd中

main.c:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#define N 1000

int main(void)
{
    int fp1,fp2,num;
    char *file1,*file2;
    char buf[N];
    file1="/etc/passwd";
    file2="passwd";
    if(( fp1=open(file1,O_RDONLY))==-1){
        printf("can‘t open %s\n",file1);
        return 1;
    }
    if((fp2=open(file2,O_CREAT|O_WRONLY))==-1){
        printf("can‘t create %s\n",file2);
        return -1;
    }
    while((num = read(fp1,buf,N))>0){
        printf("%s\n",buf);
        if(write(fp2,buf,num) == -1 ){
            printf("can‘t write to %s\n",file2);
            return -1;
        }
    }   

    close(fp1);close(fp2);
    return 0;
}

2、文件内容统计操作

任务描述:

  • 给定系统文件filesystem.manifest(dpkg-query -W --showformat=‘${Package} ${Version}\n‘>filesystem.manifest)
  • 目前文件每一行格式为"软件包名 版本号",要求输出每一行的格式为"软件包名"(去除版本号相关信息)到文件filesystem.manifest.name
  • 在第一步基础上,进一步去除换行符号,使整个文件的输出为一行(不同包名用空格分割),格式为"软件包1 软件包2 软件包3...",输出到文件filesystem.manifest.name.oneline
  • 目前每一行格式为"软件包名 版本号",找到文件中软件包名有"ubuntu"字样的软件包,并直接输出其个数(不能人工查找,需直接输出其个数)

相关知识:

①cut 命令可以从一个文本文件或者文本流中提取文本列。
  命令用法:
    cut -b list [-n] [file ...]
    cut -c list [file ...]
    cut -f list [-d delim][-s][file ...]
  上面的-b、-c、-f 分别表示字节、字符、字段(即 byte、character、field);
  list 表示-b、-c、-f 操作范围,-n 常常表示具体数字;
  file 表示的自然是要操作的文本文件的名称;
  delim(英文全写:delimiter)表示分隔符,默认情况下为 TAB;
  -s 表示不包括那些不含分隔符的行(这样有利于去掉注释和标题)
  上面三种方式中,表示从指定的范围中提取字节(-b)、或字符(-c)、或字段(-f)。

②xargs 是一条 Unix 和类 Unix 操作系统的常用命令。它的作用是将参数列表转换成小块分段传递给其他命令,以避免参数列表过长的问题。

例如,下面的命令:
rm `find /path -type f`如果 path 目录下文件过多就会因为“参数列表过长”而报错无法执行。但改用 xargs 以后,问题即获解决。
find /path -type f -print0 | xargs -0 rm
本例中 xargs 将 find 产生的长串文件列表拆散成多个子串,然后对每个子串调用 rm。这样要比如下使用 find 命令效率高的多。
find /path -type f -exec rm ‘{}‘ \;
上面这条命令会对每个文件调用"rm"命令。当然使用新版的"find"也可以得到和"xargs"
命令同样的效果:
find /path -type f -exec rm ‘{}‘ +
xargs 的作用一般等同于大多数 Unix shell 中的反引号,但更加灵活易用,并可以正确处理输入中有空格等特殊字符的情况。对于经常产生大量输出的命令如 find、locate 和 grep 来
说非常有用。

#!/bin/bash

dpkg-query -W --showformat=‘${Package} ${Version}\n‘>filesystem.manifest
cat filesystem.manifest|cut -d ‘ ‘ -f 1 >filesystem.manifest.name
cat filesystem.manifest.name|xargs >filesystem.manifest.name.oneline
cat filesystem.manifest|grep "ubuntu"|wc -l
#-d ‘ ‘表示以空格为字符 -f 1表示输出第一列
#xargs表示将参数列表转换成小块分段传递给其他命令,以避免参数列表过长的问题

3、文件描述符获取

任务描述:

  • 打印输入设备,输出设备,标准错误输出设备的文件描述符
  • 任意打开一个存在文件a,打印其文件描述符
  • 不关闭文件a,定义新的文件描述符重新打开a,打印其文件描述符
  • 关闭文件a,定义新的文件描述符重新打开a,打印文件描述符

相关知识:

  任何打开的文件都将被分配一个唯一标识该打开文件的文件描述符,为一个大于等于 0的整数。系统启动后,默认打开的文件流有标准输入设备(STDIN)、标准输出设备(STDOUT)和标准错误输出设备(STDERR),其文件描述符分别为 0、1、2。以后打开的文件的文件描述符分配依次增加。使用 fileno()函数可以返回一个流对应的文件描述符。

main.c:

#include <stdio.h>

int main()
{
    FILE *fp1,*fp2,*fp3,*fp4;
    int fd;
    fd=fileno(stdin);    printf("stdin is :%d\n",fd);
    fd=fileno(stdout);    printf("stdout is :%d\n",fd);
    fd=fileno(stderr);    printf("stderr is :%d\n",fd);
  printf("open file and open again before it closed\n");  fp1=fopen("test.c", "r");  fd=fileno(fp1);    printf("main.c is %d\n", fd);  fp2=fopen("test.c","r");  fd=fileno(fp2);    printf("main.c is %d\n",fd);  fclose(fp1);fclose(fp2);
    printf("open file and open again after it closed\n");
    fp3=fopen("test.c","r");
    fd=fileno(fp3);
      printf("main.c is %d\n",fd);
    fclose(fp3);
    fp4=fopen("test.c","r");
    fd=fileno(fp4);
      printf("main.c is %d\n",fd);
    return 0;
}

4、检测文件读写权限

任务描述:

  • 检测文件当前读写权限,如果文件具有读权限,则打印可读信息,如果有写权限,则打印可写信息,否则返回错误信息
  • 用fcntl函数实现

相关知识:

fcntl 功能描述:根据文件描述词来操作文件的特性。
文件控制函数:fcntl -- file control
函数原型:
#include <fcntl.h>;
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);
描述: fcntl()针对(文件)描述符提供控制.参数 fd 是被参数 cmd 操作(如下面的描述)的描述符。针对 cmd 的值,fcntl 能够接受第三个参数 int arg。
fcntl 函数有 5 种功能:
1.复制一个现有的描述符(cmd=F_DUPFD).
2.获得/设置文件描述符标记(cmd=F_GETFD 或 F_SETFD).
3.获得/设置文件状态标记(cmd=F_GETFL 或 F_SETFL).
4.获得/设置异步 I/O 所有权(cmd=F_GETOWN 或 F_SETOWN).5.获得/设置记录锁(cmd=F_GETLK,F_SETLK 或 F_SETLKW).

main.c:

#include<stdio.h>
#include<fcntl.h>

int main(void)
{
    FILE *fp;
    int val,acc,a;
    if(( fp=fopen("test.c","r+")) == NULL){
        printf("can‘t open the file\n");
        return 1;
    }
    a=fileno(fp);
    val=fcntl(a,F_GETFL,0);//获得文件状态标记
    acc=val&O_ACCMODE;//把不是关于r、w、x的文件状态标记屏蔽掉
    if (acc==O_RDONLY)
        printf("read only\n");
    if (acc==O_WRONLY)
        printf("write only\n");
    if (acc==O_RDWR)
        printf("read write\n");
    fclose(fp);
    return 0;
}

5、锁定/解锁文件

任务描述:

  • 用fcntl函数实现锁定文件test_lock的两个区域,锁定类型均为以文件开头为锁定的起始位置,区域1锁定为供读取用,起始偏移量为10,长度为20;区域2锁定为供写入用,起始偏移量为40,长度为10.
  • 当进程锁定文件指定区域时,输出"process locking file",停顿10秒钟,关闭文件描述符,输出"process closing file"
  • 使用flock数据结构,使用fcntl函数

相关知识:

  Linux 支持的文件锁技术主要包括劝告锁(advisory lock)和强制锁(mandatory lock)这两种。此外,Linux 中还引入了两种强制锁的变种形式:共享模式强制锁(share-mode mandatory lock)和租借锁(lease)。
  在 Linux 中,不论进程是在使用劝告锁还是强制锁,它都可以同时使用共享锁和排他锁(又称为读锁和写锁)。多个共享锁之间不会相互干扰,多个进程在同一时刻可以对同一个文件加共享锁。但是,如果一个进程对该文件加了排他锁,那么其他进程则无权再对该文件加共享锁或者排他锁,直到该排他锁被释放。所以,对于同一个文件来说,它可以同时拥有很多读者,但是在某一特定时刻,它只能拥有一个写者

  flock 函数用于实现对文件的锁定和解锁操作。此函数只能锁定整个文件,不能锁定某个区域。要锁定某个区域,则需要使用 fcntl()函数。

  int fcntl(int fd, int cmd, struct flock *lock);参数lock指针为flock 结构指针,定义如下:

  struct flock{

    short int l_type;

    short int l_whence;

    off_t l_start;

    off_t l_len;

    pid_t l_pid;

  };

  l_type 有三种状态:

    F_RDLCK 建立一个供读取用的锁定

    F_WRLCK 建立一个供写入用的锁定

    F_UNLCK 删除之前建立的锁定

  l_whence 也有三种方式:

    SEEK_SET 以文件开头为锁定的起始位置。

    SEEK_CUR 以目前文件读写位置为锁定的起始位置

    SEEK_END 以文件结尾为锁定的起始位置。

  l_start 表示相对l_whence位置的偏移量,两者一起确定锁定区域的开始位置。

  l_len表示锁定区域的长度,若果为0表示从起点(由l_whence和 l_start决定的开始位置)开始直到最大可能偏移量为止。即不管在后面增加多少数据都在锁的范围内。

  main.c:

#include<stdio.h>
#include<fcntl.h>

int main(void)
{
    int re,fd;
    fd=open("test_lock",O_RDWR|O_CREAT,0644);
    struct flock z1;
    z1.l_type=F_RDLCK;//建立一个供读取用的锁定
    z1.l_whence=SEEK_SET;//以文件开头为锁定的起始位置
    z1.l_start=10;
    z1.l_len=20;
    printf("Process %d locking file\n",getpid());
    if((re=fcntl(fd,F_SETLK,&z1))==-1){
        printf("failed to lock z1");
    }
    struct flock z2;
    z2.l_type=F_WRLCK;//建立一个供写入用的锁定
    z2.l_whence=SEEK_SET;//以文件开头为锁定的起始位置
    z2.l_start=40;
    z2.l_len=10;
    if((re=fcntl(fd,F_SETLK,&z2))==-1){
        printf("failed to lock z2");
    }
    sleep( 10);
    printf("Process %d closing file\n",getpid());
    close(fd);
    return 0;
}

6、使用 chmod()函数修改文件权限

任务描述:

  • 首先使用touch命令新建3个临时文件:test1,test2,test3
  • 查看最原始文件权限情况(是否为拥有者可读写,所有其他人可读)
  • 设置test1为拥有者可读写,同组用户可读写,其他人可读;test2为拥有者可读写,同组用户可读写可执行,其他人可读;test3为拥有者可读写,同组用户可写不可读、其他用户可写不可读
  • 采用stat数据结,chmod函数
  • 输出修改权限前和修改权限后的文件属性

相关知识:

文件权限知识:

  Linux 系统中的每个文件和目录都有访问许可权限,用它来确定谁可以通过何种方式对文件和目录进行访问和操作。
  文件或目录的访问权限分为只读,只写和可执行三种。以文件为例,只读权限表示只允许读其内容,而禁止对其做任何的更改操作。可执行权限表示允许将该文件作为一个程序执行。文件被创建时,文件所有者自动拥有对该文件的读、写和可执行权限,以便于对文件的阅读和修改。用户也可根据需要把访问权限设置为需要的任何组合。有三种不同类型的用户可对文件或目录进行访问:文件所有者,同组用户、其他用户。
  所有者一般是文件的创建者。所有者可以允许同组用户有权访问文件,还可以将文件的访问权限赋予系统中的其他用户。在这种情况下,系统中每一位用户都能访问该用户拥有的文件或目录。
  每一文件或目录的访问权限都有三组,每组用三位表示,分别为文件属主的读、写和执行权限;与属主同组的用户的读、写和执行权限;系统中其他用户的读、写和执行权限。当用 ls -l 命令显示文件或目录的详细信息时,最左边的一列为文件的访问权限。

main.c:

#include<stdio.h>
#include<sys/stat.h>
#include<unistd.h>

int main(void)
{
    chmod("test01",S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
    chmod("test02",S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH);
    chmod("test03",S_IRUSR|S_IWUSR|S_IWGRP|S_IWOTH);
    return 0;
}
时间: 2024-11-15 20:58:59

系统文件操作开发的相关文章

大数据技术之_04_Hadoop学习_01_HDFS_HDFS概述+HDFS的Shell操作(开发重点)+HDFS客户端操作(开发重点)+HDFS的数据流(面试重点)+NameNode和SecondaryNameNode(面试开发重点)

第1章 HDFS概述1.1 HDFS产出背景及定义1.2 HDFS优缺点1.3 HDFS组成架构1.4 HDFS文件块大小(面试重点)第2章 HDFS的Shell操作(开发重点)第3章 HDFS客户端操作(开发重点)3.1 HDFS客户端环境准备3.2 HDFS的API操作3.2.1 HDFS文件上传(测试参数优先级)3.2.2 HDFS文件下载3.2.3 HDFS文件夹删除3.2.4 HDFS文件名更改3.2.5 HDFS文件详情查看3.2.6 HDFS文件和文件夹判断3.3 HDFS的I/O

linux 系统文件操作sem_open, sem_close, sem_post, sem_wait

信号灯分为有名信号灯和内存信号灯 一.Posix有名信号灯 1.posix有名信号灯函数    函数sem_open创建一个新的有名信号灯或打开一个已存在的有名信号灯.有名信号灯总是既可用于线程间的同步,又能用于进程间的同步. 1. sem_open 名称:: sem_open 功能: 创建并初始化有名信号灯 头文件: #include <semaphore.h> 函数原形: sem_t *sem_open(const char *name,int oflag,/*mode_t mode,un

排球程序扩展之前端操作开发

根据个人偏向爱好,在学习计算机这个领域里,我侧重于网页前端开发.所以在这个假期里,我利用有限的时间根据排球计分这个需求,进行了前台开发的拓展... 需求:为了让排球教练和排球运动员更好的了解对手队员,我需要把对方球员的资料和技能等规划展示出来 一.准备:搜集对方球员的资料及个人技能等 计划时间:假期内抽空完成. 主要View: 二.部分代码: 主页: 子页: 代码审查: 在测试中进行代码的错误审查,有则改正,无则加冕 三.测试结果 1.主页面 2.其中一个分页面 总结: 网页前端设计是客户对程序

05、transformation操作开发实战

1.map:将集合中每个元素乘以2 2.filter:过滤出集合中的偶数 3.flatMap:将行拆分为单词 4.groupByKey:将每个班级的成绩进行分组 5.reduceByKey:统计每个班级的总分 6.sortByKey.sortBy:将学生分数进行排序 7.join:打印每个学生的成绩 8.cogroup:打印每个学生的成绩 package sparkcore.java; import java.util.Arrays; import java.util.Iterator; imp

06、action操作开发实战

1.reduce: 2.collect: 3.count: 4.take: 5.saveAsTextFile: 6.countByKey: 7.foreach: package sparkcore.java; import java.util.Arrays; import java.util.List; import java.util.Map; import org.apache.spark.SparkConf; import org.apache.spark.api.java.JavaPai

【我的Linux,我做主】Linux系统文件操作之cp、rm、mv详解

对文本文件的操作非常基础而且和重要,掌握它们后操作文本你会更加得心应手.要复制文件,请使用cp(copy)这个命令,cp这个命令的用途可多了,除了单纯的复制之外,还可以建立建立快捷方式,对比两个文件的新旧程度从而决定是否更新,以及复制整个目录下的文件等功能.至于移动目录和文件,则使用mv(move),这个命令也可以直接作为文件重命名的作用.至于删除文件,就是使用rm(remove)这个命令,我们来具体瞧一瞧~[1]复制文件或目录:cp格式:cp [-adfilprsu] 源文件 目标文件cp [

JAVAWEB开发之Hibernate详解(一)——Hibernate的框架概述、开发流程、CURD操作和核心配置与API以及Hibernate日志的使用

Hibernate框架概述 什么是Hibernate? 框架:软件的半成品,完成部分代码的功能. Hibernate:Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思想来操作数据库.Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序中使用,也可以在Servlet/JSP的web应用程序中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成

搭建Node+NPM+Grunt+Ruby开发环境

序 最近尝试了一下CoffeeScript,和Sass,不得不说这两个搭配起来的确是不错的选择,熟悉以后基本上开发就比较快速了. 当然要开发这个首先需要搭建环境,这里就需要有Node.NPM.Grunt.Ruby. Node与NPM基本上是一套安装,有了Node环境后才能搭建后面的CoffeeScript环境:而Ruby是为了执行Sass编译命令所需要的环境,当然最后还有一个Grunt,这个是为了项目构建的方便,一体化构建,不用自己重复执行编译命令. Ruby Ruby,一种为简单快捷的面向对象

【嵌入式开发】 嵌入式开发工具简介 (裸板调试示例 | 交叉工具链 | Makefile | 链接器脚本 | eclipse JLink 调试环境)

作者 : 韩曙亮 博客地址 : http://blog.csdn.net/shulianghan/article/details/42239705  参考博客 : [嵌入式开发]嵌入式 开发环境 (远程登录 | 文件共享 | NFS TFTP 服务器 | 串口连接 | Win8.1 + RedHat Enterprise 6.3 + Vmware11) 开发环境 : -- 操作系统 : Vmware11 + RedHat6.3 企业版 + Win8.1; -- 硬件 : OK-6410-A 开发