Я разрабатываю linux-программу, которая должна анализировать файл, загруженный с другого компьютера или Интернета, и собирать информацию из этого файла. Программа также должна перезагружать файл по рутине, каждые n дней/часов/минут/независимо, и анализировать его снова, чтобы обновляться, если файл был изменен.
Однако для процесса разбора файла может потребоваться много ресурсов. Таким образом, я хотел бы, чтобы функция проверяла, изменился ли файл с момента последнего его загрузки. Я представляю что-то вроде этого примера:
int get_checksum(char *filename) {
// New prototype, if no such function already exists in standard C-libraries
int result; // Or char/float/whatever
// ...
return result;
}
int main(void) {
char filename[] = { "foo.dat" };
char file_url[] = { "http://example.com/foo.dat" }
int old_checksum; // Or char/float/whatever
int new_checksum; // Or char/float/whatever
// ...
// Now assume that old_checksum has a value from before:
dl_file(filename, file_url); // Some prototype for downloading the file
if ((new_checksum = get_checksum(filename)) == -1) {
// Badness
}
else {
if (new_checksum != old_checksum) {
old_checksum = new_checksum;
// Parse the file
}
else {
// Do nothing
}
}
// ...
}
Q1: Есть ли такая функция, как get_checksum
(из приведенного выше примера), доступная в стандартных библиотеках C/C++?
Q2: Если нет: что является лучшим способом для достижения этой цели?
Нет необходимости:
- очень продвинутая функция
- зашифрованные или защищенные контрольные суммы
- возможность сравнивать новый файл с файлами старше последнего, так как новый загруженный файл всегда будет перезаписывать более старый
Вы можете сделать хэш XOR, в котором вы просто xor последовательных блоков unsigned ints/longs, но это имеет проблемы с коллизиями. Например, если файл является главным образом символами, то большинство байтов будет в диапазоне обычных символов ASCII/Unicode, поэтому будет много неиспользуемого пространства ключей.
Для стандартной реализации вы можете прочитать файл в строке и использовать std :: hash из С++ 11. http://en.cppreference.com/w/cpp/utility/hash
Ниже приведен пример первого метода:
unsigned int hash(vector<char> file){
unsigned int result;
int *arr = (int*)file.data();
for(int i = 0;i < file.size() / sizeof(unsigned int);i++)
result ^= arr[i];
return result;
}
Вам просто нужно прочитать файл в векторе.
std::hash<string>
.
На языке C++ ничего не было создано до тех пор, пока std :: hash <> в C++ 11 не будет очень простым, но может быть уместным для ваших нужд.
Последнее, что я проверил, ничего не существует в Boost (наиболее распространенное расширение библиотеки C++). Обоснование здесь обсуждается, но может быть датировано:
http://www.gamedev.net/topic/528553-why-doesnt-boost-have-a-cryptographic-hash-library/
Итак, лучше всего:
std :: hash с содержимым файла.
Или что-то вроде следующего может быть полезно сохранить в простой заголовок и связать:
http://www.zedwood.com/article/cpp-md5-function
Или вы можете получить библиотеку, такую как OpenSSL или Crypto++.
Вы можете использовать функцию stat()
. Он может предоставить вам доступ к параметрам файла, таким как время последнего доступа, время последней модификации, размер файла и т. Д.:
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
Но вам нужно иметь разрешение на выполнение в файле, в котором вы его используете.
st_size
для проверки размера файла, если он был изменен. Или любой другой параметр, который может удовлетворить ваши потребности.