Unix系统编程()open,read,write和lseek的综合练习

Posted tuhooo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unix系统编程()open,read,write和lseek的综合练习相关的知识,希望对你有一定的参考价值。

需求:程序的第一个命令行参数为将要打开的文件名称,余下的参数则指定了文件上执行的输入输出操作。每个表示操作的参数都以一个字母开头,紧跟以相关值(中间无空格分隔)。

 

soffet:从文件开始检索到offset字节位置

rlength:在文件当前偏移量处,从文件中读取length字节数据,并以文本形式显式

Rlength:在当前文件偏移量处,从文件中读取length字节数据,并以十六进制形式显式

wstr:在当前文件偏移量处,由文件写入由str指定的字符串

 

#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
#include "get_num.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
        size_t  len;
        off_t offset;
        int fd, ap, j;
        char *buf;
        ssize_t numRead, numWritten;

  /* usage */
        if(argc < 3 || strcmp(argv[1], "--help") == 0)
                printf("%s file {r<length> | R<length> | w<string> | s<offset>} ...\n",
                                                 argv[0]);

        /* open or create file */
        fd = open(argv[1], O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
                                                S_IROTH | S_IWOTH);

        /* is system call success */
        if(fd == -1)
                printf("open file error\n");

        /* biz code */
        for(ap = 2; ap < argc; ap++) {
                switch(argv[ap][0]) {
                case r:                   /* Display bytes at current offset, as text */
                case R:                   /* Display bytes at current offset, in hex */
                        len = getLong(&argv[ap][1], GN_ANY_BASE, argv[ap]);

                /* alloc buffer */
                buf = malloc(len);

                /* is alloc success */
                if(buf == NULL)
                        printf("malloc error\n");

                numRead = read(fd, buf, len);
                if(numRead == -1)
                        /* read fail */
                        printf("read\n");

                /* end of file */
                if(numRead == 0)
                        printf("%s: end-of-file\n", argv[ap]);
                else {
                        printf("%s: ", argv[ap]);
                        for(j=0; j<numRead; j++)
                                if(argv[ap][0] == r)
                                        printf("%c", isprint((unsigned char) buf[j]) ? buf[j] : ?);
                                else
                                        printf("%O2x ", (unsigned int) buf[j]);
                        printf("\n");
                }

                /* free memory */
                free(buf);
                break;
                case w:                   /* Write string at current offset */
                        numWritten = write(fd, &argv[ap][1], strlen(&argv[ap][1]));
                        if(numWritten == -1)
                                printf("write error\n");
                        printf("%s: wrote %ld bytes\n", argv[ap], (long) numWritten);
                        break;
                case s:
                        offset = getLong(&argv[ap][1], GN_ANY_BASE, argv[ap]);
                        if(lseek(fd, offset, SEEK_SET) == -1)
                                printf("lseek error!\n");
                        printf("%s: seek successed\n", argv[ap]);
                        break;
                default:
                        printf("Argument must start with [rRws]: %s\n", argv[ap]);
                }
        }

        exit(0);
}

 

get_num.h

 

#ifndef GET_NUM_H
#define GET_NUM_H

#define GN_NONNEG          01   /* Value must be >= 0 */
#define GN_GT_0            02   /* Value must be > 0 */

                                /* By default, integers are decimal */
#define GN_ANY_BASE      0100   /* Can use any base - like strtol(3) */
#define GN_BASE_8        0200   /* Value is expressed in octal */
#define GN_BASE_16       0400   /* Value is expressed in hexadecimal */

long getLong(const char *arg, int flags, const char *name);

int getInt(const char *arg, int flags, const char *name);

#endif

get_num.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include "get_num.h"

static void gnFail(const char *fname, const char *msg, const char *arg,
                   const char *name) {
  fprintf(stderr, "%s error", fname);

  if (name != NULL)
    fprintf(stderr, " (in %s)", name);

  fprintf(stderr, ": %s\n", name);

  if(arg != NULL && *arg != \0)
    fprintf(stderr, "        offending text: %s\n", arg);

  exit(EXIT_FAILURE);
}

static long getNum(const char *fname, const char *arg, int flags,
                   const char *name)
{
  long res;
  char *endptr;
  int base;

  if(arg == NULL || *arg == \0)
    gnFail(fname, "null or empty string", arg, name);

  base = (flags & GN_ANY_BASE) ? 0 : (flags & GN_BASE_8) ? 8 :
    (flags & GN_BASE_16) ? 16 : 10;

  errno = 0;

  res = strtol(arg, &endptr, base);

  if(errno != 0)
    gnFail(fname, "strtol() failed", arg, name);

  if(*endptr != \0)
    gnFail(fname, "nonnumeric characters", arg, name);

  if((flags & GN_NONNEG) && res < 0)
    gnFail(fname, "negative value not allowed", arg, name);

  if((flags & GN_GT_0) && res <= 0)
    gnFail(fname, "value must be > 0", arg, name);

  return res;
}

long getLong(const char *arg, int flags, const char *name)
{
  return getNum("getLong", arg, flags, name);
}

int getInt(const char *arg, int flags, const char *name)
{
  long res;

  res = getNum("getInt", arg, flags, name);
  if(res > INT_MAX || res < INT_MIN)
    gnFail("getInt", "integer out of range", arg, name);

  return (int) res;
}

以上是关于Unix系统编程()open,read,write和lseek的综合练习的主要内容,如果未能解决你的问题,请参考以下文章

UNIX环境高级编程:文件I/O

UNIX环境高级编程之第3章:文件I/O

Unix系统编程

Unix系统编程通用的I/O

缓冲文件系统(fopen/fread/fwrite)和非缓冲文件系统(open/read/write)

缓冲文件系统(fopen/fread/fwrite)和非缓冲文件系统(open/read/write)