0

我在一个二进制文件中有大量数据记录,我想在其中搜索一些东西。有什么方法可以在文件数据上使用 LINQ 语句而不将所有数据放入内存(如List<T>)?

我有这种使用方法List<Book>

private Book Read(long position)
{
    Book book;
    using (Stream st = File.Open(HttpContext.Current.Server.MapPath("/") + "library.majid", FileMode.OpenOrCreate, FileAccess.Read))
    {
        st.Position = position;
        using (BinaryReader reader = new BinaryReader(st))
        {
            if (!reader.ReadBoolean())
                return null;
            book = new Book()
            {
                Id = reader.ReadInt32(),
                Name = reader.ReadString(),
                Dewey = reader.ReadString()
            };
            try
            {
                book.Subject = reader.ReadString();
                book.RegDate = reader.ReadInt32();
                book.PubDate = reader.ReadInt32();
            }
                catch (EndOfStreamException) { }
            }
        }
        return book;
    }
        private List<Book> getAll( int recordLength = 100)//sorted results by Id!!
    {
        long Len;
        using (Stream st = File.Open(HttpContext.Current.Server.MapPath("/") + "library.majid", FileMode.OpenOrCreate, FileAccess.Read))
        {
            Len = st.Length;
        }
        List<Book> res = new List<Book>();
        Book ReadedBook = null;
        for (int i = 0; i < Len/100; i++)
        {
            ReadedBook = Read(i * 100);
            if (ReadedBook != null)
                res.Add(ReadedBook);
        }
        res.Sort((x, y) => x.Id.CompareTo(y.Id));
        return res;
    }
4

2 回答 2

4

如果是文本文件,可以使用File.ReadLines(filename)which returns IEnumerable<string>,而不需要将文件加载到内存中。

请参阅http://msdn.microsoft.com/en-us/library/dd383503.aspx

ReadLines 和 ReadAllLines 方法的区别如下: 使用 ReadLines 时,可以在返回整个集合之前开始枚举字符串集合;使用 ReadAllLines 时,必须等待返回整个字符串数组才能访问该数组。因此,当您处理非常大的文件时,ReadLines 会更有效率。

例如;

var count = File.ReadLines(somefile)
                .Where(line => line.StartsWith("something"))
                .Count();

编辑

如果它是一个二进制文件呢?

然后你可以写一个类似这样的方法:

public static IEnumerable<Book> ReadBooks(string filename)
{
    using (var f = File.Open(filename, FileMode.Open))
    {
        using (BinaryReader rdr = new BinaryReader(f))
        {
            Book b = new Book();
            //.....
            yield return b;
        }
    }
}
于 2013-04-29T13:31:25.683 回答
0

如果您只想搜索一些数据,您可以保留类似的方法实现getAll,传递一些参数来执行搜索并返回一个列表(或IEnumerable<T>)。这样,您只需将结果项保存在内存中。

您的Read方法不会将元素保留在内存中(仅在方法范围内)。

顺便说一句,您可以将流阅读器传递给您的Read方法,这样您就不会为每次迭代创建一个新的阅读器。流“光标”将保留最后一块读取数据的位置。

于 2013-04-29T13:56:15.233 回答