CFile Read数据问题

zwhate 2010-08-11 02:05:58
我在两个线程里面频繁的读取同一个文件同一个位置的数据,但是有一个线程90%能够读取正确,其他时候要么乱了,要么位置不对了,读到后面一段数据,不知道有没有人知道原因啊?

//¶ÁÈ¡Ë÷ÒýindexµÄµçÌÝÊý¾Ý
BOOL CLiftPara::ReadLiftDB(int index, LIFT_DATABASE& lift)
{
int iLiftNum = (int)(m_fileLift.GetLength() / sizeof(LIFT_DATABASE));

if (iLiftNum == NULL) //ûÓеçÌÝ×ÊÁÏ£¬¶Á²»µ½£¬²Ù×÷ʧ°Ü
{
return FALSE;
}

if (iLiftNum <= index) //µçÌÝ×ÊÁϲ»×㣬Ë÷Òý²»µ½£¬²Ù×÷ʧ°Ü
{
return FALSE;
}

//EnterCriticalSection
//m_cs.Lock();

EnterCriticalSection(&m_csApi);

m_fileLift.Seek(sizeof(LIFT_DATABASE) * index, CFile::begin);
m_fileLift.Read(&lift, sizeof(LIFT_DATABASE));

LeaveCriticalSection(&m_csApi);
//LeaveCriticalSection
//m_cs.Unlock();

return TRUE;
}

即使我加了临界区保护还是解决不了问题。
...全文
248 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
zwhate 2010-08-13
  • 打赏
  • 举报
回复
晕,很多人根本不认真看帖啊,我都说了是GetLength()改变了当前指针位置,导致文件位置被重新定位,所以另一个线程再去读的时候就乱了
shexinwei 2010-08-12
  • 打赏
  • 举报
回复
两个线程,使用的是两个文件指针访问文件,应当互不影响。你的读出的内容会错位?
zwhate 2010-08-12
  • 打赏
  • 举报
回复
原来这个家伙也会改变文件当前指针位置啊...
m_fileLift.GetLength()

我把这个也放在临界区内保护起来,好像就不出问题了,但是MSDN上没有说明,我来去google
liuhaifeng1976 2010-08-12
  • 打赏
  • 举报
回复
文件偏移位置不对吧
zjz800800 2010-08-12
  • 打赏
  • 举报
回复
虽然说读文件不需要同步,但是问题如果不好界定就将数据同步后分析,使用临界区、互斥量、事件量、信号量均可。
shexinwei 2010-08-12
  • 打赏
  • 举报
回复
一个文件怎么就不能有两个文件指针?
zwhate 2010-08-12
  • 打赏
  • 举报
回复
一个文件,怎么可能有两个文件指针...
确实是GetLength()函数改变了当前指针位置
zwhate 2010-08-11
  • 打赏
  • 举报
回复
那个不是线程函数,是线程调用的函数
Eleven 2010-08-11
  • 打赏
  • 举报
回复
你上面的写的是线程函数吗?
zgl7903 2010-08-11
  • 打赏
  • 举报
回复
线程里建议不要使用CFile类,我做的多线程里也遇到类似的问题,直接使用API的读写方式就解决了
CReateFile
ReadFile
WriteFile
CloseHandle
zwhate 2010-08-11
  • 打赏
  • 举报
回复
关键是这个过程我只用了读数据,根本还没有去写呢...
写只是在其他地方的按钮里面会操作一下,我目前根本不去写,但是数据乱了就算了,还有数据跑到后面一个段去了,我后来以为位置设置出错了seek的时候把位置写死,结果还会错乱
精锐掷矛手 2010-08-11
  • 打赏
  • 举报
回复
只读取的话不需要加临界区,是否有写操作呢?写操作是否有问题?
mudunke775 2010-08-11
  • 打赏
  • 举报
