分布式冗余存储系统,MATLAB R2023b,Matlab版
主函数
while true
fprintf('这是一个文件存储的程序:\n');
fprintf('存文件输入1,取文件输入2,查看输入3,删除输入4, 退出程序输入0\n');
choice = input('您想进行什么操作? ');
switch choice
case 0
fprintf('下次再见!\n');
return;
case 1
storage();
case 2
read();
case 3
look();
case 4
dismiss();
otherwise
fprintf('不是哥们\n');
fprintf('存文件输入1,取文件输入2,查看输入3,删除输入4, 退出程序输入0\n');
end
end
存储模块
function storage()
% Load or initialize .mat data
data = load_mat('save.mat');
% Input disk locations
disk0 = input('请确定存储位置(1/3),以斜杠结尾:', 's');
disk1 = input('请确定存储位置(2/3),以斜杠结尾:', 's');
disk2 = input('请确定存储位置(3/3),以斜杠结尾:', 's');
while true
file_location = input('输入文件地址(输入#退出): ', 's');
if strcmp(file_location, '#')
break;
end
if ~exist(file_location, 'file')
disp('文件不存在,请重试!');
continue;
end
% Get file suffix and size
[~, filename, ext] = fileparts(file_location);
suffix = ext;
file_size = dir(file_location).bytes;
disp(['文件后缀名为: ', suffix]);
disp(['文件大小为: ', num2str(file_size), ' 字节']);
% Open the file to split it into chunks
fid = fopen(file_location, 'rb');
buffer_size = 16 * 1024 * 1024; % 16 MB
num_chunks = ceil(file_size / buffer_size);
big_file = struct(); % Structure to store file chunk paths
big_file.original_path = file_location; % Store the original path
for i = 1:num_chunks
chunk_size = buffer_size;
if i == num_chunks
chunk_size = file_size - (num_chunks - 1) * buffer_size;
end
buffer = fread(fid, chunk_size, '*uint8');
% Get two random storage locations for redundancy, pass data to confirm_location
[c, d] = confirm_location(suffix, disk0, disk1, disk2, data);
% Save buffer to the two locations
fid_c = fopen(c, 'wb');
fwrite(fid_c, buffer, 'uint8');
fclose(fid_c);
fid_d = fopen(d, 'wb');
fwrite(fid_d, buffer, 'uint8');
fclose(fid_d);
% Save chunk file paths in metadata
big_file.(sprintf('chunk_%d', i)) = {c, d};
end
fclose(fid);
% Save file chunk metadata into the data structure
valid_name = matlab.lang.makeValidName(file_location);
data.(valid_name) = big_file;
% Save updated data to .mat file
save_mat('save.mat', data);
disp('存储成功!');
end
end
function [location_str1, location_str2] = confirm_location(input_str, disk0, disk1, disk2, data)
locations = {disk0, disk1, disk2};
selected_locs = randperm(3, 2); % Randomly select two locations
% Generate a unique filename using the input data
file_name = generate_unique_random(data, input_str);
% Create the full paths for the two selected locations
location_str1 = fullfile(locations{selected_locs(1)}, file_name);
location_str2 = fullfile(locations{selected_locs(2)}, file_name);
end
function file_name = generate_unique_random(data, suffix)
while true
% Generate a random number and convert to string
file_name = num2str(randi([0, 2023011000]));
% Check if this file name is already used in the data structure
is_unique = true;
for k = fieldnames(data)'
if ~isempty(data.(k{:}).original_path)%对于每个字段,检查其 original_path 是否非空。如果非空,则进一步检查该字段下所有以 chunk_ 开头的子字段
chunk_fields = fieldnames(data.(k{:}));
for i = 1:numel(chunk_fields)
if startsWith(chunk_fields{i}, 'chunk_') % Use MATLAB's built-in startsWith
chunk_paths = data.(k{:}).(chunk_fields{i});
for j = 1:numel(chunk_paths)
% Extract the base file name from the path
[~, base_name, ~] = fileparts(chunk_paths{j});
% Compare the base file name without the extension
if strcmp(base_name, file_name)
is_unique = false;
break;
end
end
if ~is_unique
break;
end
end
end
if ~is_unique
break;
end
end
end
% If unique, append the suffix and break the loop
if is_unique
file_name = [file_name, suffix];
break;
end
end
end
function data = load_mat(filename)
if exist(filename, 'file')
data = load(filename);
else
data = struct();
end
end
function save_mat(filename, data)
save(filename, '-struct', 'data');
end
恢复模块
function read()
if exist('save.mat', 'file')
data = load('save.mat');
else
disp('这里什么也没有');
return;
end
while true
file_location = input('请输入要恢复的文件原始地址,输入#结束恢复操作:', 's');
if strcmp(file_location, '#')
break;
end
valid_name = matlab.lang.makeValidName(file_location);
if ~isfield(data, valid_name)
disp(['文件 ', file_location, ' 无法在记录中找到']);
continue;
end
save_location = input('请输入恢复文件存储位置,以斜杠结尾:', 's');
full_save_path = fullfile(save_location, get_filename_from_path(file_location));
% 打开输出文件以恢复数据
fid_out = fopen(full_save_path, 'wb');
file_data = data.(valid_name);
% 恢复文件的每个块
chunk_names = fieldnames(file_data);
for i = 1:length(chunk_names)
if strcmp(chunk_names{i}, 'original_path')
continue; % 跳过 original_path 字段
end
chunk_paths = file_data.(chunk_names{i});
for j = 1:length(chunk_paths)
chunk_path = chunk_paths{j};
if exist(chunk_path, 'file')
fid_in = fopen(chunk_path, 'rb');
buffer = fread(fid_in, '*uint8');
fwrite(fid_out, buffer, 'uint8');
fclose(fid_in);
break; % 只恢复每个块的一个有效副本
else
disp(['小文件 ', chunk_path, ' 找不到了,已跳过']);
end
end
end
fclose(fid_out);
disp(['文件 ', file_location, ' 已保存至 ', save_location, '.']);
end
end
function filename = get_filename_from_path(filepath)
[~, filename, ext] = fileparts(filepath);
filename = [filename, ext];
end
查看模块
function look()
% Load .mat data
data = load_mat('save.mat');
if isempty(data)
disp('这里什么也没有');
return;
end
% Display stored files
disp('已存储的文件有:');
file_names = fieldnames(data);
for i = 1:length(file_names)
% Replace underscores back to original characters like slashes
original_path = data.(file_names{i}).original_path;
disp(original_path);
end
end
function data = load_mat(filename)
if exist(filename, 'file')
data = load(filename);
else
data = struct();
end
end
function save_mat(filename, data)
save(filename, '-struct', 'data');
end
删除模块
function dismiss()
if exist('save.mat', 'file')
data = load('save.mat');
else
disp('这里什么也没有');
return;
end
while true
file_location = input('请输入要删除的文件原始地址,输入#结束:', 's');
if strcmp(file_location, '#')
break;
end
valid_name = matlab.lang.makeValidName(file_location);
if ~isfield(data, valid_name)
disp(['文件 ', file_location, ' 没有记录']);
continue;
end
file_data = data.(valid_name);
% 删除文件块
chunk_names = fieldnames(file_data);
for i = 1:length(chunk_names)
if strcmp(chunk_names{i}, 'original_path')
continue; % 跳过 original_path 字段
end
chunk_paths = file_data.(chunk_names{i});
for j = 1:length(chunk_paths)
path = chunk_paths{j};
if exist(path, 'file')
delete(path);
disp(['删除 ', path]);
else
disp([path, ' 没找到,跳过']);
end
end
end
% 从数据中删除此文件
data = rmfield(data, valid_name);
% 保存更新后的数据
save('save.mat', '-struct', 'data');
disp(['文件 ', file_location, ' 已从记录里清除.']);
end
end