使用C将数组写入文件

时间:2016-12-03 22:31:02

标签: c arrays

我正在创建一个Unix v6文件系统的模型。我试图首先通过将可用的空闲块写入文件然后在需要时读取它来分配它们。我有一个100块的自由数组,所以当空闲块的数量超过100时,当前的空闲数组将被写入free [0]中的内存块,新的空闲块将被分配给free [0] 。以下是我编写的示例代码

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

void splitCommand(char**,char*, char*);
unsigned short freeArr[100];
unsigned short nfree=1,fd;
int main()
{

    fd = open("v6", O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IEXEC | S_IWRITE);
    freeArr[0] = 0;
    for (int i = 28; i < 5000; i++)
    {
        addFreeBlock(i);
    }

    unsigned short free1=0  ;
    lseek(fd, 3127 * 512, SEEK_SET);
    read(fd, &(nfree), sizeof(unsigned short));
    printf("%d\n",nfree);
    for(int i=0; i<nfree; i++)
    {
        read(fd, &free1, sizeof(unsigned short));
        printf("%d\n",free1);
    }
}

void addFreeBlock(int block_no)
{
    if(block_no==3127)
    {
        int a=0;
    }

    if (nfree == 100)
    {
        lseek(fd, block_no * 512, SEEK_SET);
        write(fd, &(nfree), sizeof(unsigned short)); // copy nfree into free array
        write(fd, freeArr, 200);// copy free array
        nfree=0;
    }
    freeArr[nfree] = block_no;
    nfree++;
}

考虑我们共有5000个街区。每个块长512个字节。我使用前27个块用于其他目的,所以我写的块从28到5000。

现在写完所有块之后,我尝试读取存储在随机位置的块。当我尝试读取存储在3027的块时,我能够读取编号为2927,2928,2929,....,3026的100个块。但是当我读取存储在3127的块时,我只能读取3027,3028,3029,....,3081中的块。剩下的只是随机的。我也试过其他一些职位。它适用于其中一些。

谁能告诉我哪里出错了?

1 个答案:

答案 0 :(得分:1)

对不起,这不是一个真正的答案,但我不能在评论中写这个。然而它确实以某种方式回答了这个问题。

您的代码正常运行,我使用valgrind进行了测试,并且没有错误,但您应该考虑很多。

您的代码中不需要单个全局变量,当您真的知道没有更好的解决方案时,您应该只使用全局变量,这是您确切代码的改进版本,

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

uint16_t add_free_block(int fd, int block_number, uint16_t *free_blocks, uint16_t free_block_count);

int main(void)
{
    uint16_t free_blocks[100];
    uint16_t free_block_count;
    int fd;

    fd = open("v6", O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IEXEC | S_IWRITE);
    if (fd == -1)
        return -1;
    free_blocks[0] = 0;

    free_block_count = 1;
    for (int i = 28; i < 5000; i++) {
        free_block_count = add_free_block(fd, i, free_blocks, free_block_count);
    }

    lseek(fd, 3127 * 512, SEEK_SET);
    read(fd, &free_block_count, sizeof(uint16_t));

    printf("%d\n", free_block_count);
    for (int i = 0; i < free_block_count; i++) {
        uint16_t block_number;        
        if (read(fd, &block_number, sizeof(uint16_t)) == sizeof(uint16_t)) {
            printf("%d\n", block_number);
        }
    }
    close(fd);
    return 0;
}

uint16_t 
add_free_block(int fd, int block_number, uint16_t *free_blocks, uint16_t free_block_count)
{
    if (free_block_count == 100) {
        lseek(fd, block_number * 512, SEEK_SET);

        write(fd, &free_block_count, sizeof(uint16_t));
        write(fd, free_blocks, free_block_count * sizeof(uint16_t));

        free_block_count = 0;
    }
    free_blocks[free_block_count] = block_number;

    return free_block_count + 1;
}

使用 0 全局变量(同样,次要但重要的是我关闭了文件描述符)。

您还应该检查其他返回值,例如write(),我没有,因为我不想这么做,我只是想检查一下是什么问题。

真正的问题在于程序其余部分的其他地方,而不是在此代码中。所以请发布实际代码并停止猜测问题是什么。

一般来说,这些是我的建议

  1. 不要使用全局变量,除非你非常非常确定你必须。
  2. 添加函数原型。
  3. 不要忽略编译器警告。
  4. 总是检查确实返回的函数的返回值,如果你不知道它确实返回,则为5。
  5. 仔细阅读您使用的每个功能的所有文档。