舍得英语魔法学苑

 找回密码
 注册
查看: 7783|回复: 13

SMPAK 文件的打包功能( c# )

  [复制链接]
  • TA的每日心情
    慵懒
    前天 08:29
  • 签到天数: 470 天

    [LV.9]以坛为家II

    feng850113 发表于 2012-6-10 20:45:32 | 显示全部楼层 |阅读模式
    最近有空,研究了一下 Supermemo Ux 的 SMPAK 文件,主要是想让  IPhone 中的 Supermeo 课程有发声功能,基于论坛中各位高手对 SMPak 的研究,本人用 C# 写了个小工具,可以将 PC 中的 Supermeo UX 课程打包成能在 IPhone 中使用的课程文件,以下是打包功能的源代码,供各位参考,随便写的,各位高手别笑。

    打包的代码:
    1. private void btn_pack_Click(object sender, EventArgs e)
    2.         {

    3.             string scanpath = txb_filepath.Text; // 如:F:\英语学习\SuperMemoUX\新概念英语2
    4.             string overrideDirPath = scanpath + "\\override";
    5.             string savepath = txb_savePath.Text; //打包文件存放地址
    6.             string savefile = "";
    7.             if (!string.IsNullOrEmpty(guid))
    8.             {
    9.                 //savefile = savepath + "\\" + guid + ".smpak"; //不用此guid
    10.                 savefile = savepath + "\\course.smpak";
    11.             }
    12.             else
    13.             {
    14.                 savefile = savepath + "\\course.smpak";
    15.             }
    16.             BinaryWriter binwr = new BinaryWriter(File.Open(savefile, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite));
    17.             if (binwr.BaseStream.Position > 0)
    18.             {
    19.                 binwr.BaseStream.Seek(0, SeekOrigin.Begin);
    20.             }

    21.             //header
    22.             binwr.Write(System.Text.Encoding.ASCII.GetBytes("-SMArch-"));
    23.             binwr.Write((short)0x101); //版本
    24.             binwr.Write((short)0); //flag
    25.             uint entrchnk_Location = 0;
    26.             uint nameChnk_Location = 0;
    27.             binwr.Write(entrchnk_Location);// 值在最后补上
    28.             binwr.Write(nameChnk_Location); //值在最后补上

    29.             //data 区
    30.             List<EntrChnkInfo> entrchnkInfoList = new List<EntrChnkInfo>();
    31.             entrchnkInfoList.Clear();

    32.             StringBuilder sb_fileNames = new StringBuilder();
    33.             sb_fileNames.Clear();

    34.             foreach (var item in fileNameList)
    35.             {//fileNameList 为 override 文件夹下的所有文件清单

    36.                 //fullName 转成短名
    37.                 string short_fileName = item.Replace(overrideDirPath + "\\", "")
    38.                                                     .ToLower()
    39.                                                     .Replace("\\", "/"); //文件名
    40.                 bool zip = short_fileName.EndsWith(".xml") || short_fileName.EndsWith(".css") ? true : false;
    41.                 short nameLength = (short)short_fileName.Length; //文件长度
    42.                 uint nameoffset = (uint)sb_fileNames.Length; // 文件相对位置
    43.                 sb_fileNames.Append(short_fileName + "|");

    44.                 byte[] fileData = GetFileData(item); //读取文件,获取 Data Byte
    45.                 if (zip)
    46.                 {//需压缩
    47.                     fileData = pub_function.Compress(fileData);
    48.                 }

    49.                 uint dataLength = (uint)fileData.Length; //内容长度
    50.                 binwr.Write(System.Text.Encoding.ASCII.GetBytes("DataChnk"));
    51.                 uint dataLocation = (uint)binwr.BaseStream.Position; // 内容区的位置
    52.                 binwr.Write(fileData);

    53.                 entrchnkInfoList.Add(new EntrChnkInfo
    54.                 {
    55.                     nameoffset = nameoffset,
    56.                     nameLength = nameLength,
    57.                     flag = zip ? (short)0x1 : (short)0x0,
    58.                     dataLocation = dataLocation,
    59.                     dataLength = dataLength
    60.                 });
    61.             }

    62.             //读取原course.smpak中包含的模板文件,将其保存到打包文件中
    63.             string coursefilepath = scanpath + "\\course.smpak";            
    64.             List<TemplateFileInfo> templates = GetTemplateFile(coursefilepath); //获取 Template 内容
    65.             foreach (var item in templates)
    66.             {
    67.                 binwr.Write(System.Text.Encoding.ASCII.GetBytes("DataChnk"));
    68.                 uint dataLocation = (uint)binwr.BaseStream.Position; // 内容区的位置
    69.                 uint dataLength = (uint)item.TemplateData.Length;
    70.                 binwr.Write(item.TemplateData);
    71.                 short zip = item.flag;
    72.                 short nameLength = (short)item.TemplateName.Length; //文件长度
    73.                 uint nameoffset = (uint)sb_fileNames.Length; // 文件相对位置
    74.                 sb_fileNames.Append(item.TemplateName + "|");
    75.                 entrchnkInfoList.Add(new EntrChnkInfo
    76.                 {
    77.                     nameoffset = nameoffset,
    78.                     nameLength = nameLength,
    79.                     flag = zip ,
    80.                     dataLocation = dataLocation,
    81.                     dataLength = dataLength
    82.                 });
    83.             }


    84.             //配置EntrChnk区
    85.             binwr.Write(System.Text.Encoding.ASCII.GetBytes("EntrChnk"));//EntrChnk 标识区
    86.             entrchnk_Location = (uint)binwr.BaseStream.Position;//entrchnkLocation
    87.             binwr.Write(entrchnkInfoList.Count);//词条数,其实是文件总数
    88.             foreach (var item in entrchnkInfoList)
    89.             {
    90.                 binwr.Write(item.nameoffset);
    91.                 binwr.Write(item.nameLength);
    92.                 binwr.Write(item.flag);
    93.                 binwr.Write(item.dataLocation);
    94.                 binwr.Write(item.dataLength);
    95.             }

    96.             //NameChnk区
    97.             binwr.Write(System.Text.Encoding.ASCII.GetBytes("NameChnk"));
    98.             nameChnk_Location = (uint)binwr.BaseStream.Position;//名称偏移值
    99.             binwr.Write(sb_fileNames.Length);//写名称长度
    100.             //byte[] checkSN = pub_function.Get_CheckSN(sb_fileNames.Length); //不用生成 Check SN
    101.             //binwr.Write(checkSN);
    102.             binwr.Write(sb_fileNames.ToString()); //此方法会自动在头部添加 check SN

    103.             //补上头部偏移值
    104.             binwr.BaseStream.Position = 12;
    105.             binwr.Write(entrchnk_Location);
    106.             binwr.Write(nameChnk_Location);
    107.             binwr.Close();
    108.             binwr.Dispose();
    109.             binwr = null;

    110.             MessageBox.Show("已完成!");
    111.         }
    复制代码

    评分

    1

    查看全部评分

  • TA的每日心情
    慵懒
    前天 08:29
  • 签到天数: 470 天

    [LV.9]以坛为家II

     楼主| feng850113 发表于 2012-6-10 22:45:53 | 显示全部楼层
    压缩及解压部分:
    1. /// <summary>
    2.         /// 解压缩
    3.         /// </summary>
    4.         /// <param name="data">字节数组</param>
    5.         /// <returns>解压后的字节数组</returns>
    6.         public static byte[] Decompress( byte[] data)
    7.         {
    8.             Stream stm = new MemoryStream(data);
    9.             DeflateStream dfs = new DeflateStream(stm, CompressionMode.Decompress);
    10.             
    11.             int nSize = 100;
    12.             List<byte> resultList = new List<byte>();
    13.             resultList.Clear();
    14.             byte[] result = new byte[nSize];
    15.             int offset = 0;
    16.             int totalCount = 0;
    17.             while (true)
    18.             {
    19.                 int bytesRead = dfs.Read(result, 0, 100);
    20.                 if (bytesRead == 0)
    21.                 {
    22.                    break;
    23.                 }
    24.                 else
    25.                 {
    26.                     for (int i = 0; i < bytesRead; i++)
    27.                     {
    28.                         resultList.Add(result[i]);
    29.                     }
    30.                     result = new byte[nSize];
    31.                 }

    32.                 offset += bytesRead;
    33.                 totalCount += bytesRead;
    34.             }

    35.             return resultList.ToArray();

    36.         }


    37.         /// <summary>
    38.         /// 压缩
    39.         /// </summary>
    40.         /// <param name="data">字节数组</param>
    41.         /// <returns>压缩后的字节数组</returns>
    42.         public static byte[] Compress(byte[] data)
    43.         {
    44.             using (var outStream = new MemoryStream())
    45.             {
    46.                 using (var compress = new DeflateStream(outStream, CompressionMode.Compress, true))
    47.                 {
    48.                     compress.Write(data, 0, data.Length);
    49.                     compress.Flush();
    50.                     compress.Close();
    51.                 }
    52.                 return outStream.ToArray();
    53.             }
    54.         }
    复制代码
  • TA的每日心情
    慵懒
    2018-2-26 22:15
  • 签到天数: 1705 天

    [LV.Master]伴坛终老

    yshumy 发表于 2012-6-11 00:20:21 | 显示全部楼层
    楼主既授人以鱼又授人以渔, 令人敬佩!
  • TA的每日心情
    慵懒
    2014-10-31 00:00
  • 签到天数: 44 天

    [LV.5]常住居民I

    mcmib 发表于 2012-6-11 01:13:42 | 显示全部楼层
    ,也就是说,有了这个程序,IPAD,IPHONE上就可以实现允许UX上的带语音的课件了是吧?
    太好了,就等国行牛排上市了
  • TA的每日心情
    郁闷
    2016-1-6 14:50
  • 签到天数: 289 天

    [LV.8]以坛为家I

    随风 发表于 2012-6-11 01:27:21 | 显示全部楼层
    论坛高人越来越多,大家有福了。能否弄成软件形式 ,让我等不会编程的也有福使用。
  • TA的每日心情
    奋斗
    2012-11-12 10:34
  • 签到天数: 23 天

    [LV.4]偶尔看看III

    ifree128 发表于 2012-6-11 20:24:08 | 显示全部楼层
    不越狱,smpak的课程可以上传到iphone吗?
  • TA的每日心情
    开心
    2012-9-22 10:12
  • 签到天数: 11 天

    [LV.3]偶尔看看II

    z91172129 发表于 2012-6-17 03:14:22 | 显示全部楼层
    一直在等,谢谢,但是不会用
  • TA的每日心情
    奋斗
    2015-12-6 17:15
  • 签到天数: 56 天

    [LV.5]常住居民I

    huyus51 发表于 2012-6-22 19:16:00 | 显示全部楼层
    期待把软件发布出来呀
  • TA的每日心情

    2018-1-27 18:22
  • 签到天数: 118 天

    [LV.6]常住居民II

    关羽青龙 发表于 2012-6-24 21:26:10 | 显示全部楼层
    C#确实不会用···········期待进一步改进
  • TA的每日心情
    奋斗
    2018-4-13 11:18
  • 签到天数: 37 天

    [LV.5]常住居民I

    hlh 发表于 2012-7-2 14:27:53 | 显示全部楼层
    要是转成QA格式的txt就更好了
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    小黑屋|手机版|Archiver|官方微博|官方QQ群|舍得英语魔法学苑 ( 冀ICP备11024081号-1 )

    GMT+8, 2018-5-20 17:49 , Processed in 0.166633 second(s), 20 queries .

    Powered by Discuz! X3.2

    © 2001-2013 Comsenz Inc.

    快速回复 返回顶部 返回列表