Исключение нулевого указателя - это индикатор того, что вы используете объект, не инициализируя его.
Например, ниже - класс ученика, который будет использовать его в нашем коде.
public class Student {
private int id;
public int getId() {
return this.id;
}
public setId(int newId) {
this.id = newId;
}
}
Приведенный ниже код дает вам исключение с нулевым указателем.
public class School {
Student obj_Student;
public School() {
try {
obj_Student.getId();
}
catch(Exception e) {
System.out.println("Null Pointer ");
}
}
}
Поскольку вы используете Obj_Student
, но вы забыли инициализировать его, как в правильном коде, показанном ниже:
public class School {
Student obj_Student;
public School() {
try {
obj_Student = new Student();
obj_Student.setId(12);
obj_Student.getId();
}
catch(Exception e) {
System.out.println("Null Pointer ");
}
}
}
bplusdotnet пакет является библиотекой перекрестных совместимых реализаций структуры данных в C#, Java и Python, которые полезны для приложений, которые должны сохранить и получить персистентную информацию. bplusdotnet структуры данных помогают [1 119] строковые ключи хранилища, связанные со значениями постоянно .
Не 100%-й управляемый код, но стоит упомянуть, что это как сама неуправляемая библиотека уже - часть каждого поля
окон XP/2003/Vista/7 ESENT, встраиваемый механизм устройства хранения данных базы данных (ISAM), который является частью Windows. Это предоставляет надежному, проведенному, параллельному, высокоэффективному хранению данных блокировку уровня строки, запишите вперед вход и создайте снимки изоляцию. Это - управляемая оболочка для Win32 ESENT API.
*Akavache является асинхронным, персистентным кэшем значения ключа, созданным для записи собственных настольных и мобильных приложений в C#. Думайте о нем как memcached для настольных приложений.
<забастовка> - Библиотека Универсального набора C5 забастовка>
C5 обеспечивает функциональность и структуры данных, не обеспеченные стандартным .NET System.Collections.Generic
пространство имен, такой как [1 123] персистентные древовидные структуры данных , основанные на "куче" приоритетные очереди, списки индексного массива хеша и связанные списки и события на изменениях набора.
Я рекомендовал бы SQL Server Express или другая база данных.
Я не большая часть программиста, но не был бы, создавая действительно простой формат XML, чтобы хранить Ваши данные, добиваются цели?
<dico>
<dicEntry index="x">
<key>MyKey</key>
<val type="string">My val</val>
</dicEntry>
...
</dico>
Оттуда, Вы загружаете XML-файл DOM и заполняете Ваш словарь как Вам угодно
XmlDocument xdocDico = new XmlDocument();
string sXMLfile;
public loadDico(string sXMLfile, [other args...])
{
xdocDico.load(sXMLfile);
// Gather whatever you need and load it into your dico
}
public flushDicInXML(string sXMLfile, dictionary dicWhatever)
{
// Dump the dic in the XML doc & save
}
public updateXMLDOM(index, key, value)
{
// Update a specific value of the XML DOM based on index or key
}
Затем каждый раз, когда Вы хотите, можно обновить DOM и сохранить его на диске.
xdocDico.save(sXMLfile);
, Если можно позволить себе сохранить DOM в памяти мудрым производительностью, довольно легко иметь дело с. В зависимости от Ваших требований Вам даже, возможно, не понадобится словарь вообще.
Рассмотрите файл с отображенной памятью. Я не уверен, существует ли прямая поддержка в.NET, но Вы могли pinvoke вызовы Win32.
Я на самом деле не использовал его, но этот проект, по-видимому, обеспечивает mmap () - как реализация в C#
Как сказанный Douglas, необходимо знать фиксированный размер типов (и T и V). Кроме того, отсутствуют экземпляры переменной длины в объектной сетке, на которую ссылается любой из тех экземпляров.
однако, реализовывая словарь, поддержанный файлом, довольно просто, и можно использовать BinaryWriter
класс записи типы к диску после наследования или инкапсуляции Dictionary<TKey, TValue>
класс.
Я не знаю ни о чем для решения проблемы. Это должна будет быть структура фиксированного размера, так, чтобы можно было отвечать требованиям способности переписать записи, не переписывая весь файл.
Это означает, что нормальные строки отсутствуют.
Просто используйте сериализацию. Посмотрите на класс BinaryFormatter.
Проверьте этот блог:
http://ayende.com/Blog/archive/2009/01/17/rhino.dht-ndash-persistent-amp-distributed-storage.aspx
Надеется быть точно, что Вы ищете.
Я думаю, что Ваша проблема, вероятно, будет то, которые в последний раз указывают:
При установке или очистке значения это не должно переписывать весь базовый файл, вместо этого это должно искать на положение в файле и обновить значение.
Это точно, что делает DB - Вы в основном описываете простую основанную на файле структуру таблицы.
Мы можем проиллюстрировать проблему путем рассмотрения строк.
Строки в памяти являются гибкими вещами - Вы не должны знать длину строки в C#, когда Вы объявляете его тип.
В строках хранения данных и все остальное - фиксированные размеры. Ваш сохраненный словарь по диску является просто набором байтов в порядке.
, Если Вы заменяете значение в середине это или должны быть точно тем же размером или Вы будете иметь к , переписывают каждый байт, который прибывает после него .
Поэтому большинство баз данных ограничивает текст и поля блоба к фиксированным размерам. Новыми возможностями как varchar(max)
/ varbinary(max)
в Sql 2005 + являются на самом деле умные упрощения в строке только на самом деле хранение указателя на реальные данные.
Вы не можете использовать фиксированные размеры со своим примером, потому что это универсально - Вы не знаете то, что вводит, Вы собираетесь быть хранением, таким образом, Вы не можете увеличить значения к максимальному размеру.
Вы могли сделать:
class PersistantDictionary<T,V> : Dictionary<T,V>
where V:struct
..., поскольку типы значения не варьируются по размеру ресурса хранения, хотя необходимо было бы быть осторожными с реализацией для сохранения правильной суммы устройства хранения данных для каждого типа.
Однако Ваша модель не была бы очень производительна - если Вы смотрите на то, как SQL-сервер и Oracle имеют дело с изменениями таблицы, они не изменяют значения как это. Вместо этого они отмечают старую запись как фантом и добавляют новую запись с новым значением. Старые повторенные записи очищены позже, когда DB менее занят.
я думаю, что Вы пытаетесь изобрести велосипед:
, Если Вы имеете дело с большими объемами данных затем, действительно необходимо проверить использование полноценного DB. MySql или SqlLite оба хороши, но Вы не собираетесь находить хорошую, простую, и облегченную реализацию с открытым исходным кодом.
, Если бы Вы не имеете дело с загрузками данных затем, я пошел бы для целой сериализации файла, и уже существует много хороших предложений здесь о том, как сделать это.
Я нашел эту ссылку, и походите на то, что Вы ищете. Это программируется в Java, но не должно случаться так что трудно портировать его на C#:
http://www.javaworld.com/javaworld/jw-01-1999/jw-01-step.html
Прохладные звуки, но как Вы обойдете изменения в хранимой сумме (если это был ссылочный тип), сам? Если его неизменное тогда, которое все хорошо, но если не Вы отчасти наполнены:-)
, Если бы Вы не имеете дело с неизменными значениями, я подозревал бы, что лучший подход должен был бы обработать персистентность на уровне значения и просто восстановить словарь по мере необходимости.
(отредактированный для добавления разъяснения)
Я работал над портированием EHCache к.NET. Смотрите на проект
http://sourceforge.net/projects/thecache/
, Персистентное кэширование является базовой функциональностью, которая уже реализована. Все основные Модульные тесты являются передающими. Я вовлек немного на распределенном кэшировании, но Вам не нужна та часть.
один путь состоит в том, чтобы использовать Расширяемый Механизм устройства хранения данных встроенный в окна для хранения материала. Это - собственная база данных победы, которая поддерживает индексацию, транзакции и т.д.
Позвольте мне проанализировать это:
, я думаю, что Вы хотите базу данных.
Редактирование: Я думаю, что Вы ищете неправильную вещь. Ищите базу данных, которая соответствует Вашим требованиям. И измените некоторые свои требования, потому что я думаю, что будет трудно встретить их всех.
Я описал реализацию сам на основе очень похожего (я думаю идентичный), требование, которое я имел на другом проекте только что. Когда я сделал это, одна вещь, которую я понял, состояла в том, что большую часть времени Вы будете делать записи, Вы только делаете чтение редко, когда программа отказывает или когда это закрывается. Таким образом, идея состоит в том, чтобы сделать записи максимально быстро. То, что я сделал, было, делают очень простой класс, который просто записал бы журнал всех операций (дополнения и удаления) к словарю, поскольку вещи произошли. Так через некоторое время Вы получаете большое повторение между ключами. Из-за этого, после того как объект обнаруживает определенное количество повторения, он очистит журнал и перепишет его так, каждый ключ и его значение только появляются однажды.
, К сожалению, Вы не можете разделить Словарь на подклассы, потому что Вы ничего не можете переопределить в нем. Это - моя простая реализация, я не протестировал ее, хотя я сожалею, я думал, что Вы могли бы хотеть идею все же. Не стесняйтесь использовать его и изменять его так, как Вам нравится.
class PersistentDictManager {
const int SaveAllThreshold = 1000;
PersistentDictManager(string logpath) {
this.LogPath = logpath;
this.mydictionary = new Dictionary<string, string>();
this.LoadData();
}
public string LogPath { get; private set; }
public string this[string key] {
get{ return this.mydictionary[key]; }
set{
string existingvalue;
if(!this.mydictionary.TryGetValue(key, out existingvalue)) { existingvalue = null; }
if(string.Equals(value, existingvalue)) { return; }
this[key] = value;
// store in log
if(existingvalue != null) { // was an update (not a create)
if(this.IncrementSaveAll()) { return; } // because we're going to repeat a key the log
}
this.LogStore(key, value);
}
}
public void Remove(string key) {
if(!this.mydictionary.Remove(key)) { return; }
if(this.IncrementSaveAll()) { return; } // because we're going to repeat a key in the log
this.LogDelete(key);
}
private void CreateWriter() {
if(this.writer == null) {
this.writer = new BinaryWriter(File.Open(this.LogPath, FileMode.Open));
}
}
private bool IncrementSaveAll() {
++this.saveallcount;
if(this.saveallcount >= PersistentDictManager.SaveAllThreshold) {
this.SaveAllData();
return true;
}
else { return false; }
}
private void LoadData() {
try{
using(BinaryReader reader = new BinaryReader(File.Open(LogPath, FileMode.Open))) {
while(reader.PeekChar() != -1) {
string key = reader.ReadString();
bool isdeleted = reader.ReadBoolean();
if(isdeleted) { this.mydictionary.Remove(key); }
else {
string value = reader.ReadString();
this.mydictionary[key] = value;
}
}
}
}
catch(FileNotFoundException) { }
}
private void LogDelete(string key) {
this.CreateWriter();
this.writer.Write(key);
this.writer.Write(true); // yes, key was deleted
}
private void LogStore(string key, string value) {
this.CreateWriter();
this.writer.Write(key);
this.writer.Write(false); // no, key was not deleted
this.writer.Write(value);
}
private void SaveAllData() {
if(this.writer != null) {
this.writer.Close();
this.writer = null;
}
using(BinaryWriter writer = new BinaryWriter(File.Open(this.LogPath, FileMode.Create))) {
foreach(KeyValuePair<string, string> kv in this.mydictionary) {
writer.Write(kv.Key);
writer.Write(false); // is not deleted flag
writer.Write(kv.Value);
}
}
}
private readonly Dictionary<string, string> mydictionary;
private int saveallcount = 0;
private BinaryWriter writer = null;
}
Я реализовал тот тип PersistedDictionary, который вы ищете. Базовое хранилище - это механизм базы данных ESENT, встроенный в Windows. Код доступен здесь: