Advertisement
kot025

INDEX 1,3,4

Mar 14th, 2015
205
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 20.58 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.  
  266.             for (int i = 0; i < fs.Length / 255; i++)
  267.             {
  268.                 var memoryStream = new MemoryStream();
  269.                 var data = new byte[255];                                       // объявить массив под сериализованную запись
  270.                 fs.Read(data, 0, 255);                                          // считать в массив всю запись
  271.                 memoryStream.Write(data, 1, data[0]);                           // значимые байты записи - в ОЗУ
  272.                 memoryStream.Position = 0;
  273.                 Person person = (Person)formatter.Deserialize(memoryStream);    // десериализуем
  274.                 Console.Write(i + 1 + ". ");
  275.                 person.Show();
  276.             }
  277.  
  278.             fs.Close();
  279.             Console.WriteLine("\nНажмите любую клавишу.");
  280.             Console.ReadKey();
  281.             Console.Clear();
  282.         }
  283.         static int PositionOfFirstAskedEntry(IndexEntry[] array, string key)
  284.         {
  285.             int left = 0, right = array.Length - 1;
  286.             int middle;
  287.             do
  288.             {
  289.                 middle = (left + right) / 2;
  290.                 if (array[middle].key.CompareTo(key) == -1)
  291.                 {
  292.                     left = middle + 1;
  293.                 }
  294.                 else
  295.                 {
  296.                     right = middle;
  297.                 }
  298.             } while (left != right);
  299.             if (array[left].key == key)
  300.             {
  301.                 return left;
  302.             }
  303.             return (-1);
  304.         }
  305.         static bool NextEntryOK(int entryNumber, string request)
  306.         {
  307.             bool flag = false;
  308.             var formatter = new BinaryFormatter();
  309.             var fs = new FileStream(indexPath, FileMode.Open, FileAccess.Read);
  310.             flag = (entryNumber + 1 != fs.Length / 255) && (EjectEntry(entryNumber + 1).key == request);
  311.             fs.Close();
  312.             return flag;
  313.         }
  314.         static void Main()
  315.         {
  316.             int act;
  317.             int exit = 2;
  318.             do
  319.             {
  320.                 IndexEntry entry;
  321.                 Person person;
  322.                 Console.WriteLine("1. Добавить участника");
  323.                 if (File.Exists(dbPath))
  324.                 {
  325.                     Console.WriteLine("2. Изменить информацию об участнике");
  326.                     Console.WriteLine("3. Найти участника по ФИО");
  327.                     Console.WriteLine("4. Вывести список всех участников");
  328.  
  329.                     Console.WriteLine("5. Удалить участника");
  330.                     exit = 6;
  331.                 }
  332.                 Console.WriteLine(exit + ". Выход");
  333.                 act = AskForAction(exit);
  334.  
  335.                 switch (act)
  336.                 {
  337.                     case 1:
  338.                         person = AskForNewPerson();                                  // запрос новой записи
  339.                         Console.Clear();
  340.                         var fs = new FileStream(dbPath, FileMode.OpenOrCreate, FileAccess.Read);
  341.                         int offset = (int)fs.Length;                                        // offset - номер байта, начиная с которого в файле хранится запись
  342.                         fs.Close();
  343.                         byte[] ar1 = arrayOfSerialized(person);                             // ar1 - массив с сер. person [255]
  344.                         int length = ar1[0];                                                // length - длина сер. person
  345.                         entry = new IndexEntry(person.name, length, offset);     // entry - запись индексов
  346.                         //byte[] ar2 = arrayOfSerialized(entry);                              //ar2 - массив с сер. entry [128]
  347.                         AddToEndOfFile(person);
  348.                         AddToIndexes(entry);
  349.                         break;
  350.                     case 3:
  351.                         int counter = 0;
  352.                         Console.Clear();
  353.                         Console.Write("Введите ФИО для поиска: ");
  354.                         string request = Console.ReadLine();
  355.                         int firstEntryOfRequestedKey = PositionOfFirstAskedEntry(ArrayOfEntries(), request);
  356.                         if (firstEntryOfRequestedKey != -1)
  357.                         {
  358.                             Console.Clear();
  359.                             Console.WriteLine("По запросу \"{0}\" найдены записи:\n",request);
  360.                             Console.WriteLine("{0,-42} {1,5} {2,9}", "№  ФИО", "Год", "Разряд");
  361.                             int currentEjectNumber = firstEntryOfRequestedKey;
  362.                             entry = EjectEntry(currentEjectNumber);
  363.                             int position = entry.offset;
  364.                             person = EjectPerson(position / 255);
  365.                             Console.Write(++counter + ". ");
  366.                             person.Show();
  367.                             while (NextEntryOK(currentEjectNumber, request))
  368.                             {
  369.                                 Console.Write(++counter + ". ");
  370.                                 EjectPerson(EjectEntry(++currentEjectNumber).offset / 255).Show();
  371.                             }
  372.                             Console.WriteLine("\nНажмите любую клавишу.");
  373.                             Console.ReadKey();
  374.                             Console.Clear();
  375.                         }
  376.                         else
  377.                         {
  378.                             Console.Clear();
  379.                             Console.WriteLine("По запросу \"{0}\" ни одной записи не найдено.", request);
  380.                             Console.WriteLine("\nНажмите любую клавишу.");
  381.                             Console.ReadKey();
  382.                             Console.Clear();
  383.                         }
  384.  
  385.                         //Console.WriteLine(PositionOfFirstAskedEntry(ArrayOfEntries(), Console.ReadLine()));
  386.                         break;
  387.                     case 4:
  388.                         ListAllRecords();
  389.                         break;
  390.                 }
  391.  
  392.             } while (act != exit);      
  393.         }
  394.     }
  395.  
  396. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement