题目:本设计使用C语言模拟一个单用户的二级文件管理系统,支持文件与目录的创建、删除、读写等操作,并实现文件的物理存储与目录管理。
实现要求:
(1)在磁盘上建立一个文件模拟磁盘分区。
(2)空闲空间管理可使用位示图,存储分配可采用链接等方法。
(3)支持一级或二级目录结构,每项含文件名、地址、长度等。
(4)支持命令操作:login、dir、create、delete、open、close、read、write、exit
(5)可扩展实现文件夹的增删功能(可部分实现)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_BLOCKS 1024 // 磁盘总块数
#define BLOCK_SIZE 512 // 块大小
#define DISK_FILE "disk.bin"// 虚拟磁盘文件名
#define MAX_FILES 100 // 最大文件数
#define MAX_OPEN_FILES 10 // 最多打开文件数
// 文件控制块 FCB
typedef struct {
char name[64]; // 文件名
int start_block; // 起始块号
int length; // 占用块数
} FileControlBlock;
// 全局变量
FileControlBlock root_dir[MAX_FILES]; // 根目录表
int bitmap[MAX_BLOCKS] = {0}; // 位示图
FILE *disk_file; // 磁盘文件指针
int logged_in = 0; // 登录状态
int open_files[MAX_OPEN_FILES][2]; // [fd][index, pos]
// 初始化磁盘
void init_disk() {
disk_file = fopen(DISK_FILE, "rb+");
if (!disk_file) {
disk_file = fopen(DISK_FILE, "wb+");
char zero[BLOCK_SIZE] = {0};
for (int i = 0; i < MAX_BLOCKS; ++i)
fwrite(zero, BLOCK_SIZE, 1, disk_file);
}
}
// 初始化根目录
void init_root_directory() {
for (int i = 0; i < MAX_FILES; ++i) {
root_dir[i].name[0] = '\0';
root_dir[i].start_block = -1;
root_dir[i].length = 0;
}
for (int i = 0; i < MAX_OPEN_FILES; ++i)
open_files[i][0] = open_files[i][1] = -1;
}
// 读取一个块
void read_block(int block_num, void* buffer) {
fseek(disk_file, block_num * BLOCK_SIZE, SEEK_SET);
fread(buffer, BLOCK_SIZE, 1, disk_file);
}
// 写入一个块
void write_block(int block_num, const void* buffer) {
fseek(disk_file, block_num * BLOCK_SIZE, SEEK_SET);
fwrite(buffer, BLOCK_SIZE, 1, disk_file);
}
// 分配一个空闲块
int allocate_block() {
for (int i = 0; i < MAX_BLOCKS; ++i) {
if (!bitmap[i]) {
bitmap[i] = 1;
return i;
}
}
return -1;
}
// 释放一个块
void free_block(int block_num) {
if (block_num >= 0 && block_num < MAX_BLOCKS)
bitmap[block_num] = 0;
}
// 查找文件是否存在
int find_file(const char* filename) {
for (int i = 0; i < MAX_FILES; ++i) {
if (root_dir[i].start_block != -1 &&
strcmp(root_dir[i].name, filename) == 0)
return i;
}
return -1;
}
// 获取一个可用的 fd
int get_free_fd() {
for (int i = 0; i < MAX_OPEN_FILES; ++i)
if (open_files[i][0] == -1)
return i;
return -1;
}
// login 命令
void cmd_login() {
if (logged_in) {
printf("Already logged in.\n");
return;
}
printf("Login successful.\n");
logged_in = 1;
}
// dir 命令
void cmd_dir() {
if (!logged_in) {
printf("Please login first.\n");
return;
}
printf("Directory:\n");
for (int i = 0; i < MAX_FILES; ++i) {
if (root_dir[i].start_block != -1 && root_dir[i].name[0] != '\0')
printf("- %s (%d blocks)\n", root_dir[i].name, root_dir[i].length);
}
}
// create 命令
void cmd_create(const char* filename) {
if (!logged_in) {
printf("Please login first.\n");
return;
}
if (find_file(filename) != -1) {
printf("File already exists.\n");
return;
}
int index = -1;
for (int i = 0; i < MAX_FILES; ++i) {
if (root_dir[i].start_block == -1) {
index = i;
break;
}
}
if (index == -1) {
printf("Directory full.\n");
return;
}
int block = allocate_block();
if (block == -1) {
printf("Disk full.\n");
return;
}
strcpy(root_dir[index].name, filename);
root_dir[index].start_block = block;
root_dir[index].length = 1;
char zero[BLOCK_SIZE] = {0};
write_block(block, zero);
printf("File created: %s\n", filename);
}
// delete 命令
void cmd_delete(const char* filename) {
if (!logged_in) {
printf("Please login first.\n");
return;
}
int index = find_file(filename);
if (index == -1) {
printf("File not found.\n");
return;
}
FileControlBlock fcb = root_dir[index];
for (int i = 0; i < fcb.length; ++i)
free_block(fcb.start_block + i);
root_dir[index].start_block = -1;
root_dir[index].length = 0;
root_dir[index].name[0] = '\0';
printf("File deleted: %s\n", filename);
}
// open 命令
void cmd_open(const char* filename) {
if (!logged_in) {
printf("Please login first.\n");
return;
}
int index = find_file(filename);
if (index == -1) {
printf("File not found.\n");
return;
}
int fd = get_free_fd();
if (fd == -1) {
printf("Too many open files.\n");
return;
}
open_files[fd][0] = index;
open_files[fd][1] = 0;
printf("File opened with fd=%d\n", fd);
}
// close 命令
void cmd_close(int fd) {
if (fd < 0 || fd >= MAX_OPEN_FILES || open_files[fd][0] == -1) {
printf("Invalid file descriptor.\n");
return;
}
open_files[fd][0] = -1;
printf("File closed.\n");
}
// seek 命令
void cmd_seek(int fd, int offset) {
if (fd < 0 || fd >= MAX_OPEN_FILES || open_files[fd][0] == -1) {
printf("Invalid file descriptor.\n");
return;
}
open_files[fd][1] = offset;
printf("File pointer set to %d\n", offset);
}
// read 命令
void cmd_read(int fd, int size) {
if (fd < 0 || fd >= MAX_OPEN_FILES || open_files[fd][0] == -1) {
printf("Invalid file descriptor.\n");
return;
}
int index = open_files[fd][0];
int pos = open_files[fd][1];
FileControlBlock fcb = root_dir[index];
char result[size + 1];
memset(result, 0, sizeof(result));
int total_read = 0;
int current_block = pos / BLOCK_SIZE;
int offset = pos % BLOCK_SIZE;
while (total_read < size && current_block < fcb.length) {
char buffer[BLOCK_SIZE];
read_block(fcb.start_block + current_block, buffer);
int available = BLOCK_SIZE - offset;
int to_copy = (available < size - total_read) ? available : (size - total_read);
memcpy(result + total_read, buffer + offset, to_copy);
total_read += to_copy;
current_block++;
offset = 0;
}
result[total_read] = '\0';
open_files[fd][1] = pos + total_read;
printf("Read: %s\n", result);
}
// write 命令
void cmd_write(int fd, const char* data) {
if (fd < 0 || fd >= MAX_OPEN_FILES || open_files[fd][0] == -1) {
printf("Invalid file descriptor.\n");
return;
}
int index = open_files[fd][0];
int pos = open_files[fd][1];
FileControlBlock* fcb = &root_dir[index];
int len = strlen(data);
int written = 0;
while (written < len) {
int block_index = pos / BLOCK_SIZE;
int offset = pos % BLOCK_SIZE;
if (block_index >= fcb->length) {
int new_block = allocate_block();
if (new_block == -1) {
printf("Disk full. Cannot write more.\n");
break;
}
fcb->length++;
write_block(new_block, "\0\0\0");
}
char buffer[BLOCK_SIZE];
int block = fcb->start_block + block_index;
read_block(block, buffer);
int space = BLOCK_SIZE - offset;
int to_write = (len - written < space) ? len - written : space;
memcpy(buffer + offset, data + written, to_write);
write_block(block, buffer);
written += to_write;
pos += to_write;
}
open_files[fd][1] = pos;
printf("Written %d bytes.\n", written);
}
// 主函数
int main() {
init_disk();
init_root_directory();
char line[256], cmd[64];
while (1) {
printf("> ");
if (!fgets(line, sizeof(line), stdin)) break;
sscanf(line, "%s", cmd);
if (strcmp(cmd, "login") == 0) {
cmd_login();
} else if (strcmp(cmd, "dir") == 0) {
cmd_dir();
} else if (strcmp(cmd, "create") == 0) {
char filename[64];
sscanf(line, "%*s %s", filename);
cmd_create(filename);
} else if (strcmp(cmd, "delete") == 0) {
char filename[64];
sscanf(line, "%*s %s", filename);
cmd_delete(filename);
} else if (strcmp(cmd, "open") == 0) {
char filename[64];
sscanf(line, "%*s %s", filename);
cmd_open(filename);
} else if (strcmp(cmd, "close") == 0) {
int fd;
sscanf(line, "%*s %d", &fd);
cmd_close(fd);
} else if (strcmp(cmd, "read") == 0) {
int fd, size;
sscanf(line, "%*s %d %d", &fd, &size);
cmd_read(fd, size);
} else if (strcmp(cmd, "write") == 0) {
int fd;
char data[256];
sscanf(line, "%*s %d %[^\n]", &fd, data);
cmd_write(fd, data);
} else if (strcmp(cmd, "seek") == 0) {
int fd, offset;
sscanf(line, "%*s %d %d", &fd, &offset);
cmd_seek(fd, offset);
} else if (strcmp(cmd, "exit") == 0) {
break;
} else {
printf("Unknown command.\n");
}
}
fclose(disk_file);
return 0;
}
这段代码的运行结果如下
> login
Login successful.
> create a.txt
File created: a.txt
> open a.txt
File opened with fd=0
> write 0 1
Written 1 bytes.
> read 0 1
Read:
> delete a.txt
File deleted: a.txt
>
请修复代码中的错误
最新发布