一个奇怪的fread后偏移量不正确的问题
#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <Windows.h>
//encrypt data
void EncryptBlock(unsigned char*& blockdata, size_t n)
{
}
//encrypt file
bool EncryptFile(const char* path, size_t blocksize)
{
FILE* fp = NULL;
auto erno = fopen_s(&fp, path, "rb+");
if (erno != 0)
{
printf("openfile:[%s] fail!!, errno=%d\n", path, erno);
return false;
}
//get file size
_fseeki64(fp, 0, SEEK_END);
int64_t filesize = _ftelli64(fp);
_fseeki64(fp, 0, SEEK_SET);
printf("filesize:%lld, %lldmb\n", filesize, filesize / (1024 * 1024));
int64_t processed = 0;
//buffer
unsigned char* blockdata = new unsigned char[blocksize];
while (1)
{
int64_t currpos = _ftelli64(fp);
//printf("curr:%lld, size=%lldmb\n", currpos, currpos / (1024 * 1024));
//read and set offset
size_t readsize = fread(blockdata, 1, blocksize, fp);
if (0 == readsize)
{
break;
}
int64_t currpos2 = _ftelli64(fp);
if (currpos + readsize != currpos2)
{
printf("offset incorrect\n");
break;
}
_fseeki64(fp, -1 * readsize, SEEK_CUR);
//encrypt
EncryptBlock(blockdata, readsize);
//write
size_t writesize = fwrite(blockdata, 1, readsize, fp);
if (writesize != readsize)
{
printf("write:writesize=%llu, readsize=%llu, warning!!!!!!!!!!!\n", writesize, readsize);
}
processed += writesize;
//_fseeki64(fp, 1 * processed, SEEK_SET);
//fflush(fp);
if (readsize != blocksize)
{
printf("readsize=%llu, block=%llu, break[processd:%llu]\n", readsize, blocksize, processed);
break;
}
}
delete[] blockdata;
fclose(fp);
//error
if (processed != filesize)
{
printf("processed(%lld) != filesize(%lld), warning!!!!!!!!!!!\n", processed, filesize);
return false;
}
else
{
return true;
}
}
int main(int argc, char *argv[])
{
auto tv1 = GetTickCount64();
auto suc = EncryptFile("d:\\soft.msi", 1024 * 102);
auto tv2 = GetTickCount64();
auto used = (tv2 - tv1);
printf("encrypt:%s, cost:%llums\n", suc ? " succ" : " fail", used);
getchar();
return 0;
}
功能很简单,读取一个文件,每次读取一块,加密后写回原位置,直到整个文件完成加密。
当使用EncryptFile("d:\\soft.msi", 1024 * 1024)
时运行良好,但是当时手一抖,变成了EncryptFile("d:\\soft.msi", 1024 * 102)
报了错。
经过调试之后,发现错误情况如下
通过查询fwrite和ftell确认文件指针的偏移量,在第二次fread之前确实符合文档说明的。
但是第二次fread之后,会发现偏移量对不上。查询fread发现和文档不一致了。
此时完全不知道应该怎么处理。
后续在LINUX下对上述代码进行验证,发现也是一样的情况。基本可以确定是代码写错了。
然后在stackoverflow上发帖询问,在搞清stackoverflow各种规则后,非常幸运的很快就有人指出了错误的原因。
fopen函数的问题
然后再去microsoft.doc.fopen上查找,也是明确说明了调用的规则。
上述代码在fwrite之后,调用fflush即可获得预期的行为