C语言实现将内存中的内容实时保存。

时间:2021-06-15 03:40:33
使用C语言开发一个数据采集程序。数据每秒1000次采集,数据可以实现实时同步到内存中,问题是如何保存到硬盘上。
每个原始数据为512*512的一个矩阵。如果进行基线检查(每个矩阵元减去一个背景值),那么数据为一个大概1000-2000个点的稀疏矩阵。如果不进行基线检查,就是原始矩阵512*512个点。

如果要实现数据的实时保存,请问采用什么方法比较好?非常感谢!下面是我用的方法,但是发现耗时严重每秒大概2次不到的样子。CPU:intel i5-6500@3.2GHz,16GB内存。

for (int jj=0;jj<1000;jj++) {
char* filename;
    filename = char(jj);
      FILE *f = fopen( filename, "w" );
      for (y=0; y<ny; y++) {
         float *ptr = (float*)GetPtr(bufnum,y);
         for (x=0; x<nx; x++, ptr++)
            fprintf(f,"%*.3f ",12, *ptr);
         fprintf(f,"\n");
      }
   
}   
   fclose(f);

10 个解决方案

#1


你这代码本身就有问题啊,在循环体里边执行fopen,却在循环体外边fclose,没有配对。fopen应该在循环之前做。

#2


你的文件打开次数太多了吧
for (int jj=0;jj<1000;jj++) {
char* filename;
    filename = char(jj);
      FILE *f = fopen( filename, "w" );
      for (y=0; y<ny; y++) {
         float *ptr = (float*)GetPtr(bufnum,y);
         for (x=0; x<nx; x++, ptr++)
            fprintf(f,"%*.3f ",12, *ptr);
         fprintf(f,"\n");
      }
   
}   

你要打开几个文件?看你的打开文件在一个循环里,那么应该是打开多次(或打开多个文件)。如果实时保存时,只需要保存一份数据,建议先把文件打开再循环写入。另外,再次写入时将文件指针,只需要将文件指针重新指向文件开头即可。使用fseek或者rewind都可以实现将文件指针指向文件开始位置

#3


打开文件会比较耗时,所以若是循环打开或者打开多个文件耗时就更多了。

#4


谢谢大家回复,重新编辑了一下. 因为数据量比较大,担心CPU运行不过来,所以打算每次都把数据保存下来,保存到不到的文件中。

for (int jj=0;jj<1000;jj++) // 采集1000次 
{
char* filename; //每一次的文件名
    filename = char(jj);//每一次的文件名
      FILE *f = fopen( filename, "w" ); //每次保存一个新文件
      for (y=0; y<ny; y++) {
         float *ptr = (float*)GetPtr(bufnum,y);
         for (x=0; x<nx; x++, ptr++)
            fprintf(f,"%*.3f ",12, *ptr); //把数据写入新文件
         fprintf(f,"\n");
      }
      fclose(f); //数据采集完一次,关闭文件;
}   

#5


由于C语言不能获得足够的权限,C程序是做成dll文件被其他程序调用使用的。不知道下面这个替代方法是否可行。

1,指定一个较大的内存区域,用于不停的存储新来的数据。
2. 主程序每调用一次C程序(dll文件),就在内存中进行一次基线检查,然后将剩下的矩阵元(1000个点)写入1中开辟的内存中。
并保证内存空间中的数据不消失(怎么保证?)
3.多次采集后例如(10万次后,将内存中的数据一次性写入硬盘)

由于每次主程序调用的是dll文件,每次调用完之后,dll文件都关闭了,那怎么保证内存空间中的数据不消失?

非常谢谢!

#6


// 创建文件句柄
HANDLE hFile = ::CreateFile(lpszFileName, GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
// 创建文件映射
HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READONLY | SEC_COMMIT, NULL, NULL, NULL);
// 读取映射中的内存
LPVOID lpBuffer = ::MapViewOfFile(hMap, FILE_MAP_READ, NULL, NULL, NULL);

// 好了文件的内存已经获取了,你可以随意处理了

// 释放映射内存
::UnmapViewOfFile(lpBuffer);
// 关闭文件映射
::CloseHandle(hMap);
// close file handle
::CloseHandle(hFile);

#7


// 创建文件句柄
HANDLE hFile = ::CreateFile(lpszFileName, GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
// 创建文件映射
HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READONLY | SEC_COMMIT, NULL, NULL, NULL);
// 读取映射中的内存
LPVOID lpBuffer = ::MapViewOfFile(hMap, FILE_MAP_READ, NULL, NULL, NULL);

// 好了文件的内存已经获取了,你可以随意处理了

// 释放映射内存
::UnmapViewOfFile(lpBuffer);
// 关闭文件映射
::CloseHandle(hMap);
// close file handle
::CloseHandle(hFile);

#8


