用c++将大型int写入磁盘



我有很多20字节的整数要写入磁盘。我使用GMPmpz_class将它们存储在ram中

我已经尝试使用以下测试代码,但文件中的代码是20x 0s,而不是预期的00000000 00000000 00000000 00000000 21F882C7

#include <iostream>
#include <fstream>
#include <string>
#include <gmpxx.h>
using namespace std;
int main() {
mpz_class userId;
userId="569934535";
//open user file
string fileName= "test.bin";
ofstream mapFile(fileName,ios::binary);
//save userId
mpz_class temp=userId;  //copy so original not destroyed(never reused in example but in real life it would)
unsigned int bytes[20];
for (unsigned char i=0;i<20;i++) {
mpz_class t=temp%256;
bytes[19-i]=t.get_ui();
temp/=256;
}
mapFile.write((char*)&bytes,20);//expecting to write 00000000 00000000 00000000 00000000 21F882C7
mapFile.close();
return 0;
}

我是c++新手,我缺少什么?如果有更好的方法,还有什么建议吗?

编辑1:

感谢您的评论,指出我使用的是int,而我本应该使用char。但更好的是@kelalaka指出,mpz_class有一个内置功能,这让我有了两个不同的选项

以下是对mpz_out_raw的替换,除了它使用mpz_class而不是mpz_t op作为输入之外。假设您总是使用小于256字节的数据,则每个写入的数字可节省3个字节,但速度慢了5倍。

void nonStandard(FILE *stream, mpz_class op) {
unsigned char length=0;
unsigned char bytes[127];
while (op>0) {
mpz_class t=op%256;
bytes[length+1]=t.get_ui();
op/=256;
length++;
}
unsigned char buffer[length+1];
buffer[0]=length;
for (char i=length-1;i>=0;i--) buffer[length-i]=bytes[i];
fwrite(buffer, sizeof(unsigned char),length+1, stream);
}

事实证明,gmp有一个将数字写入文件streemmpz_out_raw的函数,但它使用了一个4字节的长度值,对我来说,这是一个过杀的值,所以我写了一个类似的函数,只使用了1字节的长度。虽然我的函数保存了3个字节的存储数据,但它的运行时间是本机函数的5倍,因此可能不需要。

下面是我的函数nonStandard和一个测试其速度的示例脚本。它将向磁盘写入1000000个数字,并计算所用时间。

#include <iostream>
#include <string>
#include <gmpxx.h>
using namespace std;
#include <chrono>
#include <thread>
using Clock = std::chrono::steady_clock;
using std::chrono::time_point;
using std::chrono::duration_cast;
using std::chrono::milliseconds;
using namespace std::literals::chrono_literals;
using std::this_thread::sleep_for;

/**
* This function only works with numbers up to 2^1016
* @param stream
* @param op
*/
void nonStandard(FILE *stream, mpz_class op) {
unsigned char length=0;
unsigned char bytes[127];
while (op>0) {
mpz_class t=op%256;
bytes[length]=t.get_ui();
op/=256;
length++;
}
unsigned char buffer[length+1];
buffer[0]=length;
for (char i=length-1;i>=0;i--) buffer[length-i]=bytes[i]; // NOLINT(cppcoreguidelines-narrowing-conversions)
fwrite(buffer, sizeof(unsigned char),length+1, stream);
}
int main() {
mpz_class userId;
userId="345474756569934535";
FILE* mapFile = fopen("mpz_out_raw.bin", "wb");

time_point<Clock> start = Clock::now();
//test start
for (int i=0;i<1000000;i++) {
userId+=7;
mpz_out_raw(mapFile,userId.get_mpz_t());
}
fclose(mapFile);
//test end
time_point<Clock> end = Clock::now();
milliseconds diff = duration_cast<milliseconds>(end - start);
std::cout << "mpz_out_raw: " << diff.count() << "ms" << std::endl;

userId="345474756569934535";
mapFile = fopen("nonStandard.bin", "wb");
start = Clock::now();
//test start
for (int i=0;i<1000000;i++) {
userId+=7;
nonStandard(mapFile,userId);
}
fclose(mapFile);
//test end
end = Clock::now();
diff = duration_cast<milliseconds>(end - start);
std::cout << "nonStandard: " << diff.count() << "ms" << std::endl;
return 0;
}

最新更新