fscanf读取INI文件时键名部分重合问题
2011-11-12 16:50
211 查看
公司以前的项目中有的是用fscanf来读取INI文件,这会产生不少问题,键名部分重合便是一个不常出现,但可能出现的问题。
这里指的键名部分重合是指在同一节(Section)中,键名间出现类似如下情况:
NameAltitude=100
Sort=10
NameOffsetY=20
以上3个字段均是可选项,其中NameAltitude和NameOffsetY的第一个单词出现了重合。NameOffsetY是后来功能需要再添加上去。使用fscanf读取INI文件数据相关代码如下:
bool bSucRead = true;
// ...
// ...
// ...
// 读取必选键值-Begin
bSucRead &= fscanf(fp, "Name=%s\n", pInfo->szName);
bSucRead &= fscanf(fp, "SizeAdd=%d\n", &pInfo->nSizeAdd);
// ...
// ...
// ...
// 读取必选键值-End
// 读取可选键值-Begin
// ...
// ...
// ...
if (!fscanf(fp, "NameAltitude=%d\n", &pInfo->nNameAltitude))
{
pInfo->nNameAltitude = 0;
}
if (!fscanf(fp, "Sort=%d\n", &pInfo->nSort))
{
pInfo->nSort = 0;
}
if (!fscanf(fp, "NameOffsetY=%d\n", &pInfo->nNameOffsetY))
{
pInfo->nNameOffsetY = 0;
}
// ...
// ...
// ...
// 读取可选键值-End
当有NameOffsetY前面至少有NameAltitude存在时,如下:
[003]
Name=monster
SizeAdd=23
...
...
...
NameAltitude=123
Sort=14
NameOffsetY=20
或者
[022]
Name=monster
SizeAdd=23
...
...
...
NameAltitude=123
NameOffsetY=20
此时数据读取正常。
而当从NameAltitude到NameOffsetY之前的字段都不存在时,如下:
[041]
Name=monster
SizeAdd=23
...
...
...
NameOffsetY=25
NameOffsetY读取失败,pInfo->nNameOffsetY被赋予默认值0,而不是25。
当文件指针走到"NameOffsetY"前时,fscanf却在准备读取"NameAltitude",结果前面的"Name"被读取了,然而到后面才发现读取错误,但文件指针已经走到"Altitude"前了。fscanf继续往后判断,读取"NameOffsetY"必然是失败的,因此pInfo->nNameOffsetY被赋予默认值0。
解决方案一:使用GetPrivateProfileInt、GetPrivateProfileInt等WIN32 API函数来读取INI文件。
解决方案二:使用现有框架下的CMyIni读取INI文件。
解决方案三:在发现读取错误后,让文件指针退会正确位置,可使用ftell和fseek来实现:
// 调整文件指针位置
inline bool AdjustFilePtrPos(FILE* fp, long lPosBeforeOffset)
{
if (NULL != fp)
{
long lOffset = ftell(fp) - lPosBeforeOffset;
if (0 < lOffset)
{
fseek(fp, -lOffset, SEEK_CUR);
return true;
}
}
return false;
}
//....
//....
//....
long lPosBeforeOffset = ftell(fp); // 记录文件指针出错前位置
if (!fscanf(fp, "NameAltitude=%d\n", &pInfo->nNameAltitude))
{
pInfo->nNameAltitude = 0;
AdjustFilePtrPos(fp, lPosBeforeOffset); // 调整文件指针位置
}
//....
//....
//....
这里指的键名部分重合是指在同一节(Section)中,键名间出现类似如下情况:
NameAltitude=100
Sort=10
NameOffsetY=20
以上3个字段均是可选项,其中NameAltitude和NameOffsetY的第一个单词出现了重合。NameOffsetY是后来功能需要再添加上去。使用fscanf读取INI文件数据相关代码如下:
bool bSucRead = true;
// ...
// ...
// ...
// 读取必选键值-Begin
bSucRead &= fscanf(fp, "Name=%s\n", pInfo->szName);
bSucRead &= fscanf(fp, "SizeAdd=%d\n", &pInfo->nSizeAdd);
// ...
// ...
// ...
// 读取必选键值-End
// 读取可选键值-Begin
// ...
// ...
// ...
if (!fscanf(fp, "NameAltitude=%d\n", &pInfo->nNameAltitude))
{
pInfo->nNameAltitude = 0;
}
if (!fscanf(fp, "Sort=%d\n", &pInfo->nSort))
{
pInfo->nSort = 0;
}
if (!fscanf(fp, "NameOffsetY=%d\n", &pInfo->nNameOffsetY))
{
pInfo->nNameOffsetY = 0;
}
// ...
// ...
// ...
// 读取可选键值-End
当有NameOffsetY前面至少有NameAltitude存在时,如下:
[003]
Name=monster
SizeAdd=23
...
...
...
NameAltitude=123
Sort=14
NameOffsetY=20
或者
[022]
Name=monster
SizeAdd=23
...
...
...
NameAltitude=123
NameOffsetY=20
此时数据读取正常。
而当从NameAltitude到NameOffsetY之前的字段都不存在时,如下:
[041]
Name=monster
SizeAdd=23
...
...
...
NameOffsetY=25
NameOffsetY读取失败,pInfo->nNameOffsetY被赋予默认值0,而不是25。
当文件指针走到"NameOffsetY"前时,fscanf却在准备读取"NameAltitude",结果前面的"Name"被读取了,然而到后面才发现读取错误,但文件指针已经走到"Altitude"前了。fscanf继续往后判断,读取"NameOffsetY"必然是失败的,因此pInfo->nNameOffsetY被赋予默认值0。
解决方案一:使用GetPrivateProfileInt、GetPrivateProfileInt等WIN32 API函数来读取INI文件。
解决方案二:使用现有框架下的CMyIni读取INI文件。
解决方案三:在发现读取错误后,让文件指针退会正确位置,可使用ftell和fseek来实现:
// 调整文件指针位置
inline bool AdjustFilePtrPos(FILE* fp, long lPosBeforeOffset)
{
if (NULL != fp)
{
long lOffset = ftell(fp) - lPosBeforeOffset;
if (0 < lOffset)
{
fseek(fp, -lOffset, SEEK_CUR);
return true;
}
}
return false;
}
//....
//....
//....
long lPosBeforeOffset = ftell(fp); // 记录文件指针出错前位置
if (!fscanf(fp, "NameAltitude=%d\n", &pInfo->nNameAltitude))
{
pInfo->nNameAltitude = 0;
AdjustFilePtrPos(fp, lPosBeforeOffset); // 调整文件指针位置
}
//....
//....
//....
相关文章推荐
- flash中 读取XML的问题[xml部分]
- flash中读取XML问题[FLASH AS 部分]
- Utf-8+Bom编码导致的读取数据部分异常问题
- 关于QT5读取ini文件中文乱码问题
- 关于读取INI文件的API问题
- DataInputStream读取文件流时部分乱码问题
- pe_xscan 新增加对一个较少见的启动项的扫描,DIY了INI文件读取部分
- 解决WebService中调用dll读取不到ini文件的问题
- c#读取ini文件时遇到的问题
- 解决部分乱七八糟的厂商SD卡路径乱放导致无法读取的问题
- java的SSM框架整合时Tomcat循环读取错误bean重合小问题
- 读取Excel的部分问题
- Java的部分问题和小结
- 关于php读取数据库以及网页显示问题
- C# 读取EXCEL文件出现数据丢失问题
- 使用canvas.clipPath来裁剪时部分机型出现问题
- CentOs 安装 Redmine 部分问题解决
- win7环境Eclipse中运行JAVA项目读取HDFS(hadoop-2.7.2)中的文件实例与问题汇总
- 【求助】二进制图片读取的问题。'System.Data.Linq.Binary' to type 'System.Byte[]'
- 创建springboot项目时 yml或application.properties无效或无法读取的问题