Click here to Skip to main content
14,034,935 members
Click here to Skip to main content
Add your own
alternative version

Stats

2.4K views
54 downloads
1 bookmarked
Posted 15 Apr 2019
Licenced BSD

A Simple Dictionary

, 17 Apr 2019
Rate this:
Please Sign up or sign in to vote.
A simple dictionary/notepad application.

Introduction

This is a simple dictionary application.

You can also use this application as a Notepad. Instead of having too many separate notes or text files on your desktop, you can save and keep all of them in one data file. Simply enter your text into the richtextbox and click on save button. All data is encrypted with AES (Advanced Encryption Standard) by using a default password. You can also encrypt each entry with your own password. This application has search-as-you-type feature. Search suggestions will appear as you type into the textbox.

1. Structure of the Data

There are obviously plenty of solutions to store the data, e.g. a fast popular database, etc.
I did not use any popular database. So, you do not need to install any database for this application.

Instead, I used two separate files: the 'Data File' and the corresponding 'Keys/Address File' in which byte-addresses of the values are saved.

Since we have all the addresses of the values, we do not need to implement a 'search algorithm'.
After getting the address of the value, we can directly seek to the address and read the value from that point.

In this application, I used 'length-prefixed' data, i.e., the data is prepended with its length.
In this way, each time we need to read the data, we know its byte-length before we read the data.

The data structure of one record having both the key and its value:

where:

byte bdel;       // Indicates whether this record is deleted or not. 0=Not deleted, 1=Deleted
int Total;       // The total length of this record (excluding itself and the preceding byte)
int prekey;      // The length of the keyName
byte[] KeyName;  // The KeyName as byte array
int predat;      // The length of the data or value.

The KeyName is tagged with 4-Bytes KeyTag which is used for encoding some information about the record, i.e., whether default encryption is used and RGB values of the displayed 'background color'.

4-Bytes KeyTag structure:

  • [0. Byte]: Encoded with save formats and other options
  • [1. Byte]: Red
  • [2. Byte]: Green
  • [3. Byte]: Blue

Simple way of encoding the first (0th byte) of the key tag using '|' (OR) bitwise operator:

byte KeyFirstByte = 0;

private byte EncodeKeyByte()
        {
            this.KeyFirstByte = 0;

            // encrypt with user-provided password?
            if (this.withPassword)
                this.KeyFirstByte = (byte)(this.KeyFirstByte | 1);

            // is compression checked?
            if (this.isCompressed)
                this.KeyFirstByte = (byte)(this.KeyFirstByte | 128);

            // UTF8 selected:
            if (this.encodingWith == Encoding.UTF8)
                this.KeyFirstByte = (byte)(this.KeyFirstByte | 2);

            // Unicode selected:
            else if (this.encodingWith == Encoding.Unicode)
                this.KeyFirstByte = (byte)(this.KeyFirstByte | 4);

            // ASCII selected:
            else if (this.encodingWith == Encoding.ASCII)
                this.KeyFirstByte = (byte)(this.KeyFirstByte | 8);

            // default: UTF8
            else
                this.KeyFirstByte = (byte)(this.KeyFirstByte | 2);

            return this.KeyFirstByte;
        }

The structure of the keys/addresses file:

where:

byte bdel;           // Indicates whether this record is deleted or not. 0=Not deleted, 1=Deleted
int Total;           // The total length of this key record (excluding itself and preceding byte)
int prekey;          // The length of the keyName (including 4-Bytes KeyTag)
byte[] KeyName;      // The KeyName as byte array
long NodeAddress;    // The Address of the corresponding record in the main data file
int TotalinDataFile; // The length of the record in the main data file

And write all data into the file. An example of writing a test entry:

using (FileStream fs = File.Create(filename)) { };
using (FileStream fsk = File.Create(keysFile)) { };

/* test Entry from richTextBox: */
string testEntry = "{\\rtf1\\ansi{\\fonttbl{\\f0\\fnil\\fcharset162 Calibri;}" +
 "{\\f1\\fnil\\fcharset0 Calibri;}}" +
 "\\viewkind4\\uc1\\pard\\f0\\fs23  Test Entry. \\par }";

this.KeyFirstByte = EncodeKeyByte();
this.backRGB[0] = this.richTextBox1.BackColor.R;
this.backRGB[1] = this.richTextBox1.BackColor.G;
this.backRGB[2] = this.richTextBox1.BackColor.B;
this.tagKey = new byte[] 
    { this.KeyFirstByte, this.backRGB[0], this.backRGB[1], this.backRGB[2]};

WriteToFile("test", testEntry, false, false);

where WriteToFile() is:

private void WriteToFile(string key, string value, bool delete, bool withPass)
{
    using (FileStream fs = new FileStream(filename, FileMode.Append))
    using (BinaryWriter writer = new BinaryWriter(fs))
    {
          //  write data details...
    }
}

You may insert pictures into your entry which will increase the data size abruptly compared to text-only entries. As an option, in order to save some disk space, we can also compress the data inside the richtextbox:

public static byte[] Compress(byte[] input)
{
     using (MemoryStream compressed = new MemoryStream())
     using (DeflateStream deflate = new DeflateStream(compressed, CompressionMode.Compress))
     {
          deflate.Write(input, 0, input.Length);
          deflate.Close();

          return compressed.ToArray();
     }
}

public static byte[] Decompress(byte[] data)
{
      using (MemoryStream compressedDataStream = new MemoryStream(data))
      using (MemoryStream decompressedStream = new MemoryStream())
      using (DeflateStream deflate = 
             new DeflateStream(compressedDataStream, CompressionMode.Decompress))
      {
          deflate.CopyTo(decompressedStream);
          deflate.Close();
          decompressedStream.Position = 0;

          return decompressedStream.ToArray();
      }
}

And this is the flowchart of the whole process of reading from or writing to the file. Compression (and decompression) is optional.

Summary

If your desktop is full of your notes, pictures, howtos, etc., then this application may be a suitable alternative for you to keep all of them in one data file. In addition, it secures your entries with AES encryption.

History

  • 15th April, 2019: v1.0

License

This article, along with any associated source code and files, is licensed under The BSD License

Share

About the Author

Yucel Guven
Engineer
Turkey Turkey
EE/Physics

You may also be interested in...

Comments and Discussions

 
-- There are no messages in this forum --
Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web04 | 2.8.190424.1 | Last Updated 17 Apr 2019
Article Copyright 2019 by Yucel Guven
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid