1. 程式人生 > >C++ /檔案流 /BMP檔案讀寫

C++ /檔案流 /BMP檔案讀寫

把一個字元寫到輸出流中:
cout.put('c'); // 輸出一個字元
cout<<'c'; // 輸出一個字元,但是此前設定的寬度和填充方式在此起作用

write 函式:

把記憶體中的一塊兒內容寫到一個輸出檔案中,該函式有兩個引數:一個char指標(指向記憶體資料的起始地址)和一個所寫位元組數。常用於二進位制檔案的輸出。(\(^o^)/~這個很有用哦) 注意:當用write 函式輸出資料時,如果檔案是按照binary模式開啟,寫到檔案的資料和輸出的資料完全相同。但是,如果檔案是按照文字模式開啟的,當輸出整數10,即二進位制數00001010 時,系統會認為它是ASCII字元回車,並且自動加上一個ASCII 字元00001101 ,也就是換行。變為將”回車換行“輸出到檔案。所以,用write 函式輸出資料時,檔案應該按照binary模式開啟。

seekp 和 tellp 函式:

seekp 把位置指標設定到某位置,tellp返回當前指標位置。(可參考下面的程式1)

close 函式:

與open 相對應,把輸出檔案流關聯的磁碟檔案關閉。一般來講,輸出流解構函式會自動關閉流關聯的檔案,不必顯示呼叫,但是如果要在同一個流物件上開啟另外的檔案,就需要close 函式。 ================================================================================================================================

檔案輸入流:

從磁碟檔案讀取資料。

read 函式:

從一個檔案 把位元組流讀到一個指定的儲存區,當讀了指定的位元組數或者遇到檔案結束符時讀結束。

seekg 和 tellg 函式:

在輸入檔案流中,儲存著一個指向下一個將要讀取資料的位置的內部指標,可以用seekg來設定這個指標。 tellg 返回當前檔案讀指標的位置,這個值是streampos型別,定義在iostream.h檔案中。 ==================================================================================================================================

幾個栗子:

1、指標定位,檔案長度獲取,檔案讀寫

// -----------------------------------------------------------------------------------------
// Function:讀取一個視訊檔案,然後將該視訊檔案另存為。
// -----------------------------------------------------------------------------------------
#include<iostream>
#include <fstream>
const int LENGTH = 32*1024;

using namespace std;

void main()
{
	char buff[LENGTH];
	streamoff  curpos;
	streamoff endpos;
	streamoff  length;
	int flag =1;
	int count=0;

	ifstream srcfile("1.avi",ios::binary);
	ofstream destfile("11.avi",ios::binary|ios::app);

	while(flag)
	{
		curpos=srcfile.tellg();// 獲取當前讀指標位置 // 成功才會是正常值,否則是-1
		srcfile.seekg(0,ios::end);// 將讀指標放置於檔案末尾
		endpos=srcfile.tellg();
		length=endpos-curpos;
		srcfile.seekg(curpos);// 恢復當前讀指標
		if (length>=LENGTH)
		{

			srcfile.read(buff,LENGTH );
			destfile.write(buff,LENGTH);// 前面說過,使用write時,需要用binary模式開啟。
			count+=LENGTH/1024;

			cout<<"本次傳送:"<<LENGTH/1024<<" KB ;  "<<"總髮送:"<<count<<" KB  "<<endl;
		}
		else
		{
			srcfile.read(buff,length);
			destfile.write(buff,length);
			count+=length/1024;

			cout<<"本次傳送:"<<length/1024<<" KB ;  "<<"總髮送:"<<count<<" KB  "<<endl;
			flag=0;

		}
	}
	char wbp=getchar();
}

2、變數寫入檔案,檔案資料排版

//----------------------------------------------------------------------------------------------------------------------
// Function: 建立一個大陣列,寫入資料,然後存到磁碟檔案;將磁碟檔案資料讀入到大陣列中。
//----------------------------------------------------------------------------------------------------------------------