回复
应该是读取汉字的时候出的问题,截断的时候正好截到了汉字的字符中间,所以出现乱码
CFile //创建/打开文件 CFile file; file.Open(_T("test.txt"),CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite); 文件打开模式可组合使用,用“|”隔开,常用的有以下几种: CFile::modeCreate:以新建方式打开,如果文件不存在,新建;如果文件已存在,把该文件长度置零,即清除文件原有内容。 CFile::modeNoTruncate:以追加方式打开,如果文件存在,打开并且不将文件长度置零,如果文件不存在,会抛出异常。一般与CFile::modeCreate一起使用,则文件不存在时,新建一个文件;存在就进行追加操作。 CFile::modeReadWrite:以读写方式打开文件。 CFile::modeRead:只读。 CFile::modeWrite:只写。 //写入数据 CString strValue = "Hello World!"; file.Write(strValue,strValue.GetLength()); //追加数据 file.SeekToEnd(); //将指针移至文件末尾进行追加 file.Write(strValue,strValue.GetLength()); //关闭文件 file.Close(); CStdioFile CStdioFile是CFile的派生类,对文件进行流式操作,对于文本文件的读写很有用处,可按行读取写入。 //写入数据 CString strValue = "Hello World!"; file.WriteString(strValue); //读取数据 CString strRead; file.ReadString(strRead); 当文件存在多行数据需要逐行读取时,可用函数BOOL CStdioFile::ReadString(CString& rString),当遇到"\n "时读取截断,如果文件未读完,返回true,否则返回false。 //逐行读取文件内容,存入strRead while(file.ReadString(strRead)) { ...; } 各种关于文件的操作在程序设计中是十分常见,如果能对其各种操作都了如指掌,就可以根据实际情况找到最佳的解决方案,从而在较短的时间内编写出高效的代码,因而熟练的掌握文件操作是十分重要的。本文将对Visual C++中有关文件操作进行全面的介绍,并对在文件操作中经常遇到的一些疑难问题进行详细的分析。   1.文件的查找   当对一个文件操作时,如果不知道该文件是否存在,就要首先进行查找。MFC中有一个专门用来进行文件查找的类CFileFind,使用它可以方便快捷地进行文件的查找。下面这段代码演示了这个类的最基本使用方法。   CString strFileTitle;   CFileFind finder;   BOOL bWorking = finder.FindFile("C:\\windows\\sysbkup\\*.cab");   while(bWorking)   {   bWorking=finder.FindNextFile();   strFileTitle=finder.GetFileTitle();   }   2.文件的打开/保存对话框   让用户选择文件进行打开和存储操作时,就要用到文件打开/保存对话框。MFC的类CFileDialog用于实现这种功能。使用CFileDialog声明一个对象时,第一个BOOL型参数用于指定文件的打开或保存,当为TRUE时将构造一个文件打开对话框,为FALSE时构造一个文件保存对话框。   在构造CFileDialog对象时,如果在参数中指定了OFN_ALLOWMULTISELECT风格,则在此对话框中可以进行多选操作。此时要重点注意为此CFileDialog对象的m_ofn.lpstrFile分配一块内存,用于存储多选操作所返回的所有文件路径名,如果不进行分配或分配的内存过小就会导致操作失败。下面这段程序演示了文件打开对话框的使用方法。   CFileDialog mFileDlg(TRUE,NULL,NULL,   OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_ALLOWMULTISELECT,   "All Files (*.*)|*.*||",AfxGetMainWnd());   CString str(" ",10000);   mFileDlg.m_ofn.lpstrFile=str.GetBuffer(10000);   str
〉CDIB功能 提供针对设备无关位图的一系列操作。 〉CDIB使用方法 将DIB目录复制到工程的原文件目录中。 在工程的Source Files中添加DIB文件夹,并导入DIB目录中的所有文件。 在需要使用DIB的文件中添加 include "dib.h" using namespace DIB; 1)读取Bitmap图片 //CDib对象可以从读取Bitmap,DIB文件数据。 //之前需要创建CFile对象,而后从CFile对象读取数据。 CDib m_Dib; CFile* pf; pf=new CFile; pf->Open(m_ImageName,CFile::modeRead); //m_ImageName为路径加文件名,如"C:\\Img\\My_Bitmap.bmp" m_Dib.Read(pf); pf->Close(); delete pf; 2)保存CDib对象到文件 //m_Dib是包含有图像数据CDib对象 //pFile 指向已经创建的可对文件进行写操作的CFile对象 m_Dib.write(CFile* pFile) 3)从CDIB获得图像数据 //m_Dib 包含有图像数据CDib对象 //realDataFLag 选择是返回真实图像数据,还是返回灰度数据的布尔值变量(bool),为真时返回的是图像真实数据。 unsigned char * img; img=m_Dib.GetImgPtr(realDataFLag); //获得的图像数据是以左上角为(0,0)点开始的从左至右, //从上至下,具有真实宽度(非补4)的数据 //realDataFlag为真时返回的是图像真实数据 //realDataFlag为假时返回的是灰度化的图像数据 4)将图像数据赋给CDib对象 //m_Dib是包含有图像数据CDib对象 //img 指向图像数据的无符号字符型指针(unsigned char *) //realDataFLag 指明输入的是真实图像数据,还是返回灰度数据的布尔值变量(bool),为真时输入的是图像真实数据。 m_Dib.SetImgPtr(img,realDataFlag);//设置图像数据 5)从图像数据创建CDib对象 CDib m_Dib m_Dib.CreateDib(pImgData,width,height,nBitCount);//pImgData为指向图象数据的指针 //nBitCount一个像素所用的比特数 目前仅支持8 6)由CDib对象创建Bitmap对象 //m_Dib是包含有图像数据CDib对象 HBITMAP bitmap; CDC * pDC=AfxGetApp()->GetMainWnd()->GetDC(); bitmap=m_Dib.CreateBitmap(pDC)//输入值为 CDC * ,一般可通过AfxGetApp()->GetMainWnd()->GetDC()获得 7)显示图象中的特殊信息 在处理过程中将图像中的特殊信息用251~255表示(对彩色图像,将R、G、B赋予251~255的相同数值) 将灰度图象中灰度值大于等于251的不需特殊显示的像素赋为250, 将彩色图像中R=G=B且大于等于251的不需特殊显示的像素赋为(250,250,250) 而后按4)中描述的将图像数据赋给CDib对象 最后调用EnhanceColor()将CDib对象转化为可以显示特殊信息的图像
if(strPathName == "") return false; BITMAPFILEHEADER * pBFH; BITMAPINFOHEADER * pBIH; CFile file(strPathName,CFile::modeCreate | CFile::modeNoTruncate | CFile::modeRead); DWORD filelength = file.GetLength(); // 分配一块内存用于装入图象数据 if(m_hDib!=NULL) ::GlobalFree(m_hDib); m_hDib = :: GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,filelength); if(m_hDib==NULL) { return (FALSE); } m_pDib = (BYTE *)::GlobalLock(m_hDib); if(m_pDib==NULL) { ::GlobalFree(m_hDib); return (FALSE); } // 将图象数据读入内存 file.Read(m_pDib,(UINT)filelength); file.Close(); // 读入头信息 pBFH = (BITMAPFILEHEADER *) m_pDib; pBIH = (BITMAPINFOHEADER *) (m_pDib+sizeof(BITMAPFILEHEADER)); WORD bfType = pBFH->bfType; if(bfType!=19778) // "BM"标志 { AfxMessageBox("Not a valid BMP image!"); return FALSE; } //得到位图信息 m_nWidth = (int)pBIH->biWidth; m_nHeight = (int)pBIH->biHeight; m_nBits = (int)pBIH->biBitCount; m_nColors = (int)pBIH->biClrUsed; if(m_nColors == 0) { if(m_nBits <= 8) m_nColors = 1 << m_nBits; } m_strPathName = strPathName; // 载入调色板 m_Palette.DeleteObject(); if( m_nBits <= 8 ) m_nPaletteInBytes = m_nColors * sizeof( RGBQUAD ); if( m_nBits <= 8 ) { RGBQUAD *pRGBPalette; pRGBPalette = ( RGBQUAD * )&m_pDib[ sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) ]; LOGPALETTE *pLogPalette; pLogPalette = ( LOGPALETTE * )new char[ sizeof( LOGPALETTE ) + m_nColors * sizeof( PALETTEENTRY ) ]; pLogPalette->palVersion = 0x300; pLogPalette->palNumEntries = ( unsigned short )m_nColors; for(int i=0; ipalPalEntry[ i ].peRed = pRGBPalette[ i ].rgbRed; pLogPalette->palPalEntry[ i ].peGreen = pRGBPalette[ i ].rgbGreen; pLogPalette->palPalEntry[ i ].peBlue = pRGBPalette[ i ].rgbBlue; pLogPalette->palPalEntry[ i ].peFlags = 0; } if( pLogPalette == NULL ) { ::GlobalUnlock( m_hDib ); return FALSE; } m_Palette.CreatePalette( pLogPalette ); delete[] pLogPalette; }

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