1. 程式人生 > >C++簡單的檔案操作

C++簡單的檔案操作

背景

專案中需要接收週期性(0.625ms)資料(128Bytes),並將資料儲存、解析,之後需要將其以曲線的形式繪製出來。128位元組資料需要解析出60項引數。

方案

原方案:
接收128位元組資料後,先進行解析,將解析後的引數項以字元文字形式儲存在.txt中,同時繪製實時引數曲線。在之後進行資料回放時,直接從文字檔案中讀取。
這種方法的優點是可以在文字中儲存下各個引數的解析值,但是在回放繪製曲線時效率很低,耗時久。
改進方案:
接收128位元組資料後,直接將此資料以二進位制流的形式寫入.bin檔案,同時解析引數繪製實時曲線。在之後進行資料回放時,從.bin檔案中讀取、解算、繪圖。
此方案的優點是儲存檔案小,讀取時效率高,耗時少,佔用記憶體可確定。

此處簡單寫了一段程式碼對兩種方案的存取資料過程及讀取耗時進行比較:

// binFileTry.cpp : 定義控制檯應用程式的入口點。
// 2019-1-4 E705

#include "stdafx.h"
#include "iostream"
#include "iomanip"
#include "fstream"
#include "time.h"
#include "windows.h"


using namespace std;

ofstream outFileBin;
ofstream outFileTxt;

ifstream inFileTxt;
ifstream inFileBin;

int count_bin = 0;
int count_txt = 0;

int initialData(char * data)
{
	
	for (int i = 0; i < 128; i++)
	{
		data[i] = rand()%100;
		//std::cout << (int)data[i] << "	";
	}
	return 0;
}

int writeTxtFile(char * data)
{
	
	for (int i = 0; i < 128; i += 4)
	{
		char pBuffer[20];		
		int tmp = ((data[i] << 24) & 0xff000000) + ((data[i + 1] << 16) & 0xff0000) + ((data[i + 2] << 8) & 0xff00) + data[i+3];
		
		sprintf_s(pBuffer, sizeof(pBuffer), "%10d\t", tmp);
		outFileTxt.write(pBuffer, strlen(pBuffer));
	}
	return 0;
}

int readTxtFile()
{
	int buffer[32];

	LARGE_INTEGER nFreq;
	LARGE_INTEGER nBeginTime;
	LARGE_INTEGER nEndTime;

	QueryPerformanceFrequency(&nFreq);
	QueryPerformanceCounter(&nBeginTime);

	while (inFileTxt >> \
		buffer[0] >> buffer[1] >> buffer[2] >> buffer[3] >> buffer[4] >> buffer[5] >> buffer[6] \
		>> buffer[7] >> buffer[8] >> buffer[9] >> buffer[10] >> buffer[11] >> buffer[12] >> buffer[13] \
		>> buffer[14] >> buffer[15] >> buffer[16] >> buffer[17] >> buffer[18] >> buffer[19] >> buffer[20] \
		>> buffer[21] >> buffer[22] >> buffer[23] >> buffer[24] >> buffer[25] >> buffer[26] >> buffer[27] \
		>> buffer[28] >> buffer[29] >> buffer[30] >> buffer[31])
	{
		count_txt++;

		//顯示以檢視讀取是否正確
// 		for (int i = 0; i < 32; i++)
// 		{
// 			cout << setw(16) << buffer[i] << "	";
// 		}
// 		cout << endl;
	}

	QueryPerformanceCounter(&nEndTime);
	double time = (double)(nEndTime.QuadPart - nBeginTime.QuadPart) / double(nFreq.QuadPart) * 1000;

	cout << time << "\n";

	

	return 0;
}

int readBinFile_oneLine()
{
	char buffer[128];

	LARGE_INTEGER nFreq;
	LARGE_INTEGER nBeginTime;
	LARGE_INTEGER nEndTime;

	QueryPerformanceFrequency(&nFreq);
	QueryPerformanceCounter(&nBeginTime);

	while (!inFileBin.eof() && inFileBin.peek() != EOF)
	{
		inFileBin.read(buffer, sizeof(char)* 128);
		for (int i = 0; i < 128; i += 4)
		{
			int tmp = ((buffer[i] << 24) & 0xff000000) + ((buffer[i + 1] << 16) & 0xff0000) + ((buffer[i + 2] << 8) & 0xff00) + buffer[i + 3];
			count_bin++;
			cout << setw(16) << tmp << "	";
		}
		cout << endl;
	}

	QueryPerformanceCounter(&nEndTime);
	double time = (double)(nEndTime.QuadPart - nBeginTime.QuadPart) / double(nFreq.QuadPart) * 1000;

	cout << time << "\n";
	
	return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
	//將採集(生成)的資料寫入檔案
	outFileBin.open("..\\..\\1.bin", ios::binary);
	outFileTxt.open("..\\..\\1.txt", ios::out);

	char binData[128];
	char nextLine[2] = { 0x0a, 0X0D };
	srand((unsigned int)time(NULL));
	
	int totalTime = 5*60*1000 / 0.625;   //生成5min中資料
	for (int i = 0; i < totalTime; i++)
	{
		initialData(binData);
		//std::cout << "\n";
		writeTxtFile(binData);
		outFileTxt.write("\r\n", 2);
		outFileBin.write(binData, 128);
	}

	outFileBin.close();
	outFileTxt.close();

	//從檔案中讀取資料,並比較操作時間
	inFileBin.open("..\\..\\1.bin", ios::binary);
	inFileTxt.open("..\\..\\1.txt", ios::in);

	readTxtFile();    //原方案花費時間:66543.7ms  65594.1ms  66566.3ms
	readBinFile_oneLine();  //使用二進位制花費時間:517.953ms 478.404ms 456.393ms
	
	cout << endl << count_bin;
	cout << endl << count_txt*32;

	inFileBin.close();
	inFileTxt.close();

	return 0;
}

耗時結果比較:

實驗次數 1 2 3
原方案耗時/ms 66543.7 65594.1 66566.3
改進方案耗時/ms 517.953 478.404 56.393

表格建立參考:利用Markdown建立表格