mac2dos换行从mac方式转dos方式

来源:互联网 发布:淘宝层级排名 编辑:程序博客网 时间:2024/06/05 07:13

/***************************************************************
 * 函数名称:函数getFileChar负责按每个字符读写文件,文件级操作
             函数mac2dos负责判断,把CR或LF格式转换成CR/LF文件格式
 * 功能描述:函数mac2dos负责把UINX文件格式转换成DOS文件格式
            原理:
   Dos和windows采用回车+换行CR/LF表示下一行,
   而UNIX/Linux采用换行符LF表示下一行,
            苹果机(MAC OS系统)则采用回车符CR表示下一行.

            本程序把CR 或 LF 的文本转换成CR/LF的文本

 * 局限性: 实现有缺漏,无法达到满意效果,如OD 00 OA 00情况没有考虑
            可对unix/linux/mac/dos混合的文件,进行转换,但会产生多个空行。
    
   因为之前是CR或LF,经转换后为0D000A00,这时接入的00是多余的,必须删除,否则会乱码。
   为FF时候就省去该换页符,即0C 00 不进入out流。
   深层次原因:中文总是从文件偶数个字符开始的,每两个字符表示一个汉字如,文:CE C4
   与英文字符在一块的CR/LF特殊状态是0D0A,与中文字符在一起的则是0D000A00.
   所以如果转换0D或0A后遇到的下一个字符是非00字符,那就表示是英文字母。
   如果转换0D或0A后遇到的下一个字符是00,那就表示是中文,可以删去该00。

 * 输入参数:
     char *path = "E://RES//1.txt"类型,待转换的文件绝对路径
 返回参数:
     int 值0  ,代表正常结束;值1  ,代表中途出现过问题;
 * 外部依赖:
 * 写作时间:2011.05.26 1.0版
 * 修改时间:2011.05.29 1.1版
 * 用法举例:
 
   int main(string  DestDir,string strRet,string model = "r")
   {
   char* file1 = "E://RES//1.txt";
   char* Dir = file1;
   if ( getFileChar(Dir) == 0 )
   {
   printf("mac2dos is success./n");
   }
   else
   {
   printf("mac2dos is fail./n");
   }
  
  system("pause");
  return 0;
}
 *
 ****************************************************************/

#include <iostream>
#include <io.h>
#include <sys/utime.h>
using namespace std;

const static int LF=0x0A;// 换行符,可以以int来写入文件流,就相当于以换行符输入文件流
const static int CR=0x0D;// 回车符,可以以int来写入文件流,就相当于以回车符输入文件流
const static int FF=0x0C;// 换页符, 走纸控制,可以以int来写入文件流,就相当于以换页符输入文件流
const static int ZERO=0x00;//null空字符,可以以int来写入文件流,就相当于以回车符输入文件流,
                      //因为putc只能输出一个字符,所以0D 00 或0A 00 转到0D 00 0A 00 就需要00输出一次了

//结构类型定义,结构变量;#include <sys/stat.h>的struct stat结构是stat函数可以返回的结构,
//里面包括文件的全部属性。返回值:若成功则返回0,失败则返回-1
struct stat s_buf;

//函数getFileChar负责按每个字符读写文件,文件级操作
int getFileChar (char *path);
//函数mac2dos负责判断,把CR或LF格式转换成CR/LF文件格式
int mac2dos(char ch,char buffer[],char &writebuffer,int &index,bool &isClear);

int getFileChar (char *path )
{
 FILE *in, *out; //指向文件的指针,即FILE*文件流(管道应用);in用来读入,out用来输出。
    bool status = true;//表示已经出错状态,初始化为false,即暂时没出错。
 
 char ch = 0x00,//当前处理字符
  prev_ch= 0x00;//prev_ch是用来指示重复字符
 //缓冲读取的字符,以便判读
 char buffer[4] = {'0','0','0','0'};
 //存在两个个连续CR时,需要用writebuffer缓存第二个CR
 char writebuffer = '0';
 int index = 0;
 //是否马上写入文件
 bool isClear = true;

 //缓冲临时文件路径,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 ((ch = getc (in)) != EOF)
  {
   // 当ch也就是getc(in)的返回值不等于EOF文件尾结束符时,进行该循环;
  // getc功 能: 从流中取一个字符进行处理

   mac2dos(ch, buffer,writebuffer,index,isClear);
   if (  isClear == true)
   {
    for ( int i = 0; i < index; ++i)
    {
          putc(buffer[i], out);
    }
    //本次写入结束
    index = 0;
   }
  } // while 结束,文件转化完毕
  
  printf("mac2dos 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 mac2dos(char ch,char buffer[],char &writebuffer,int &index,bool &isClear)
{
 //清空标志,然后处理时按需要自己决定是否需要即时写入文件
 isClear = true;

 //上次碰到连续两个CR的情况,处理writebuffer
 if ( writebuffer == CR )
 {
  buffer[0] = CR;
  index = 1;
  //writebuffer清空,只有在碰到连续两个CR才进入本语句块
  writebuffer = '0';
  isClear = false;
 }

 //程序缓存会在遇到CR临时存储不写入文件,遇到LF和其他字符时转换成CR/LF写入文件。
 buffer[index] = ch;
 ++index;

 switch ( ch )
 {
 case CR:
  if ( index == 1 )
  {
   //当前缓存只存在1个CR
   isClear = false;
  }
  else if ( index == 2 )
  {
   //当前缓存存在连续两个CR,可以释放一个CR,
   //第一个CR需要转换成CR/LF的DOS格式
   buffer[0] = CR;
   buffer[1] = LF;
   index = 2;
   //缓存第二个CR,下次处理
   writebuffer = CR;
   isClear = true;
  }

  break;
 case LF:
  if ( index == 1)
  {
   //buffer只缓存一个字符LF,需要转换成CR/LF的DOS格式
   buffer[0] = CR;
   buffer[1] = ch;
   index = 2;
   isClear = true;
  }
  if ( index == 2 && buffer[0] == CR && buffer[1] == LF )
  {
   //buffer中已经缓存CR,形成CR/LF,不需转换
   isClear = true;
  }
  break;
 case FF:
  //其他字符,会直接导致缓存的字符转换成CR/LF的DOS格式,清空效果
    //贯穿!
 case ZERO:
  //暂不处理
  //其他字符,会直接导致缓存的字符转换成CR/LF的DOS格式,清空效果
  //贯穿!
 default:
  //其他字符(包括FF、ZERO),会直接导致缓存的字符转换成CR/LF的DOS格式,清空效果
  
  if ( index == 1 )
  {
   //buffer未缓存其他字符
  }
  else if ( (index == 2) &&  (buffer[0] == CR) )
  {
   //buffer缓存字符CR,需要转换成CR/LF的DOS格式
   buffer[0] = CR;
   buffer[1] = LF;
   buffer[2] = ch;
   index = 3;
  }
  
  //缓冲区字符直接写入文件
  isClear = true; 

  break;
 }

 return 0;
}

原创粉丝点击