#include <iostream>
#include <fstream>
using namespace std;
struct Point2f
{
	float x;
	float y;
};
struct Point2fv
{
	float x;
	float y;
};
Point2fv PicAndPoint[6][4];
Point2fv testP[6][4];
void main()
{
	for (int i=0;i<3;++i)
	{
		for (int j=0;j<2;++j)
		{
			PicAndPoint[2*i+j][0].x= -1+j;
			PicAndPoint[2*i+j][0].y= 1/3.0-i*2/3.0;

			PicAndPoint[2*i+j][1].x=0+j;
			PicAndPoint[2*i+j][1].y=1/3.0-i*2/3.0;

			PicAndPoint[2*i+j][2].x=0+j;
			PicAndPoint[2*i+j][2].y=1-i*2/3.0;

			PicAndPoint[2*i+j][3].x= -1+j;
			PicAndPoint[2*i+j][3].y=1-i*2/3.0;

		}
	}


	ofstream destfile("F:\\conversion.txt", ios::app);
	for (int i=0;i<6;++i)
	{
		for (int j=0;j<4;++j)
		{
			destfile<<PicAndPoint[i][j].x<<" "<<PicAndPoint[i][j].y<<"\n"; // 此處有回車符

		}
	}
	destfile.close();

	ifstream srctfile("F:\\conversion.txt", ios::in);
	for (int i=0;i<6;++i)
	{
		for (int j=0;j<4;++j)
		{
			srctfile>>testP[i][j].x>>testP[i][j].y; // 忽略了回車符

		}
	}
	srctfile.close();
}



3、點陣圖檔案(BMP)的儲存

截圖神馬的可以參考這裡的程式碼。 用到#include <gl.h>  #include <glut.h>
void saveSceneImage(int x,int y,int width, int height)  
{  
	//glGetIntegerv(GL_VIEWPORT,ViewPort);  
	int ColorChannel = 3;  // 點陣圖檔案通道數,RGB
	int bufferSize = width*height*sizeof(GLubyte)*ColorChannel;  
	char * ImgData = new char[bufferSize];   
	// OpenGL 相關
	glPixelStorei(GL_UNPACK_ALIGNMENT,4);   // 4位元組對齊
	glReadPixels(x,y,width,height,GL_RGB,GL_UNSIGNED_BYTE,ImgData);  //從影象快取裡讀取一塊資料到記憶體


	BITMAPFILEHEADER hdr;  
	BITMAPINFOHEADER infoHdr;  
// 我們只需要關心點陣圖的尺寸,其他值預設就好了
	infoHdr.biSize = sizeof(BITMAPINFOHEADER);  
	infoHdr.biWidth =width;  
	infoHdr.biHeight = height;  
	infoHdr.biPlanes = 1;  
	infoHdr.biBitCount = 24;  
	infoHdr.biCompression = 0;  
	infoHdr.biSizeImage =width*height*3;  
	infoHdr.biXPelsPerMeter = 0;  
	infoHdr.biYPelsPerMeter = 0;  
	infoHdr.biClrUsed = 0;  
	infoHdr.biClrImportant = 0;  

	hdr.bfType = 0x4D42;  
	hdr.bfReserved1 = 0;  
	hdr.bfReserved2 = 0;  
	hdr.bfOffBits = 54;  
	hdr.bfSize =(DWORD)(sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+width* height * 3);  

	ofstream destfile("F:\\snap.bmp",ios::binary | ios::app);// app模式,依次寫入BITMAPFILEHEADER、BITMAPINFOHEADER和影象資料
	destfile.write((char*)&hdr,sizeof(BITMAPFILEHEADER));  
	//destfile.seekp(sizeof(BITMAPFILEHEADER));
	destfile.write((char*)&infoHdr,sizeof(BITMAPINFOHEADER));  
	//destfile.seekp(sizeof(BITMAPINFOHEADER));
	destfile.write((char*)ImgData,width* height * 3);  

	delete[] ImgData;
}  

補充: OpenGL提供了簡潔的函式來操作畫素:
glReadPixels
:讀取一些畫素。當前可以簡單理解為把已經繪製好的畫素(它可能已經被儲存到顯示卡的視訊記憶體中)讀取到記憶體
glDrawPixels
:繪製一些畫素。當前可以簡單理解為把記憶體中一些資料作為畫素資料,進行繪製
glCopyPixels
:複製一些畫素。當前可以簡單理解為把已經繪製好的畫素從一個位置複製到另一個位置。雖然從功能上看,好象等價於先讀取畫素再繪製畫素,但實際上它不需要把已經繪製的畫素(它可能已經被儲存到顯示卡的視訊記憶體中)轉換為記憶體資料,然後再由記憶體資料進行重新的繪製,所以要比先讀取後繪製快很多。