/***************************************************************
* 函数名称:函数analyzeXml会把XML格式文档格式化成标准缩进格式
每次缩进4个空格
* 功能描述:会把XML格式文档格式化成标准缩进格式
每次缩进4个空格
* 局限性: 对'>'和'<'之间的所有字符全部删除,比如换行符,空格等。
为避免数据泥团,使用struct varWork类型
* 输入参数:
varWork &p = struct varWork类型
返回参数:
int 值0 ,代表正常结束;
* 外部依赖:
* 写作时间:2011.05.31 1.0版
* 修改时间:2011.05.31 1.1版
2011.05.31 1.2版,修正layer初始化值为-1,相当于重新确认root为第二行<...>节点,而不是第一行<?...?>
2011.05.31 1.3版,修正类型:<!....>,包括<![CDATA[....]]>,不再进行区分
* 用法举例:
int main(string DestDir,string strRet,string model = "r")
{
char* file1 = "E://RES//try.xml";
char* Dir = file1;
if ( getFileChar(Dir) == 0 )
{
printf("analyzeXml is success./n");
}
else
{
printf("analyzeXml is fail./n");
}
system("pause");
return 0;
}
*
****************************************************************/
#include <iostream>
#include <io.h>
#include <sys/utime.h>
using namespace std;
enum direction{Left,Right};
struct varWork
{
//当前处理字符
char ch;
//缓冲字符
char buffer;
//查找目标类型,Left代表查找'<';Right代表查找'>'
direction type;
//信号量,0代表直接写入字符;1代表暂缓写入'<'字符;2代表写入endl、space*缩进数、"<X"字符
int signal;
//数据元素所在嵌套层次,初始化为0
int layer;
//本次'<'前,应该缩进的空格数,当出现</...>时会和layer不对应(元素结束行和元素起始行保持一致)
int numSpace;
}p = {0,0,Left,0,-1,0};
//结构类型定义,结构变量;#include <sys/stat.h>的struct stat结构是stat函数可以返回的结构,
//里面包括文件的全部属性。返回值:若成功则返回0,失败则返回-1
struct stat s_buf;
//函数getFileChar负责按每个字符读写文件,文件级操作
int getFileChar (char *path);
//函数analyzeXml负责判断,把CR或LF格式转换成CR/LF文件格式
int analyzeXml(varWork &p);
int getFileChar (char *path )
{
FILE *in, *out; //指向文件的指针,即FILE*文件流(管道应用);in用来读入,out用来输出。
bool status = true;//表示已经出错状态,初始化为false,即暂时没出错。
//缓冲临时文件路径,16字符的数组temppath,实际上除了结束符占一个字符外,只能存取15字符.
char temppath [16];
struct _utimbuf ut_buf; //在Windows NT和Windows95下,你可以改变utimbuf结构中的访问时间和修改时间。用来设定文件属性
//建立一个临时文件。
strcpy (temppath, "./clntmp");//把src所指由NULL结束的字符串复制到dest所指的数组中。
strcat (temppath, "XXXXXX");//功能:把src所指字符串添加到dest结尾处(覆盖dest结尾处的'/0')并添加'/0'。
mktemp (temppath);//mktemp()用来产生唯一的临时文件名。参数template所指的文件名称字符串中最后六个字符必须是XXXXXX。产生后的文件名会借字符串指针返回。
// 返回值: 文件顺利打开后,指向该流的文件指针就会被返回。如果文件打开失败则返回NULL,并把错误代码存在errno中。
//---打开文件----------------------------------------------------------------------
if ((in=fopen (path, "rb")) == NULL)
{
//如果in等于NULL,即(FILE *) 0,表示打开文件失败,
status = false;
}
else if ((out=fopen (temppath, "wb")) == (FILE *) NULL)
{
//如果out等于NULL,即(FILE *) 0,表示打开文件失败,
//fclose(in)善后处理,取消本次不成功流程
fclose (in);
status = false;
}
else
{
//---开始转化,对每个字符进行遍历,处理后将写入临时文件----------------------------------------------------
while ((p.ch = getc (in)) != EOF)
{
// 当ch也就是getc(in)的返回值不等于EOF文件尾结束符时,进行该循环;
// getc功 能: 从流中取一个字符进行处理
analyzeXml(p);
switch (p.signal)
{
case 0:
//直接写入字符
putc(p.ch, out);
if ( p.ch == '>')
{
p.signal = 1;
}
break;
case 1:
//暂缓写入,直至'<'字符解析完毕
break;
case 2:
//排除第一行<?xml version="1.0" encoding="UTF-8" ?>前面出现空行的情况
if ( p.ch != '?')
{
//代表写入endl、space*缩进数、"<X"字符
//DOS换行符
putc(0x0D, out);
putc(0x0A, out);
//缩进指定空格数
for (int i = 0; i < p.numSpace; ++i)
{
putc(' ', out);
}
}
//写入"<X"字符
putc('<', out);
putc(p.ch, out);
//清空信号量,等待下次进入
p.signal = 0;
//修改查找类型,转为查找'>'
p.type = Right;
break;
default:
printf("there may be one error in getFileChar./n");
break;
}
} // while 结束,文件转化完毕
printf("analyzeXml is success./n");
} // else 结束
//fclose若关闭文件动作成功则返回0,有错误发生时则返回EOF。流成功关闭,fclose 返回 0,否则返回EOF(-1)。
if (fclose (in) == EOF)
{
status = false; //表示已经出错状态
}
if (fclose (out) == EOF)
{
status = false; //表示已经出错状态
}
//---后期处理----------------------------------------------------------------------
ut_buf.actime = s_buf.st_atime; //最后一次访问的时间
ut_buf.modtime = s_buf.st_mtime;//文件内容最后一次被更改的时间
if (_utime (temppath, &ut_buf) == -1)//修改文件属性出错
//#include <time.h> int utime(const char pathname, const struct utimbuf *times);返回值:成功返回0,失败返回-1
status = false; //表示已经出错状态
//原子性:1、删除原文件(成功);2、重名名临时文件为原文件(成功);3;删除临时文件(成功)---->成功
// 1、删除原文件(成功);2、重名名临时文件为原文件(失败)---->出错提示,失败
// 1、删除原文件(失败);2、删除临时文件---->失败
//1、删除原文件,用unlink()函数来清除临时文件path,即删除原文件,成功返回0,失败返回-1。
if (unlink (path) == 0 )
{
//删除原文件(成功)
//2、重名名临时文件为原文件
if ( rename (temppath,path) == 0 )
{
//3;删除临时文件
unlink (temppath);//转换成功结束
}
else
{
//重命名出错提示
fprintf (stderr, "Unix2Dos: Problems renaming '%s' to '%s'./n", temppath, path);
fprintf (stderr, " However, file '%s' remains./n", temppath);
status = false;
}
}
else
{
//删除原文件(失败)
//删除临时文件
unlink (temppath);//用unlink()函数来清除临时文件temppath,即删除原文件,成功返回0,失败返回-1。
status = false; //出错状态,函数返回true。
}
return status ? 0 : 1;
}
int analyzeXml(varWork &p)
{
//恢复正常缩进空格数
p.numSpace = 4 * p.layer;
switch ( p.type )
{
case Left:
if ( p.ch == '<')
{
//开头<?.........?>,需要把信号量从0置为1,否则会多出一个<
p.signal = 1;
}
else if ( p.buffer == '<' )
{
//已经存在'<',做后续判断
switch ( p.ch)
{
case '?':
//类型:<?
//layer、numSpace保持不变
break;
case '/':
//类型:</
//layer减1,numSpace不减,元素结束行和元素起始行保持一致
p.layer -= 1;
break;
case '!':
//类型:<!....>,包括<![CDATA[....]]>
//layer保持不变,numSpace增4
p.numSpace += 4;
break;
default:
//其他类型:<t...
//layer增1,numSpace增4
p.layer += 1;
p.numSpace += 4;
break;
}
//修改信号量,可以写入
p.signal = 2;
}
break;
case Right:
if (p.ch == '>')
{
//按p.buffer进行判断
switch (p.buffer)
{
case '/':
//类型:/>
//layer减1,numSpace减4
p.layer -= 1;
p.numSpace -= 4;
break;
case '?':
//类型:?>
//layer,numSpace保持不变
break;
// case ']':
// //类型:<!....>,包括<![CDATA[....]]>,不再进行区分
// //layer减1,numSpace减4
// p.layer -= 1;
// p.numSpace -= 4;
// break;
default:
//其他类型:...t>
//layer,numSpace保持不变
break;
}
//修改查找类型,转为查找'<'
p.type = Left;
}
break;
default:
printf("there may be one error in analyzeXml./n");
break;
}
//缓冲字符,为"?>"类型作判断依据
p.buffer = p.ch;
return 0;
}
/***************************************************************
* 函数名称:函数EnxXml会把XML格式文档还原成Enx特定格式文件
* 功能描述:会把XML格式文档还原成Enx特定格式文件
* 局限性: 对'>'和'<'之间的所有字符全部删除,比如换行符,空格等。
为避免数据泥团,使用struct varWork类型
* 输入参数:
varWork &p = struct varWork类型
返回参数:
int 值0 ,代表正常结束;
* 外部依赖:
* 写作时间:2011.05.31 1.0版
* 修改时间:2011.05.31 1.1版
* 用法举例:
int main(string DestDir,string strRet,string model = "r")
{
char* file1 = "E://RES//try.xml";
char* Dir = file1;
if ( getFileChar(Dir) == 0 )
{
printf("EnxXml is success./n");
}
else
{
printf("EnxXml is fail./n");
}
system("pause");
return 0;
}
*
****************************************************************/
#include <iostream>
#include <io.h>
#include <sys/utime.h>
using namespace std;
enum direction{Left,Right};
struct varWork
{
//当前处理字符
char ch;
//缓冲字符
char buffer;
//查找目标类型,Left代表查找'<';Right代表查找'>'
direction type;
//信号量,0代表直接写入字符;1代表暂缓写入'<'字符;2代表写入endl、space*缩进数、"<X"字符
int signal;
//数据元素所在嵌套层次,初始化为0
int layer;
//本次'<'前,应该缩进的空格数,当出现</...>时会和layer不对应(元素结束行和元素起始行保持一致)
int numSpace;
}p = {0,0,Left,0,0,0};
//结构类型定义,结构变量;#include <sys/stat.h>的struct stat结构是stat函数可以返回的结构,
//里面包括文件的全部属性。返回值:若成功则返回0,失败则返回-1
struct stat s_buf;
//函数getFileChar负责按每个字符读写文件,文件级操作
int getFileChar (char *path);
//函数EnxXml负责判断,把CR或LF格式转换成CR/LF文件格式
int EnxXml(varWork &p);
int getFileChar (char *path )
{
FILE *in, *out; //指向文件的指针,即FILE*文件流(管道应用);in用来读入,out用来输出。
bool status = true;//表示已经出错状态,初始化为false,即暂时没出错。
//缓冲临时文件路径,16字符的数组temppath,实际上除了结束符占一个字符外,只能存取15字符.
char temppath [16];
struct _utimbuf ut_buf; //在Windows NT和Windows95下,你可以改变utimbuf结构中的访问时间和修改时间。用来设定文件属性
//建立一个临时文件。
strcpy (temppath, "./clntmp");//把src所指由NULL结束的字符串复制到dest所指的数组中。
strcat (temppath, "XXXXXX");//功能:把src所指字符串添加到dest结尾处(覆盖dest结尾处的'/0')并添加'/0'。
mktemp (temppath);//mktemp()用来产生唯一的临时文件名。参数template所指的文件名称字符串中最后六个字符必须是XXXXXX。产生后的文件名会借字符串指针返回。
// 返回值: 文件顺利打开后,指向该流的文件指针就会被返回。如果文件打开失败则返回NULL,并把错误代码存在errno中。
//---打开文件----------------------------------------------------------------------
if ((in=fopen (path, "rb")) == NULL)
{
//如果in等于NULL,即(FILE *) 0,表示打开文件失败,
status = false;
}
else if ((out=fopen (temppath, "wb")) == (FILE *) NULL)
{
//如果out等于NULL,即(FILE *) 0,表示打开文件失败,
//fclose(in)善后处理,取消本次不成功流程
fclose (in);
status = false;
}
else
{
//---开始转化,对每个字符进行遍历,处理后将写入临时文件----------------------------------------------------
while ((p.ch = getc (in)) != EOF)
{
// 当ch也就是getc(in)的返回值不等于EOF文件尾结束符时,进行该循环;
// getc功 能: 从流中取一个字符进行处理
EnxXml(p);
switch (p.signal)
{
case 0:
//直接写入字符
putc(p.ch, out);
if ( p.ch == '>')
{
//清理掉'>'、'<'之间的换行符、空格等字符
p.signal = 1;
}
break;
case 1:
//暂缓写入,直至'<'字符解析完毕
break;
default:
printf("there may be one error in getFileChar./n");
break;
}
} // while 结束,文件转化完毕
printf("EnxXml is success./n");
} // else 结束
//fclose若关闭文件动作成功则返回0,有错误发生时则返回EOF。流成功关闭,fclose 返回 0,否则返回EOF(-1)。
if (fclose (in) == EOF)
{
status = false; //表示已经出错状态
}
if (fclose (out) == EOF)
{
status = false; //表示已经出错状态
}
//---后期处理----------------------------------------------------------------------
ut_buf.actime = s_buf.st_atime; //最后一次访问的时间
ut_buf.modtime = s_buf.st_mtime;//文件内容最后一次被更改的时间
if (_utime (temppath, &ut_buf) == -1)//修改文件属性出错
//#include <time.h> int utime(const char pathname, const struct utimbuf *times);返回值:成功返回0,失败返回-1
status = false; //表示已经出错状态
//原子性:1、删除原文件(成功);2、重名名临时文件为原文件(成功);3;删除临时文件(成功)---->成功
// 1、删除原文件(成功);2、重名名临时文件为原文件(失败)---->出错提示,失败
// 1、删除原文件(失败);2、删除临时文件---->失败
//1、删除原文件,用unlink()函数来清除临时文件path,即删除原文件,成功返回0,失败返回-1。
if (unlink (path) == 0 )
{
//删除原文件(成功)
//2、重名名临时文件为原文件
if ( rename (temppath,path) == 0 )
{
//3;删除临时文件
unlink (temppath);//转换成功结束
}
else
{
//重命名出错提示
fprintf (stderr, "Unix2Dos: Problems renaming '%s' to '%s'./n", temppath, path);
fprintf (stderr, " However, file '%s' remains./n", temppath);
status = false;
}
}
else
{
//删除原文件(失败)
//删除临时文件
unlink (temppath);//用unlink()函数来清除临时文件temppath,即删除原文件,成功返回0,失败返回-1。
status = false; //出错状态,函数返回true。
}
return status ? 0 : 1;
}
int EnxXml(varWork &p)
{
switch ( p.type )
{
case Left:
if ( p.ch == '<')
{
//开始正常写入
p.signal = 0;
//修改查找类型,转为查找'>'
p.type = Right;
}
break;
case Right:
if ( p.ch == '>')
{
//修改查找类型,转为查找'<'
p.type = Left;
}
break;
default:
printf("there may be one error in EnxXml./n");
break;
}
return 0;
}