2010-11-04 3 views
1

Есть ли у кого-нибудь опыт хранения данных на диске? У меня есть приложение для моделирования в памяти, которое может выполнять вычисления и т. Д. В основном данные хранятся в виде списков объектов, которые имеют вложенные коллекции значений ключа, такие как словарь < int, словарь < int, T >>.дисковое хранилище массивов и т. Д.

В настоящее время я использую SQL-Server как уровень защиты, но я использую очень мало его функций. Поэтому я думаю, что могу писать/читать данные на диск самостоятельно, чтобы уменьшить зависимости и упростить установку.

Итак, я написал небольшую рутину, которая записывает каждый массив на диск примерно в таком формате, где слова «ObjId», «Type», «Valid» и «Count» на самом деле не находятся в файле, это 1-й, 2-й, 3-й и 4-й строки в байте [], затем идут < int, T> пары. 52 происходит от 4 * 4 + 3 * (4 + 8). (4 байта для междунар 8 для двойной)

Bytes: 52 

ObjId: 123 
Valid: 234 
Type: double 
Count: 3 
    1 .23 
    2 .34 
    3 .45 

В реальной жизни нет отступов и т.д., они все последовательные байты в длинном потоке.

Это нормально, чтобы написать один раз. Но когда я хочу написать дополнительную ценность где-то посередине, я должен переписать все это. Также я не могу легко обновить одно значение.

Один из вариантов заключается в том, чтобы записывать каждый объект в отдельный файл, поэтому мне пришлось бы только переписать его. Но это кажется довольно неэффективным, потому что я получаю файлы размером 1kb, но 4kB на диске, поэтому я буду тратить туда пространство.

Так что мне нужно сделать, чтобы иметь возможность увеличивать запись в этом файле на диске? Я знаю, что в SqlServer есть «страницы», где он записывает данные, это путь?

Есть ли какая-нибудь библиотека, готовая пойти на этот тип проблем? Может быть, какой-то виртуальный файл, который позволит мне рассматривать их как отдельный байт [], но обрабатывает хранилище как отдельный файл psysical? В идеале сжат .. (толкая его, но кто знает .. Я был удивлен, прежде чем :-)

Заранее спасибо,

Герт-Ян

ответ

2

Если вы не хотите, накладные расходы на СУБД, можно использовать базу данных ключ-значение, как Berkeley DB. Существует С # интерфейс для него здесь:

Berkeley DB for .NET

Вы можете иметь одну запись для каждого массива, а просто переписать, что, когда вам нужно. Остальная часть файла базы данных будет неизменной, поэтому она намного быстрее, чем переписывание всего файла.

Вы можете повторно использовать логику сериализации, которую вы уже реализовали при записи массива. Все, что вам нужно добавить, это уникальный ключ для каждого массива.

+0

Привет, спасибо! Я знал о BDB как движок mySql, но никогда не рассматривал его для этого. Я посмотрю на него в выходные. Имея возможность просто поместить мой байт [] туда и вернуть его, кажется, довольно многое, что я искал. Я бы предпочел бы чистый C# с источником, но это должна быть зрелая технология, достаточная для использования в качестве черного ящика. – gjvdkamp

1

Вы не сможете обойти с 1 файлом на объект или переписыванием всего списка объектов при внесении изменений. Вы можете использовать SQLite. Это очень простая и эффективная встроенная база данных с одним файлом. Это означает, что ваше приложение не имеет внешних зависимостей от db.

Если вы пишете свои данные напрямую, вы должны прочитать и записать их в binary format.. Вы будете хранить целые числа в одном байте вместо их представления ASCII (1234 = 4 байта, но это 1 байт int).

Это ускорит чтение и запись в файл.

Часть кода из статьи:

Hashtable addresses = new Hashtable(); 
    addresses.Add("Jeff", "123 Main Street, Redmond, WA 98052"); 
    addresses.Add("Fred", "987 Pine Road, Phila., PA 19116"); 
    addresses.Add("Mary", "PO Box 112233, Palo Alto, CA 94301"); 

    // To serialize the hashtable and its key/value pairs, 
    // you must first open a stream for writing. 
    // In this case, use a file stream. 
    FileStream fs = new FileStream("DataFile.dat", FileMode.Create); 

    // Construct a BinaryFormatter and use it to serialize the data to the stream. 
    BinaryFormatter formatter = new BinaryFormatter(); 
    try 
    { 
     formatter.Serialize(fs, addresses); 
    } 
    catch (SerializationException e) 
    { 
     Console.WriteLine("Failed to serialize. Reason: " + e.Message); 
     throw; 
    } 
+0

Небольшой оговорка с BinaryFormatter заключается в том, что сгенерированные файлы не будут допускать переносимость версий в отношении сборок приложения или .NET Framework. – Alan

+0

технически, конечно, 1234 слишком велико, чтобы хранить в одном байте. Я ожидаю, что вы это знаете и просто неправильно напечатали. –

+0

@High Performance Mark - Да, вы правы, я должен был поставить 255 или что-то в этом роде. –

1

Существует тысячи способов хранения информации на диске. У вас уже есть предложения по базам данных. Вы также можете рассмотреть структурированные форматы файлов, такие как HDF5, который имеет привязки для языков, включая C#. Одной из сильных сторон HDF5 является поддержка хранения n-мерных массивов.

0

В дополнение к другим предложениям, сделанным здесь, вы можете попробовать MongoDB с NORM как отличным, без трения (без базы данных для настройки, без реляционного сопоставления объектов для создания), способ хранения данных без накладных расходов/стоимости SQL-сервера ,

Смежные вопросы