文件内容大概如下:
03KW48BRLB01R            0.033     AC001     HJ01(QC001\QC002\QC003\QC004)                     2009-5-8 17:13:49   0.01925   0.01925   03KW48BRLB01R9970506A    焊检合格            0506A     
03KW48BRLB01R            0.033     AC001     HJ01(QC001\QC002\QC003\QC004)                     2009-5-8 17:13:50   0.01925   0.01925   03KW48BRLB01R9960506A    焊检合格            0506A       
03KW48BRLB01R            0.033     AC001     HJ01(QC001\QC002\QC003\QC004)                     2009-5-8 17:13:50   0.01925   0.01925   03KW48BRLB01R9960506A    焊检合格            0506A     
03KW48BRLB01R            0.033     AC001     HJ01(QC001\QC002\QC003\QC004)                     2009-5-8 17:13:51   0.01925   0.01925   03KW48BRLB01R9980506A    焊检合格            0506A     
03KW48BRLB01R            0.033     AC001     HJ01(QC001\QC002\QC003\QC004)                     2009-5-8 17:13:51   0.01925   0.01925   03KW48BRLB01R9990506A    焊检合格            0506A     
03KW48BRLB01R            0.033     AC001     HJ01(QC001\QC002\QC003\QC004)                     2009-5-8 17:13:49   0.01925   0.01925   03KW48BRLB01R9970506A    焊检合格            0506A     
03KW48BRLB01R            0.033     AC001     HJ01(QC001\QC002\QC003\QC004)                     2009-5-8 17:13:50   0.01925   0.01925   03KW48BRLB01R9960506A    焊检合格            0506A     
03KW48BRLB01R            0.033     AC001     HJ01(QC001\QC002\QC003\QC004)                     2009-5-8 17:13:51   0.01925   0.01925   03KW48BRLB01R9980506A    焊检合格            0506A     
03KW48BRLB01R            0.033     AC001     HJ01(QC001\QC002\QC003\QC004)                     2009-5-8 17:13:51   0.01925   0.01925   03KW48BRLB01R9990506A    焊检合格            0506A     
03KW48BRLB01R            0.033     AC001     HJ01(QC001\QC002\QC003\QC004)                     2009-5-8 17:13:49   0.01925   0.01925   03KW48BRLB01R9970506A    焊检合格            0506A     
03KW48BRLB01R            0.033     AC001     HJ01(QC001\QC002\QC003\QC004)                     2009-5-8 17:13:50   0.01925   0.01925   03KW48BRLB01R9960506A    焊检合格            0506A     
03KW48BRLB01R            0.033     AC001     HJ01(QC001\QC002\QC003\QC004)                     2009-5-8 17:13:51   0.01925   0.01925   03KW48BRLB01R9980506A    焊检合格            0506A     
03KW48BRLB01R            0.033     AC001     HJ01(QC001\QC002\QC003\QC004)                     2009-5-8 17:13:51   0.01925   0.01925   03KW48BRLB01R9990506A    焊检合格            0506A     
03KW48BRLB01R            0.033     AC001     HJ01(QC001\QC002\QC003\QC004)                     2009-5-8 17:13:49   0.01925   0.01925   03KW48BRLB01R9970506A    焊检合格            0506A     
一、每行有192个字节,大概记录为7000多条,在WINCE下查找速度非常慢,想请教各位高人,如何实现查找速度快?
二、查找内容为字段03KW48BRLB01R9970506A,不重复;
三、有没有办法实现在刚开始写入文件的时候就对内容进行排序?如何实现?
四、WINCE设备内存有限,清不要用ARRAYLIST,太耗内存了!
谢谢!!!!

