[C#.net]操作系统作业-模拟二级文件系统-开发日志

//开博题记: 接触编程两年多, 从没自己写过编程笔记, 偶尔会收藏些有用的文章, 但是都没整理过. 乱七八糟一大堆资料自己看起来也辛苦, 有必要把这些心得和资料整理记录下了, 留给自己以后查找, 也分享给各位学习者, 共同进步.

目标

  1. 设计一个简单的二级文件系统
  2.  实现下列命令(至少两个)
    • DELETE 删除文件
    • CLOSE 关闭文件
    • READ 读文件(显示出读的文件的内容)
    • WRITE 写文件(对原文件改写或添加内容,并显示修改后的文件内容)

概念


为了克服单级目录所存在的缺点, 可以为每一个用户建立一个单独的用户文件目录UFD(User File Directory). 这些文件目录具有相似的结构, 它由用户所有文件的文件控制块组成. 此外, 在系统中再建立一个主文件目录MFD(Master File Directory); 在主文件目录中,每个用户目录文件都占有一个目录项,其目录项中包括用户名和指向该用户目录文件的指针. 如下, 图中的主目录中示出了三个用户名,即Wang、Zhang和Gao.

[C#.net]操作系统作业-模拟二级文件系统-开发日志_第1张图片

 

 

实现方法

看到图片后我首先想到的是利用DataTable存数据的方法来模拟程序. 上图很显然可以做成一个表存用户信息, 一个表存文件信息. 文件信息表内通过外键约束辨别属于哪个用户的表, 这样就可以实现权限管理, 当前用户可以读写新建删除自己的文件, 只读其他用户创建的文件. 由于是模拟操作, 文件表内就直接保存文件名和文件内容, 所以表如下

User(user, password)

File(user, fileName, fileContent, fileTime)

有了表后, 我想实现的功能是首先一个界面, 用户可以登录或新建用户, 程序默认有一个超级管理员admin, 超级管理员可以操作所有用户的文件, admin不可删除以防用户删完后就不能操作文件. 登录后可以进行新建删除修改文件等操作, 关闭程序后, 数据保存到本地.

开发日志

第一个问题就是DataTable如何保存到本地, 保存到本地后如何读入程序. 找资料的时候发现, DataSet拥有ReadXml()和WriteXml()方法, 也就是说DateSet可以和Xml相互转换. 于是就写了一个DataSet的操作类, 读取Xml到DateSet内, 以及把DateSet内的DataTable保存到Xml内, 参考了DataSet实例之建立数据表和主外键约束里面初始化DateSet和Datatable写的方法.

/// 
        /// 加载表集合的时候如果有数据文件就直接读取, 没有就初始化一个
        /// 
        public void Load()
        {
            //判断根目录下是否存在文件
            if (File.Exists("MyFMS_DataS.xml"))
            {
                //存在的话就把文件读入到DataSet内
                ds.ReadXml("MyFMS_DataS.xml");

            }
            else
            {
                //初始化Datatable
                dtUser.Columns.Add("user", typeof(string));
                dtUser.Columns.Add("password", typeof(string));

                dtFile.Columns.Add("user", typeof(string));
                dtFile.Columns.Add("FileName", typeof(string));
                dtFile.Columns.Add("FileConrent", typeof(string));
                dtFile.Columns.Add("FileTime", typeof(string));

                //将两个内存表增加到Dataset对象ds的表集合中
                ds.Tables.Add(dtFile);
                ds.Tables.Add(dtUser);

                //初始化个超级管理员
                object[] add_dt = new object[2];
                add_dt[0] = "admin";
                add_dt[1] = "admin";

                Add(add_dt, "User");

                //初始化个超级管理员
                object[] add_dt2 = new object[4];
                add_dt2[0] = "admin";
                add_dt2[1] = "程序说明";
                add_dt2[2] = "本程序是用来模拟操作系统的二级文件管理系统\n\n概念:二级文件管理简单理解就是创建一个数组用来存储用户信息,每个数组元素在对应一个数组用来存储文件信息.管理员账户可以读写所有用户创建的文件,而特定的用户只能读写自己创建的文件,只读别人创建的文件.\n\n实现方式:本程序是利用两个Datatable, 一个用来存储用户资料(用户名, 密码), 另一张表用来存储文件信息(用户名, 文件名, 文件内容, 创建时间), 利用这两张表就可实现简单的二级文件模拟管理操作.\n\nby Cinwell";
                add_dt2[3] = DateTime.Now.ToString();

                Add(add_dt2, "File");

                设置主键和外键约束
                //UniqueConstraint uc = new UniqueConstraint("ucUser", ds.Tables["User"].Columns["user"], true);
                //ds.Tables["User"].Constraints.Add(uc);

                //ForeignKeyConstraint fc = new ForeignKeyConstraint("fcUser", ds.Tables["User"].Columns["User"], ds.Tables["File"].Columns["User"]);
                //ds.Tables["File"].Constraints.Add(fc);
                
                //保存DataSet
                Save();
            }
        }

        /// 
        /// 保存文件
        /// 
        public void Save()
        {
            //保存DataSet
            ds.WriteXml("MyFMS_DataS.xml");
        }

有了数据后, 当用户打开程序, 首先是要登录. 简单一点实现就是, 当用户输入帐号密码之后, 程序把用户填的帐号和User表内匹配看有没有这行数据, 有的话把对应的密码返回出来, 然后返回的密码和用户填写的密码匹配, 如果一致则登录成功. 于是就还需要一个方法: 输入一个表名, 一个键值对, 返回一行数据. 这里可以用简单DataTable.Select()类似SQL查找表内数据的方法.由于限定用户名不重名, 所以返回的数据肯定是只有一行的, 直接读取password列的数据就得到该用户的密码了, 匹配一下就能判断帐号密码正确与否.

/// 
        /// 查找表中指定行中的其他键的值
        /// 
        /// 表名
        /// 指定行的键
        /// 指定行的值
        /// 
        public DataRow[] FoundResult(string tName, string tKey, string tValue)
        {
            string strCondition = tKey + "='" + tValue + "'";

            DataRow[] dr = ds.Tables[tName].Select(strCondition);
            return dr;
        }

用户还可以注册账户, 注册时限定用户输入只能是数字或字母, 在文本框上注册一个KeyPress事件

private void txtUser_KeyPress(object sender, KeyPressEventArgs e)
        {
            //IsNumber:指定字符串中位于指定位置的字符是否属于数字类别
            //IsPunctuation:指定字符串中位于指定位置的字符是否属于标点符号类别
            //IsControl:指定字符串中位于指定位置的字符是否属于控制字符类别
            if (!Char.IsNumber(e.KeyChar) && !Char.IsControl(e.KeyChar))
            {
                e.Handled = true;
            }
            
        }

登录成功后用户就可以操作文件, 把DataTable内文件信息遍历到Listview内

 for (int i = 0; i < dt.Rows.Count; i++)
            {
                ListViewItem lvi = new ListViewItem(dt.Rows[i][0].ToString());
                for (int j = 0; j < dt.Columns.Count; j++)
                {
                    // lvi.ImageIndex = 0;
                    lvi.SubItems.Add(dt.Rows[i][j].ToString());
                }
                ltvUser.Items.Add(lvi);
            }

最后就是窗体间传值的问题, 找到一篇文章(C#)WinForm窗体间传值 用了里面其中一个方法写的

//Form1
 FormAlterPwd fr = new FormAlterPwd(tValue); //窗体间传值
//Form2
        private string tValue;

        public FormAlterPwd(string tValue)
        {
            InitializeComponent();
            // TODO: Complete member initialization
            this.tValue = tValue;
        }

完成

做完上面功能后发现还有一些细节可以完善, 比如新建用户可以选择是否为超级管理员, 还有打开多个文件的时候不能重复打开同一文件. 大致如此.

源码下载: 模拟二级文件系统(c#)

 

你可能感兴趣的:(开发日志)