Advertisement
kot025

INDEX 1,3,4 better

Mar 14th, 2015
216
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 23.22 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.IO;
  7. using System.Runtime.Serialization.Formatters.Binary;
  8.  
  9.  
  10. namespace ConsoleApplication2
  11. {
  12.     [Serializable]
  13.     public struct Person
  14.     {
  15.         bool active;
  16.         public string name;
  17.         public int year;
  18.         public int rank;
  19.         public Person(bool _active, string _name, int _year, int _rank)
  20.         {
  21.             active = _active;
  22.             name = _name;
  23.             year = _year;
  24.             rank = _rank;
  25.         }
  26.         public void Show()
  27.         {
  28.             Console.WriteLine("{0,-40} {1,5} {2,3}", name, year, rank);
  29.             if (!active)
  30.             {
  31.                 Program.RedLn("В корзине.\n");
  32.             }
  33.         }
  34.     }
  35.     [Serializable]
  36.     public struct IndexEntry
  37.     {
  38.         public string key;
  39.         public int length;
  40.         public int offset;
  41.         public IndexEntry(string _key, int _length, int _offset)
  42.         {
  43.             key = _key;
  44.             length = _length;
  45.             offset = _offset;
  46.         }
  47.         public void Show()
  48.         {
  49.             Console.WriteLine("{0,-40} {1} {2}", key, length, offset);
  50.         }
  51.     }
  52.     class Program
  53.     {
  54.         static string dbPath = Path.Combine(Environment.CurrentDirectory, "contestants.dat");
  55.         static string indexPath = Path.Combine(Environment.CurrentDirectory, "index.dat");
  56.         public static void RedLn(string str) // вывести переданную строку красным цветом
  57.         {
  58.             Console.ForegroundColor = ConsoleColor.Red;
  59.             Console.WriteLine(str);
  60.             Console.ResetColor();
  61.         }
  62.         static int AskForAction(int qtyOfActions)// запросить команду меню с проверкой вводимых значений
  63.         {
  64.             int act;
  65.             bool ok;
  66.             Console.WriteLine();
  67.             do
  68.             {
  69.                 Console.Write("Команда: ");
  70.                 string buf = Console.ReadLine();
  71.                 ok = int.TryParse(buf, out act) && act > 0 && act <= qtyOfActions;
  72.                 if (!ok)
  73.                     RedLn("Доступны команды 1 - " + qtyOfActions + ".");
  74.             } while (!ok);
  75.             Console.WriteLine();
  76.             return act;
  77.         }
  78.  
  79.         static Person EjectPerson(int i)                                    // извлечь указанную запись
  80.         {
  81.             var formatter = new BinaryFormatter();
  82.             var fs = new FileStream(dbPath, FileMode.Open, FileAccess.Read);
  83.             var memoryStream = new MemoryStream();
  84.             fs.Position = i * 255;
  85.             var data = new byte[255];                                       // объявить массив под сериализованную запись
  86.             fs.Read(data, 0, 255);                                          // считать в массив всю запись
  87.             memoryStream.Write(data, 1, data[0]);                           // значимые байты записи - в ОЗУ
  88.             memoryStream.Position = 0;
  89.             Person person = (Person)formatter.Deserialize(memoryStream);    // десериализовать запись из байтов записи
  90.             fs.Close();
  91.             return person;                                                  // вернуть запись
  92.         }
  93.         static IndexEntry EjectEntry(int i)                                 // извлечь указанную запись  
  94.         {
  95.             var formatter = new BinaryFormatter();
  96.             var fs = new FileStream(indexPath, FileMode.Open, FileAccess.Read);
  97.             var memoryStream = new MemoryStream();
  98.             fs.Position = i * 255;
  99.             var data = new byte[255];                                       // объявить массив под сериализованную запись
  100.             fs.Read(data, 0, 255);                                          // считать в массив всю запись
  101.             memoryStream.Write(data, 1, data[0]);                           // значимые байты записи - в ОЗУ
  102.             memoryStream.Position = 0;
  103.             IndexEntry entry = (IndexEntry)formatter.Deserialize(memoryStream);    // десериализовать запись из байтов записи
  104.             fs.Close();
  105.             return entry;                                                  // вернуть запись
  106.         }
  107.         static IndexEntry[] ArrayOfEntries()
  108.         {
  109.             var fs = new FileStream(indexPath, FileMode.Open, FileAccess.Read);
  110.             var array = new IndexEntry[fs.Length / 255];
  111.             for (int i = 0; i < fs.Length / 255; i++)
  112.             {
  113.                 array[i] = EjectEntry(i);
  114.             }
  115.             fs.Close();
  116.             return (array);
  117.         }
  118.         static Person AskForNewPerson() // запросить нового участника, создать и вернуть запись
  119.         {
  120.             Console.Clear();
  121.             string name;
  122.             int year, rank;
  123.             bool ok;
  124.             Console.Write("ФИО: ");                         // ввод ФИО
  125.             name = Console.ReadLine();
  126.             int tempParse;
  127.             do                                              // ввод года
  128.             {
  129.                 Console.Write("Год рождения: ");
  130.                 string buf = Console.ReadLine();
  131.                 ok = int.TryParse(buf, out tempParse) && tempParse > 1900 && tempParse < 2015;
  132.                 if (!ok)
  133.                 {
  134.                     RedLn("Ошибка.");
  135.                     Console.WriteLine("Убедитесь в правильности введенного года рождения и повторите ввод.\n");
  136.                 }
  137.             } while (!ok);
  138.             year = tempParse;
  139.             do                                              // ввод разряда
  140.             {
  141.                 Console.Write("Текущий разряд: ");
  142.                 string buf = Console.ReadLine();
  143.                 ok = int.TryParse(buf, out tempParse) && tempParse >= 0 && tempParse < 10;
  144.                 if (!ok)
  145.                 {
  146.                     RedLn("Ошибка.");
  147.                     Console.WriteLine("Убедитесь в правильности введенного разряда и повторите ввод.\n");
  148.                 }
  149.             } while (!ok);
  150.             rank = tempParse;
  151.             return new Person(true, name, year, rank);      // конец ввода данных и возврат записи
  152.         }
  153.         static void AddToEndOfFile(Person person) // добавить переданную запись в конец БД
  154.         {
  155.             var formatter = new BinaryFormatter();
  156.             var memoryStream = new MemoryStream();
  157.             var fs = new FileStream(dbPath, FileMode.OpenOrCreate, FileAccess.Write); // добавление записи в файл
  158.             fs.Seek(0, SeekOrigin.End);
  159.             BinaryWriter bw = new BinaryWriter(fs);
  160.             byte[] data = new byte[255];                // массив байтов под сериализованную запись (решение проблемы с размером)
  161.             formatter.Serialize(memoryStream, person);
  162.             memoryStream.Position = 0;
  163.             data[0] = (byte)memoryStream.Length;        // в нулевую ячейку массива - количество байтов в сериализованной записи
  164.             memoryStream.Read(data, 1, (int)memoryStream.Length); // в массив с первой ячейки все из сериализованной записи из памяти
  165.             bw.Write(data);                             // запись массива байтов в конец файла
  166.             fs.Close();
  167.         }
  168.         static void AddToEndOfFile(IndexEntry entry) // добавить переданную запись в конец индексов
  169.         {
  170.             var formatter = new BinaryFormatter();
  171.             var memoryStream = new MemoryStream();
  172.             var fs = new FileStream(indexPath, FileMode.OpenOrCreate, FileAccess.Write); // добавление записи в файл
  173.             fs.Seek(0, SeekOrigin.End);
  174.             BinaryWriter bw = new BinaryWriter(fs);
  175.             byte[] data = new byte[255];                // массив байтов под сериализованную запись (решение проблемы с размером)
  176.             formatter.Serialize(memoryStream, entry);
  177.             memoryStream.Position = 0;
  178.             data[0] = (byte)memoryStream.Length;        // в нулевую ячейку массива - количество байтов в сериализованной записи
  179.             memoryStream.Read(data, 1, (int)memoryStream.Length); // в массив с первой ячейки все из сериализованной записи из памяти
  180.             bw.Write(data);                             // запись массива байтов в конец файла
  181.             fs.Close();
  182.         }
  183.         static void AddToIndexes(IndexEntry entry)
  184.         {
  185.             var fs = new FileStream(dbPath, FileMode.Open, FileAccess.Read);
  186.             fs.Position = 0;
  187.             if ((int)fs.Length == 255)                                              // если в базе 1 запись -
  188.             {
  189.                 AddToEndOfFile(entry);                                              // пишем в конец индексов;
  190.             }
  191.             else                                                                    // если больше одной  -
  192.             {
  193.                 bool done = false;
  194.                 var entryArray = new IndexEntry[(int)fs.Length / 255];
  195.                 int counter = 0;
  196.                 int i = 0;
  197.                 while (i < fs.Length / 255 - 1)
  198.                 {
  199.                     IndexEntry ejected = EjectEntry(i);
  200.                     int comp = ejected.key.CompareTo(entry.key);                // ej<en= -1 ej=en =0 ej>en=1
  201.                     if (comp == -1 || comp == 0)                                             // ФИО извлеченной записи < ФИО введенной                            
  202.                     {
  203.                         entryArray[counter++] = ejected;
  204.                     }
  205.                     else
  206.                     {
  207.                         if (!done)
  208.                         {
  209.                             entryArray[counter++] = entry;
  210.                             done = true;
  211.                         }
  212.                         entryArray[counter++] = ejected;
  213.                     }
  214.                     i++;
  215.                 }
  216.                 if (!done)
  217.                 {
  218.                     entryArray[counter] = entry;
  219.                 }
  220.  
  221.                 UpdateIndex(entryArray);
  222.             }
  223.             fs.Close();
  224.         }
  225.         static byte[] arrayOfSerialized(Person person)              // этот массив нужно будет писать в файл БД
  226.         {
  227.             var formatter = new BinaryFormatter();
  228.             var memoryStream = new MemoryStream();
  229.             byte[] data = new byte[255];                            // массив байтов под сериализованную запись (решение проблемы с размером)
  230.             formatter.Serialize(memoryStream, person);
  231.             memoryStream.Position = 0;
  232.             data[0] = (byte)memoryStream.Length;                    // в нулевую ячейку массива - количество байтов в сериализованной записи
  233.             memoryStream.Read(data, 1, (int)memoryStream.Length);   // в массив с первой ячейки все из сериализованной записи из памяти
  234.             return data;                                                    // этот массив нужно будет писать в файл
  235.         }
  236.         static byte[] arrayOfSerialized(IndexEntry entry)           // этот массив нужно будет писать в файл ИНДЕКСОВ
  237.         {
  238.             var formatter = new BinaryFormatter();
  239.             var memoryStream = new MemoryStream();
  240.             byte[] data = new byte[127];                            // массив байтов под сериализованную запись (решение проблемы с размером)
  241.             formatter.Serialize(memoryStream, entry);
  242.             memoryStream.Position = 0;
  243.             data[0] = (byte)memoryStream.Length;                    // в нулевую ячейку массива - количество байтов в сериализованной записи
  244.             memoryStream.Read(data, 1, (int)memoryStream.Length);   // в массив с первой ячейки все из сериализованной записи из памяти
  245.             return data;
  246.         }
  247.  
  248.         static void UpdateIndex(IndexEntry[] entryArray) // обновить файл индексов
  249.         {
  250.             string path = Path.Combine(Environment.CurrentDirectory, "index.dat");
  251.             var fs = new FileStream(path, FileMode.Truncate, FileAccess.Write);
  252.             fs.Close();
  253.             for (int i = 0; i < entryArray.Length; i++)
  254.             {
  255.                 entryArray[i].Show();
  256.                 AddToEndOfFile(entryArray[i]); // тут можно перезаписать не весь, а только обновленную часть
  257.             }
  258.         }
  259.         static void ListAllRecords() // вывести все записи БД
  260.         {
  261.             Console.Clear();
  262.             Console.WriteLine("{0,-42} {1,5} {2,9}", "№  ФИО", "Год", "Разряд");
  263.             var formatter = new BinaryFormatter();
  264.             var fs = new FileStream(dbPath, FileMode.Open, FileAccess.Read);
  265.             var ifs = new FileStream(indexPath, FileMode.Open, FileAccess.Read);
  266.              
  267.             for (int i = 0; i < ifs.Length/255; i++)
  268.             {
  269.                 var memoryStream = new MemoryStream();
  270.                 var data = new byte[255];                                           // объявить массив под сериализованную запись
  271.                 ifs.Read(data, 0, 255);                                             // считать в массив всю запись
  272.                 memoryStream.Write(data, 1, data[0]);                              // значимые байты записи - в ОЗУ
  273.                 memoryStream.Position = 0;
  274.                 IndexEntry entry = (IndexEntry)formatter.Deserialize(memoryStream);
  275.                 memoryStream = new MemoryStream();
  276.                 data = new byte[255];                                               // объявить массив под сериализованную запись
  277.                 fs.Position = entry.offset;
  278.                 fs.Read(data, 0, 255);                                              // считать в массив всю запись
  279.                 memoryStream.Write(data, 1, data[0]);                              // значимые байты записи - в ОЗУ
  280.                 memoryStream.Position = 0;
  281.                 Person person = (Person)formatter.Deserialize(memoryStream);
  282.                 Console.Write(i + 1 + ". ");
  283.                 person.Show();
  284.             }
  285.            
  286.             /* если заменить этим предыдущий цикл, записи будут выведены в порядке расположения в БД
  287.              * for (int i = 0; i < fs.Length / 255; i++)
  288.             {
  289.                 var memoryStream = new MemoryStream();
  290.                 var data = new byte[255];                                       // объявить массив под сериализованную запись
  291.                 fs.Read(data, 0, 255);                                          // считать в массив всю запись
  292.                 memoryStream.Write(data, 1, data[0]);                           // значимые байты записи - в ОЗУ
  293.                 memoryStream.Position = 0;
  294.                 Person person = (Person)formatter.Deserialize(memoryStream);    // десериализуем
  295.                 Console.Write(i + 1 + ". ");
  296.                 person.Show();
  297.             }*/
  298.              
  299.  
  300.             fs.Close();
  301.             ifs.Close();
  302.             Console.WriteLine("\nНажмите любую клавишу.");
  303.             Console.ReadKey();
  304.             Console.Clear();
  305.         }
  306.         static int PositionOfFirstAskedEntry(IndexEntry[] array, string key) // бинарный поиск первого вхождения записи с запрошенным полем в БД
  307.         {
  308.             int left = 0, right = array.Length - 1;
  309.             int middle;
  310.             do
  311.             {
  312.                 middle = (left + right) / 2;
  313.                 if (array[middle].key.CompareTo(key) == -1)
  314.                 {
  315.                     left = middle + 1;
  316.                 }
  317.                 else
  318.                 {
  319.                     right = middle;
  320.                 }
  321.             } while (left != right);
  322.             if (array[left].key == key)
  323.             {
  324.                 return left;
  325.             }
  326.             return (-1);
  327.         }
  328.         static bool NextEntryOK(int entryNumber, string request)
  329.         {
  330.             bool flag = false;
  331.             var formatter = new BinaryFormatter();
  332.             var fs = new FileStream(indexPath, FileMode.Open, FileAccess.Read);
  333.             flag = (entryNumber + 1 != fs.Length / 255) && (EjectEntry(entryNumber + 1).key == request);
  334.             fs.Close();
  335.             return flag;
  336.         }
  337.         static Person[] AddPersonToArray(Person[] array, Person personToAdd)
  338.         {
  339.             var newArray = new Person[array.Length + 1];
  340.             int i = 0;
  341.             for (i = 0; i < array.Length; i++)
  342.             {
  343.                 newArray[i] = array[i];
  344.             }
  345.             newArray[i] = personToAdd;
  346.             return newArray;
  347.         }
  348.         static Person[] SearchIndexesForKeys(string request) // создает массив найденных по ФИО записей БД лиюбо возврящает нулевую ссылку
  349.         {
  350.             Person[] array = new Person[0];
  351.             var entry = new IndexEntry();
  352.             var person = new Person();
  353.             int firstEntryOfRequestedKey = PositionOfFirstAskedEntry(ArrayOfEntries(), request);
  354.             if (firstEntryOfRequestedKey != -1)
  355.             {
  356.                 int currentEjectNumber = firstEntryOfRequestedKey;
  357.                 entry = EjectEntry(currentEjectNumber);
  358.                 int position = entry.offset;
  359.                 person = EjectPerson(position / 255);
  360.                 array = AddPersonToArray(array, person);
  361.                 while (NextEntryOK(currentEjectNumber, request))
  362.                 {
  363.                     array = AddPersonToArray(array, EjectPerson(EjectEntry(++currentEjectNumber).offset / 255));
  364.                 }
  365.                 return array;
  366.             }
  367.             else
  368.             {
  369.                 return null;
  370.             }
  371.         }
  372.         static void Main()
  373.         {
  374.             int act;
  375.             int exit = 2;
  376.             do
  377.             {
  378.                 IndexEntry entry;
  379.                 Person person;
  380.                 Console.WriteLine("1. Добавить участника");
  381.                 if (File.Exists(dbPath))
  382.                 {
  383.                     Console.WriteLine("2. Изменить информацию об участнике");
  384.                     Console.WriteLine("3. Найти участника по ФИО");
  385.                     Console.WriteLine("4. Вывести список всех участников");
  386.  
  387.                     Console.WriteLine("5. Удалить участника");
  388.                     exit = 6;
  389.                 }
  390.                 Console.WriteLine(exit + ". Выход");
  391.                 act = AskForAction(exit);
  392.  
  393.                 switch (act)
  394.                 {
  395.                     case 1:
  396.                         person = AskForNewPerson();                                  // запрос новой записи
  397.                         Console.Clear();
  398.                         var fs = new FileStream(dbPath, FileMode.OpenOrCreate, FileAccess.Read);
  399.                         int offset = (int)fs.Length;                                        // offset - номер байта, начиная с которого в файле хранится запись
  400.                         fs.Close();
  401.                         byte[] ar1 = arrayOfSerialized(person);                             // ar1 - массив с сер. person [255]
  402.                         int length = ar1[0];                                                // length - длина сер. person
  403.                         entry = new IndexEntry(person.name, length, offset);                // entry - запись индексов
  404.                         AddToEndOfFile(person);
  405.                         AddToIndexes(entry);
  406.                         break;
  407.                     case 3:
  408.                         Console.Clear();
  409.                         Console.Write("Введите ФИО для поиска: ");
  410.                         string request = Console.ReadLine();
  411.                         var arrayOfFoundPersons = SearchIndexesForKeys(request);
  412.                         if (arrayOfFoundPersons == null)
  413.                         {
  414.                             Console.Clear();
  415.                             Console.WriteLine("По запросу \"{0}\" ни одной записи не найдено.", request);
  416.                             Console.WriteLine("\nНажмите любую клавишу.");
  417.                             Console.ReadKey();
  418.                             Console.Clear();
  419.                         }
  420.                         else
  421.                         {
  422.                             Console.Clear();
  423.                             Console.WriteLine("По запросу \"{0}\" найдены записи:\n", request);
  424.                             Console.WriteLine("{0,-42} {1,5} {2,9}", "№  ФИО", "Год", "Разряд");
  425.                             for (int i = 0; i < arrayOfFoundPersons.Length; i++)
  426.                             {
  427.                                 Console.Write(i + 1 + ". ");
  428.                                 arrayOfFoundPersons[i].Show();
  429.                             }
  430.                             Console.WriteLine("\nНажмите любую клавишу.");
  431.                             Console.ReadKey();
  432.                             Console.Clear();
  433.                         }
  434.                         break;
  435.                     case 4:
  436.                         ListAllRecords();
  437.                         break;
  438.                 }
  439.  
  440.             } while (act != exit);      
  441.         }
  442.     }
  443.  
  444. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement