Read 23 byte data:HelloWorld
HelloMaQian


## 四、关于lseek

lseek用于设置文件指针的位置,同时也可以查看当前指针所处的位置。

如果设置的文件指针超过了文件范围,系统将会给文件申请更多的内存空间来存储这些超出的文件数据,但这要求系统要在指针所指向的位置进行一次写操作。

include "apue.h"

include <fcntl.h>

int main() {

int fd, ret;

const char *s1 = "abcdefghij";
const char *s2 = "ABCDEFGHIJ";

fd = open("test.hole", O_WRONLY | O_CREAT | O_TRUNC, 0755);
if (-1 == fd)
    err_sys("open file error");

if (write(fd, s1, 10) != 10)
    err_sys("write s1 error");
if ((ret = lseek(fd, 0, SEEK_CUR)) < 0)
    err_sys("lseek error");
printf("localtion: %d\n", ret); // 打印当前的指针位置 10

if ((ret = lseek(fd, 1000, SEEK_SET)) < 0)
    err_sys("lseek error");
printf("localtion: %d\n", ret); // 移动后的位置 1000

if (write(fd, s2, 10) != 10)
    err_sys("write s2 error");
close(fd);
return 0;

}


运行程序后输出:
./a.out
localtion: 10
localtion: 1000
ll test.hole
-rwxr-xr-x 1 ma ma 1010 May 18 11:18 test.hole # 文件大小1010字节

### 4.1 使用lseek生成指定大小的文件

根据上面所描述的`lseek`的特性,文件指针超出时会自动申请空间,因此我们可以通过它来生成一个指定大小的文件。

include "apue.h"

include <fcntl.h>

const int BT_SIZE = 1;
const int KB_SIZE = 1 << 10;
const int MB_SIZE = 1 << 20;
const int GB_SIZE = 1 << 30;

/*

  • 解析输入的文件大小
  • @size 大小字符串1g, 1m, 1k, 1
  • @return 返回解析好的字节数
  • 失败直接退出程序
    */

int parser_size(const char *size)
{

int i = 0, n = 0;
char ch; // 遍历每一个字符
while ((ch = size[i]))
{
    if ((''a'' <= ch && ch <= ''z'') || (''A'' <= ch && ch <= ''Z''))
    {
        if(size[i + 1])
            err_quit("invalid input: %s", size);
        switch (ch)
        {
        case ''b'':
        case ''B'':
            return BT_SIZE * n;
        case ''k'':
        case ''K'':
            return KB_SIZE * n;
        case ''m'':
        case ''M'':
            return MB_SIZE * n;
        case ''g'':
        case ''G'':
            return GB_SIZE * n;
        default:
            err_quit("invalid input: %c", ch);
        }
    }
    else if (''0'' <= ch && ch <= ''9'')
    {
        n = 10 * n + ch - ''0'';
    }
    else
    {
        err_quit("invalid input: %s", size);
    }
    i++;
}
return n;

}

int main(int argc, char **argv)
{

if (argc < 3)
    err_quit("Usage: ./mkfile filename size");

int sz = parser_size(argv[2]);

int fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0755);
if (-1 == fd)
    err_sys("crate file error");

// 移动到指定位置的前一个字节
if (-1 == lseek(fd, sz - 1, SEEK_SET))
    err_sys("create file error");

// 写入一个字节申请内存块
if (1 != write(fd, " ", 1))
    err_sys("write data error");

close(fd);
return 0;

}


根据输入即可生成指定大小的文件:
mkdir debug && gcc main.c /apue.* -o debug/app
./debug/app test1 1g
./debug/app test2 2m
./debug/app test3 3k
./debug/app test4 4
ll
total 32K
drwxrwxr-x 2 ma ma 4.0K May 18 14:40 debug
-rw-rw-r-- 1 ma ma 1.7K May 18 14:39 main.c
-rw-rw-r-- 1 ma ma 1.7K May 18 14:35 main.c.orig
-rw-rw-r-- 1 ma ma 311 May 18 14:22 Makefile
-rwxr-xr-x 1 ma ma 1.0G May 18 14:41 test1
-rwxr-xr-x 1 ma ma 2.0M May 18 14:41 test2
-rwxr-xr-x 1 ma ma 3.0K May 18 14:41 test3
-rwxr-xr-x 1 ma ma 4 May 18 14:41 test4

不过对于文件的大小有个限制,文件最多只能`2G+`,因为此时计算出来的`sz`大小会溢出。
最后修改:2017 年 11 月 25 日
如果觉得我的文章对你有用,请随意赞赏