C创建具有给定大小的文件

时间:2014-12-31 01:00:13

标签: c++ c linux

我正在尝试使用lseek()创建一个具有给定大小的文件,并在文件末尾添加一个字节,但是它会创建一个0字节的稀疏文件。

以下是代码......有什么建议吗?

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

#ifndef BUF_SIZE
#define BUF_SIZE 1024
#endif // BUF_SIZE

int main(int argc, char *argv[])
{
    int inputFd;
    int fileSize = 500000000;
    int openFlags;
    int result;

    mode_t filePerms;
    ssize_t numRead;
    char buf[BUF_SIZE];

    openFlags = O_WRONLY | O_CREAT | O_EXCL;
    filePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; /*rw-rw-ew*/

    inputFd = open(argv[1], openFlags, filePerms);
    if (inputFd == -1)
        printf("problem opening file %s ", argv[1]);
        return 1;
    printf ("input FD: %d", inputFd);


    result = lseek(inputFd, fileSize-1, SEEK_SET);
    if (result == -1){
        close(inputFd);
        printf("Error calling lseek() to stretch the file");
        return 1;
    }

    result = write(inputFd, "", 1);
    if (result < 0){
        close(inputFd);
        printf("Error writing a byte at the end of file\n");
        return 1;

    }

    if (close(inputFd) == -1)
        printf("problem closing file %s \n",argv[1]);

    return 0;
}

2 个答案:

答案 0 :(得分:5)

你缺少一些大括号:

if (inputFd == -1)
    printf("problem opening file %s ", argv[1]);
    return 1;

您需要将其更改为:

if (inputFd == -1) {
    printf("problem opening file %s ", argv[1]);
    return 1;
}

没有大括号,if语句控制的唯一语句是printf,无论return 1;的值是什么,inputFd语句总是运行

优点是总是在受控块周围使用大括号,即使只有一个语句(例如程序末尾的close)。

答案 1 :(得分:0)

  

你有任何在文件的每个块上写一个字节的例子吗?

此代码来自略有不同的上下文,但可以根据您的情况进行调整。上下文是确保Informix数据库的磁盘空间全部被分配,因此围绕它的包装器代码创建了文件(并且它不存在等)。但是,实际写入的入口点是这两个函数中的第二个 - 填充缓冲区函数将8字节字informix复制到64 KiB块中。

/* Fill the given buffer with the string 'informix' repeatedly */
static void fill_buffer(char *buffer, size_t buflen)
{
    size_t filled = sizeof("informix") - 1;

    assert(buflen > filled);
    memmove(buffer, "informix", sizeof("informix")-1);
    while (filled < buflen)
    {
        size_t ncopy = (filled > buflen - filled) ? buflen - filled : filled;
        memmove(&buffer[filled], buffer, ncopy);
        filled *= 2;
    }
}

/* Ensure the file is of the required size by writing to it */
static void write_file(int fd, size_t req_size)
{
    char buffer[64*1024];
    size_t nbytes = (req_size > sizeof(buffer)) ? sizeof(buffer) : req_size;
    size_t filesize = 0;

    fill_buffer(buffer, nbytes);

    while (filesize < req_size)
    {
        size_t to_write = nbytes;
        ssize_t written;
        if (to_write > req_size - filesize)
            to_write = req_size - filesize;
        if ((written = write(fd, buffer, to_write)) != (ssize_t)to_write)
            err_syserr("short write (%d vs %u requested)\n",
                        (int)written, (unsigned)to_write);
        filesize += to_write;
    }
}

正如您所看到的,它写入64 KiB块。坦率地说,在页面上写入所有字节和每页写入一个字节之间没有区别。实际上,如果有的话,编写整个页面会更快,因为可以简单地编写新值,而如果每页只写一个字节,则必须创建/读取,修改旧页面,然后再写回。

在您的上下文中,我会将当前文件扩展为4 KiB的倍数(如果您愿意,则为8 KiB),然后编写主数据块,并在必要时写入最终的部分块。你可能只是做memset(buffer, '\0', sizeof(buffer));而示例代码是故意编写除零字节块之外的东西。 AFAIK,即使您编写的块都是零字节,驱动程序实际上会将该块写入磁盘 - 简单的写入操作可确保文件非稀疏。

err_syserr()函数有点像fprintf(stderr, …),但它会添加来自errnostrerror()的系统错误消息,并退出程序。代码确实假设32位(或更大)int值。我从未尝试过使用TB级文件 - 该代码最后一次更新于2009年。