我是 C 新手,習慣于 python。但由于目前的世界形勢,我的主電腦被毀壞了,我只剩下 12 歲的筆記本電腦。Python 在那里不能很好地作業。
我的目標是創建加密演算法。 目前它相當簡單,但我稍后會升級它
如何分塊讀取檔案并覆寫其資料? 這是我的代碼:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned char byte;
void printa(byte a[]) {
printf("[");
for (int i = 0; i < strlen(a); i ) {
printf("%d", a[i]);
if (i != strlen(a) - 1) {
printf(", ");
};
};
printf("]\n");
};
int encrypt(byte data[], byte key[], int keyi) {
for (int i = 0; i < strlen(data); i ) {
data[i] = key[keyi];
keyi = (keyi 1) * (keyi < strlen(key) - 1); //branchless if (keyi<strlen(key)) {keyi ;} else {keyi=0;};
};
return keyi;
};
void encrypt_file(byte filename[], byte key[], int buffer_size) {
FILE *file;
byte *buff = calloc(sizeof(byte), buffer_size);
file = fopen(filename, "rb");
if (file == NULL) {
printf("UNABLE TO OPEN FILE\n");
};
};
int main() {
encrypt_file("test.txt", "key", 1024);
return 0;
};
我的檔案大小約為 2GB,但我的筆記本電腦記憶體為 512MB,所以我必須使用分塊。
uj5u.com熱心網友回復:
要以塊為單位加密檔案,您應該使用fread
和fwrite
。
keyi
要在鍵的末尾重置鍵索引,將其與 進行比較strlen(key) - 1
可能非常低效,因為strlen()
迭代整個字串以定位空終止符。只需測驗是否key[keyi]
為空位元組。
也不必擔心無分支代碼:
- 任何好的編譯器都會為簡單的測驗生成無分支代碼
if (key[keyi] == '\0') keyi = 0;
- 分支在現代處理器上并不是一個真正的問題,只要它們可以被一致地預測。
這是修改后的版本:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned char byte;
int encrypt(byte data[], size_t size, const byte key[], int keyi) {
for (size_t i = 0; i < size; i ) {
data[i] ^= key[keyi ]; // involutory encryption (apply twice to decrypt)
if (key[keyi] == '\0')
keyi = 0;
}
return keyi;
}
int encrypt_file(const char *filename, const char *filename2,
const byte key[], size_t buffer_size)
{
byte *buff = calloc(sizeof(*buff), buffer_size);
if (buff == NULL) {
fprintf(stderr, "Cannot allocate memory\n");
return 1;
}
FILE *f1 = fopen(filename, "rb");
if (f1 == NULL) {
fprintf(stderr, "Cannot open file %s: %s\n", filename, strerror(errno));
free(buff);
return 1;
}
FILE *f2 = fopen(filename2, "wb");
if (f2 == NULL) {
fprintf(stderr, "Cannot open file %s: %s\n", filename2, strerror(errno));
fclose(f1);
free(buff);
return 1;
}
size_t nread;
int keyi = 0;
while ((nread = fread(buff, sizeof(*buff), size, f1)) != 0) {
keyi = encrypt(buff, nread, key, keyi);
if (fwrite(buff, sizeof(*buff), nread, f2) != nread) {
fprintf(stderr, "Error writing to file %s: %s\n", filename2, strerror(errno));
break;
}
}
fclose(f1);
fclose(f2);
free(buff);
return 0;
}
int main() {
return encrypt_file("test.txt", "test.out", (const byte *)"key", 1024);
}
您可以修改程式以就地加密檔案,但請注意,如果行程中斷,部分加密的檔案將難以恢復。您還應該嘗試保留檔案修改時間。一種更安全的方法是使用適當的工具對磁區進行加密,其中一些工具支持隱藏磁區和合理的可否認性。
uj5u.com熱心網友回復:
您想使用fread
and fwrite
,將您的buff
as ptr、sizeof byte
size 和buffer_size
nmemb 傳遞給您。
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb,
FILE *stream);
uj5u.com熱心網友回復:
如何分塊讀取檔案并覆寫其資料?
首先,如果你想同時讀取和寫入同一個檔案預先存在的檔案,就地,然后在 mode 中打開它rb
。您當前使用的Moderb
不允許寫入。
其次,分塊讀寫二進制資料正是標準fread()
和fwrite()
函式的作用。
您還需要重新定位檔案指標以覆寫您剛剛讀取的資料。為此,有ftell()
和fseek()
或fgetpos()
和fsetpos()
。但是,我建議通過將輸出寫入不同的檔案來避免這種情況,并且(僅)在新檔案完全寫入并關閉之后,用它替換原始檔案。這避免了在行程在中間失敗的情況下留下部分加密檔案的可能性。
不要忽視所有這些函式的回傳值,因為它們會在發生錯誤時報告。但是您絕對必須注意 的回傳值fread()
,因為它還會報告實際讀取的資料量。對于您處理的每個長度不是所選塊大小的精確倍數的檔案,這至少會很重要。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/493608.html