嗯。。稀疏矩阵最好用位图bitmap,可以去自己参考一下思想。空间利用率和CPU利用率都很高
如果想进一步压缩时间的话,最好减少IO的操作次数,考虑把成堆数据一次性输出到文件中
最后,将数据从内存中输出到硬盘中的操作,是不怎么会用到CPU的,电脑自带存储管理管线和控制器,CPU只是吧数据放在控制器上而已,传输操作不归CPU管

#9


内存中的数据只要你程序没有崩溃或者关闭,就会一直存在,所以你要做的,就是写一个好的、鲁棒的程序,保证其稳定性,

#10


你代码本身就存在问题,你打开了多次fopen,如果你想向一个文件中紧接文件尾部继续写入可以用fflush

#1


你这代码本身就有问题啊,在循环体里边执行fopen,却在循环体外边fclose,没有配对。fopen应该在循环之前做。

#2


你的文件打开次数太多了吧
for (int jj=0;jj<1000;jj++) {
char* filename;
    filename = char(jj);
      FILE *f = fopen( filename, "w" );
      for (y=0; y<ny; y++) {
         float *ptr = (float*)GetPtr(bufnum,y);
         for (x=0; x<nx; x++, ptr++)
            fprintf(f,"%*.3f ",12, *ptr);
         fprintf(f,"\n");
      }
   
}   

你要打开几个文件?看你的打开文件在一个循环里,那么应该是打开多次(或打开多个文件)。如果实时保存时,只需要保存一份数据,建议先把文件打开再循环写入。另外,再次写入时将文件指针,只需要将文件指针重新指向文件开头即可。使用fseek或者rewind都可以实现将文件指针指向文件开始位置

#3


打开文件会比较耗时,所以若是循环打开或者打开多个文件耗时就更多了。

#4


谢谢大家回复,重新编辑了一下. 因为数据量比较大,担心CPU运行不过来,所以打算每次都把数据保存下来,保存到不到的文件中。

for (int jj=0;jj<1000;jj++) // 采集1000次 
{
char* filename; //每一次的文件名
    filename = char(jj);//每一次的文件名
      FILE *f = fopen( filename, "w" ); //每次保存一个新文件
      for (y=0; y<ny; y++) {
         float *ptr = (float*)GetPtr(bufnum,y);
         for (x=0; x<nx; x++, ptr++)
            fprintf(f,"%*.3f ",12, *ptr); //把数据写入新文件
         fprintf(f,"\n");
      }
      fclose(f); //数据采集完一次,关闭文件;
}   

#5


由于C语言不能获得足够的权限,C程序是做成dll文件被其他程序调用使用的。不知道下面这个替代方法是否可行。

1,指定一个较大的内存区域,用于不停的存储新来的数据。
2. 主程序每调用一次C程序(dll文件),就在内存中进行一次基线检查,然后将剩下的矩阵元(1000个点)写入1中开辟的内存中。
并保证内存空间中的数据不消失(怎么保证?)
3.多次采集后例如(10万次后,将内存中的数据一次性写入硬盘)

由于每次主程序调用的是dll文件,每次调用完之后,dll文件都关闭了,那怎么保证内存空间中的数据不消失?

非常谢谢!

#6


// 创建文件句柄
HANDLE hFile = ::CreateFile(lpszFileName, GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
// 创建文件映射
HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READONLY | SEC_COMMIT, NULL, NULL, NULL);
// 读取映射中的内存
LPVOID lpBuffer = ::MapViewOfFile(hMap, FILE_MAP_READ, NULL, NULL, NULL);

// 好了文件的内存已经获取了,你可以随意处理了

// 释放映射内存
::UnmapViewOfFile(lpBuffer);
// 关闭文件映射
::CloseHandle(hMap);
// close file handle
::CloseHandle(hFile);

#7


// 创建文件句柄
HANDLE hFile = ::CreateFile(lpszFileName, GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
// 创建文件映射
HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READONLY | SEC_COMMIT, NULL, NULL, NULL);
// 读取映射中的内存
LPVOID lpBuffer = ::MapViewOfFile(hMap, FILE_MAP_READ, NULL, NULL, NULL);

// 好了文件的内存已经获取了,你可以随意处理了

// 释放映射内存
::UnmapViewOfFile(lpBuffer);
// 关闭文件映射
::CloseHandle(hMap);
// close file handle
::CloseHandle(hFile);

#8


嗯。。稀疏矩阵最好用位图bitmap,可以去自己参考一下思想。空间利用率和CPU利用率都很高
如果想进一步压缩时间的话,最好减少IO的操作次数,考虑把成堆数据一次性输出到文件中
最后,将数据从内存中输出到硬盘中的操作,是不怎么会用到CPU的,电脑自带存储管理管线和控制器,CPU只是吧数据放在控制器上而已,传输操作不归CPU管

#9


内存中的数据只要你程序没有崩溃或者关闭,就会一直存在,所以你要做的,就是写一个好的、鲁棒的程序,保证其稳定性,

#10


你代码本身就存在问题,你打开了多次fopen,如果你想向一个文件中紧接文件尾部继续写入可以用fflush