Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1613058
  • 博文数量: 441
  • 博客积分: 20087
  • 博客等级: 上将
  • 技术积分: 3562
  • 用 户 组: 普通用户
  • 注册时间: 2006-06-19 15:35
文章分类

全部博文(441)

文章存档

2014年(1)

2012年(1)

2011年(8)

2010年(16)

2009年(15)

2008年(152)

2007年(178)

2006年(70)

分类:

2007-09-19 16:11:57

我定义了一个结构
typedef struct tag_HOSTINFO
{
   char szHostName[64];
   DWORD dwIP;
   DWORD dwPort;
}HOSTINFO, *PHOSTINFO;

然后我填充这个结构,将N个结构信息写入文件

接着我用下面的方法读出写入文件的数据:
CFile f;
f.Open(.....)

PHOSTINFO pInfo = new HOSTINFO; //申请内存
ZeroMemory(pInfo, sizoef(HOSTINFO); // 用0填充新申请的空间

while ( f.Read(pInfo, sizeof(HOSTINFO)) == sizoef(HOSTINFO)) // 将数据读入内存
{
    AddToList((void*)pInfo); // 将读出来的数据指针放入链表

    PHOSTINFO pInfo = new HOSTINFO; // 再申请内存,为下一次读数据做准备
    ZeroMemory(pInfo, sizoef(HOSTINFO); // 如果这里改了变量名的话,下一次read
                                       // 就没法读数据到新的内存了
    
}
delete pInfo;// 删除多申请的一次内存

...
f.Close();

可是当我调试的时候却发现,new HOSTINFO成功申请了内存,可是当f.Read的时候
pInfo不仅读出来的值不对而且pInfo本身的值被修改了,类似 0xcccccc.的东西

后来我改变了写法:
HOSTINFO tInfo;
ZeroMemory(&tInfo, sizeof(HOSTINFO));
while ( f.Read(&tInfo, sizeof(HOSTINFO)) == sizoef(HOSTINFO))
{
    PHOSTINFO pInfo = new HOSTINFO;
    ZeroMemory(pInfo, sizoef(HOSTINFO);
    
    memcpy(pInfo, &tInfo, sizeof(HOSTINFO));
    // do something
}

这个时候,我发现pInfo没有被修改而且值也对,我看了MSDN:
virtual UINT Read(
void* lpBuf,
UINT nCount );

Parameters:
lpBuf
Specifies the pointer to the user-supplied buffer that is to receive the data read from the file.

nCount
Specifies the maximum number of bytes to be read from the file. For text-mode files, carriage return–linefeed pairs are counted as single characters.

Return Value
The number of bytes transferred to the buffer. Note that for all CFile classes, the return value may be less than nCount if the end of file was reached.

从这上面的描述来看,我new 出来的内存应该也是可以的,可为什么会被修改呢?
我一直搞不明白,后来在vckbase.com的论坛上问了问,我才发现一个不应该出现的错误:

在这段代码里面,我愿意是这样一个流程:

申请内存

while ( 读数据 )
{
   将读出来的数据指针加入到链表
   再申请内存【准备接受下一次读的数据】
}

删除最后一次多申请的内存【至于前面申请的我会在程序退出时一块释放】


论坛上一些兄弟说因为内循环和外循环的变量相同导致了调试结果不正确,可是我这里因为要循环读数据,
那么如果修改了内循环的变量名称,就会导致下一次while循环无法将新读的数据放到新申请的内存,后来
有个兄弟提醒我“ 循环内变量不要重新定义,每次new即可”,我猛然发现,这里写错了:

在while循环里面
while ( f.Read(&tInfo, sizeof(HOSTINFO)) == sizoef(HOSTINFO))
{
    PHOSTINFO pInfo = new HOSTINFO;
    ZeroMemory(pInfo, sizoef(HOSTINFO);
    
    memcpy(pInfo, &tInfo, sizeof(HOSTINFO));
    // do something
}

这个

PHOSTINFO pInfo = new HOSTINFO;

应该改为:
pInfo = new HOSTINFO;

因为如果前面再加一个PHOSTINFO就相当于重新定义了一个变量,而我的本意是要用同一个指针在完成一次读数据之后,指向新分配的内存,然后再将新的数据读入到新分配的内存, 如果重新定义的话,显然是违背了这个意思。
而如果不重新定义的话,在while循环里面pInfo = new HOSTINFO;
只是把外面定义的指针pInfo指向了新的内存,这样就能达目的。

后来一个兄弟提出了这样的读数据方法,我觉得很有借鉴意义:

int iRecordCount = file.GetLength()%sizeof(HOSTINFO)?file.GetLength()/sizeof(HOSTINFO) + 1 : file.GetLength()/sizeof(HOSTINFO); //根据文件长度确定结构个数

PHOSTINFO pInfo[iRecordCount];
//分配
for ( int i = 0; i < iRecordCount; i++ )
{
   pInfo[i] = new HOSTINFO;
   ZeroMemory(pInfo[i], sizeof(HOSTINFO));
}
file.Read(pInfo[0], sizeof(HOSTINFO) * iRecordCount); //可以一次性读完

这个根据文件长度和结构大小确定结构个数,然后根据结构个数和大小循环分配内存,最后,一次性读完所有数据到分配的内存,这个方法相当不错。不过,需要注意的是, CFile::Read应该有最大读取数据的限制的,如果超过了,也可能导致读取失败。

阅读(4729) | 评论(0) | 转发(0) |
0

上一篇:最近很无聊

下一篇:CFile::Read读文件问题

给主人留下些什么吧!~~