解决方案 »

  1.   

    如果数据没有经过排序,只能遍历所有数据,只有用空间换时间来提高速度了,但是在WINCE上资源有限最好是在插入数据的时候就进行排序,先查找到应该插入的位置,然后将后面的数据往后挪,其实就是简单的文件操作
    因为你这里都是定长的记录,文件操作的时候就不用全部转成string类型了,直接用byte[]来操作
      

  2.   

    1. 建议用Hashtable类,但不是把所有的信息都放进Hashtable中,只放入具有唯一性的字段,如03KW48BRLB01R9970506A等,这个字段长度为20bytes,由于你提及每行都是192bytes,就是说每条记录的长度是固定的,那么对应地只要存放该记录起始位置相对于文件头的偏移量,一个整形数字就可以了,因为只有7000多条记录。因此Hashtable中的内容大概象下面这个样子:
    唯一标记                  记录开始的物理位置相对与文件头的偏移量
    03KW48BRLB01R9970506A  0
    ....
    03KW48BRLB01R9970506A  19200   (说明这条记录的开始处位于文件的第19200个字符,应为192的倍数)
    ....所以7000条记录,共需要内存7000 * (20 + 4)= 168k,这点内存应该还是可以消耗得起的。现在假定你要查找03KW48BRLB01R9970506A这条记录,那么你先到Hashtable中查找03KW48BRLB01R9970506A,得到对应的偏移量为19200,然后你就可以从文件的第19200个字符开始读取192个字符,这就是你要找的记录了。2. 由于Hashtable的内容存在内存中,当应用退出时,其中的内容就会消失,所以建议你将其中的内容作为文件保存在硬盘上,每次重启应用的时候,就将它读入到Hashtable中。其实大型数据库中的索引的原理差不多也就是这样的。
      

  3.   

    更正:
    1. 建议用Hashtable类,但不是把所有的信息都放进Hashtable中,只放入具有唯一性的字段,如03KW48BRLB01R9970506A等,这个字段长度为21bytes(上面的回答数错为20),由于你提及每行都是192bytes,就是说每条记录的长度是固定的,那么对应地只要存放该记录起始位置相对于文件头的偏移量,一个整形数字就可以了,因为只有7000多条记录。因此Hashtable中的内容大概象下面这个样子: 唯一标记                              记录开始的物理位置相对与文件头的偏移量 
    03KW48BRLB01R9970506A    0 (第1条记录,说明这条记录的开始处位于文件的第0个字符,应为192的倍数)
    .... 
    03KW48BRLB01R9970506A    19200 (说明这条记录的开始处位于文件的第19200个字符,应为192的倍数) 
    .... 所以7000条记录,共需要内存7000 * (21 + 4)= 175k,这点内存应该还是可以消耗得起的。 现在假定你要查找03KW48BRLB01R9970506A这条记录,那么你先到Hashtable中查找03KW48BRLB01R9970506A,得到对应的偏移量为19200,然后你就可以从文件的第19200个字符开始读取192个字符,这就是你要找的记录了。 2. 由于Hashtable的内容存在内存中,当应用退出时,内容就会消失,所以建议你将其中的内容作为文件保存在硬盘上,每次重启应用的时候,就将它读入到Hashtable中。 其实大型数据库中的索引的原理差不多也就是这样的。
      

  4.   

    感谢各位的回复,我之前也用了Hashtable类,但在加载文件到Hashtable类的时候好像也点内存,速度不是很理想,我用的方法是创建了一个索引文件,把要查找的关键字放到索引文件中进行查找,速度还可以;
    另:可能是我加载文件到Hashtable类的方法不对,所以速度上慢了点,我的方法是
    byte[] b;
    StreamReader sr = new StreamReader(filename,...);
    while(sr.read())
    {
      temp = sr.readline();
      b = Encoding.Default.GetBytes(temp);
      ht.add(b,b);
    }
    然后是ht.Contains(...)
    代码记不清了,大概就是如此,查询速度不是很理想,请问pathuang68
    有没有更好的办法!谢谢!!!
      

  5.   


    1. 内存肯定是要用点的,不过175k的内存这样代价是值得,也是可以付出的;
    2. 兄弟所言“速度不是很理想”,能说具体一点么,比如在Hastable中查询到一条记录需要多长的时间?用6楼所说的方法应该不会慢的;
    3. 上面代码中,filename所指的文件的内容是什么?即temp是什么?
    4. 上面代码中,为什么要用b = Encoding.Default.GetBytes(temp); 呢?没有必要呀
    5. ht.add(b,b); 这句兄弟就更加看不明白了,为何两个参数都是一样的?前一个是Key,后一个是对应的Value才是,拿你的例子来说,应该是这样的:
       ht.add("03KW48BRLB01R9970506A", 19200);
    6. 上面代码中ht.Contains(...) 可以判断记录是否存在,它返回的是一个bool值,但对如何找到对应的记录而言没有什么用,可以将它和hastable遍历一起使用。关于Hashtable,建议兄弟看看,文章很短:
    http://blog.csdn.net/txl816/archive/2008/10/20/3108799.aspx在第一次构造你需要的hastable的时候,需要你遍历整个原始文本文件,以获得03KW48BRLB01R9970506A(即Key)和与这个Key对应的记录相对原始文本文件头的偏移量如19200,这个可能需要一点时间,根据6楼2中提及的方法,以后就再也不需要了这样耗时的操作了。还有,还可以将hastable排序,这也可以提高性能,但具体在你这个应用中,性能的提升估计很不明显。
      

  6.   

    1、速度不理想是指在一次性把文件内容读入到HASTABLE类的时候,耗时没有计算(不会!呵呵)
    2、filename是加载的文件名,temp是每次读取一行的记录
    3、由于文件中含有中文,故用了b = Encoding.Default.GetBytes(temp)
    4、ht.add(b,b)是我随便写的,和你的意思是一样的,把键值,和对应值添加到hastable中
      (另:对于value是不是键值在原始文件中所在的位置?如何计算?谢谢!)
    5、我用到ht.Contains就是用来判断记录是否存在的,不知道这个函数是不是全本查找?
      

  7.   

    如果不想用数据库,那用xls比较好。他也可以当表操作,而且人也能看懂,这点比数据库好
      

  8.   

    根本不需要“一次性把文件内容读入到HASTABLE类”!只要读那个文本文件中的两个字段就可以了,怪不得你又说占内存,又说速度慢。还是建议你再看看6L和9L的回帖。
      

  9.   

    pathuang68已经说得很清楚了,楼主还不明白?!汗啊!
      

  10.   

    感谢各位的指点,我是半路出家的,30岁才开始接触编程,到现在也不过2年,有些基础的东西并没有学习,特别是数据结构,所以还请各位海涵!!
    至于用索引文件,也是通过百度查了一些资料得到了,我也不知道创建的文件是不是对的,我的方法是,同时创建源文件和索引文件,这个要查找的内容位置是一一对应的,查找的方法很笨,还是加载到ARRAYLIST中,由于索引文件里的内容小,所以点内存也少,这样不影响速度!呵呵!
    还请各位达人指点该如何创建索引文件;另,我在网上下了个C#数据结构正在看,不过没头绪,越看赿不明白!!!
    再谢谢!!!!
    还是请教,我在读取文本文件关键值,及对应值的时候是不是要加循环呢?
    根本不需要“一次性把文件内容读入到HASTABLE类”!只要读那个文本文件中的两个字段就可以了,怪不得你又说占内存,又说速度慢。还是建议你再看看6L和9L的回帖请问是不是用以下代码:
    streamreader sr = new streamreader("@\\2.txt",...);
    while (sr.peek()!=-1)
    {
      ht.add(sr.readline().substing(20,20));
    }
    只读取每行的第几个字段内容就行了???
    再谢谢!!!
      

  11.   

    感谢网友flora186,我现在写的程序越多越感觉知识太少,这个我的基础有关系,虽然是半路出家,但我会努力的,编程这事是任何年龄阶段都可以的,只要用心。至少不懂的地方可以和你们这些热心人交流,很高兴得到你们的帮助,谢谢!!!不要嫌烦哦!!!
      

  12.   

    佩服楼主的脾气,至少比我好多了。我也是半路出家,从97年学FORTRAN,98年学C,后来一直学了Basic、VB4、VB5、VB6、VB.NET,到04年改成C#。学了不少啥都不精,唉……其实,根据楼上那样大大的说法,只要在哈希表里设置Key和记录号。
    需要时,取出记录号,由于记录是定长的,根据记录号算一下文件读取位置的偏移,定位下,读出相应记录。        private string ReadRecord(string Key)
            {
                const Int32 iRecordLength = 192;//这个数字没考虑到换行符,所以要修正下
                System.Collections.Hashtable htIndex = new System.Collections.Hashtable();
                //载入索引
                //...
                //完成载入
                Int64 iPosition = iRecordLength * (Int64)htIndex[Key];
                string sRecord = string.Empty;
                using (System.IO.BinaryReader brT = new System.IO.BinaryReader(System.IO.File.OpenRead, System.Text.Encoding.Default))
                {
                    brT.BaseStream.Position = I;
                    byte[] byteBuffer = brT.ReadBytes(192);
                    sRecord = System.Text.Encoding.Default.GetString(byteBuffer);
                }
                return sRecord;
            }
      

  13.   

            private string ReadRecord(string Key)
            {
                const Int32 iRecordLength = 192;
                System.Collections.Hashtable htIndex = new System.Collections.Hashtable();
                //载入索引
                 //...
                //完成载入
                Int64 iPosition = iRecordLength * (Int64)htIndex[Key];
                string sRecord = string.Empty;
                using (System.IO.BinaryReader brT = new System.IO.BinaryReader(System.IO.File.OpenRead, System.Text.Encoding.Default))
                {
                    brT.BaseStream.Position = I;
                    byte[] byteBuffer = brT.ReadBytes(iRecordLength);//这里修改下
                    sRecord = System.Text.Encoding.Default.GetString(byteBuffer);
                }
                return sRecord;
            }
    因为是用字节方式读取,所以在储存的时候最好能用BinaryWriter写入,保持一致。
      

  14.   

    非常感谢网友starj1,你的代码基本能看懂,想请教一下        //另,没有看到要比较的地方?变量Key是什么?比较的值吗?如果我要在hashtable里查找Key,该怎么查?呵呵,谢谢!!!!
            private string ReadRecord(string Key)
            {
                const Int32 iRecordLength = 192;
                System.Collections.Hashtable htIndex = new System.Collections.Hashtable();
                //载入索引
                 //...
                //完成载入
                Int64 iPosition = iRecordLength * (Int64)htIndex[Key];//指针位置,好像没用到!
                string sRecord = string.Empty;//初始化字符串
                using (System.IO.BinaryReader brT = new System.IO.BinaryReader(System.IO.File.OpenRead, System.Text.Encoding.Default))
                {
                    brT.BaseStream.Position = I;  //这个地方是不是流的起始位置,好像是从0开始吧???
                    byte[] byteBuffer = brT.ReadBytes(iRecordLength);//读取192个字节
                    sRecord = System.Text.Encoding.Default.GetString(byteBuffer);//转换成字符串
                }
                return sRecord;
            }谢谢朋友,我接触编程是从2001年才开始的,真正开始写程序还是2007年,C#,C,DELPHI这三个由于工作原因用的比较多,回想第一个简单的进销存程序写了一个多月,真是不堪回首啊,还好老板人不错,让我坚持了下来,多少有那么一点成就!就是基础差,哎,都32了,感觉以前都白活了!!
      

  15.   

    Key就是具有唯一性特征的值,你从记录中选出一部分作为Key就可以了。
    hashtable里的key不需要你查找,使用方式就是如:hashtable[Key]
    brT.BaseStream.Position = I;这句错了,改成brT.BaseStream.Position = iPosition;
    是用来定位记录的位置。
    另外,我上面的函数把载入索引写到里面,这是不应该的,要把这部分在外部完成,以加快速度。
      

  16.   

    再次感谢网友starj1,麻烦你那么晚给我回复,如果有什么问题还要请教!呵呵!
    好了,现在结帖!!!