Внешняя сортировка слиянием в C#: невозможно прочитать после окончания потока - PullRequest
0 голосов
/ 29 февраля 2020

Итак, я пытаюсь реализовать внешнюю сортировку слиянием в C#, но получаю сообщение об ошибке: Невозможно прочитать за пределами конца потока. Когда я вызываю Метод MergeSort, я использую эти параметры:

MergeSort(fileName, 0, elementCount - 1)

Я пытался изменить с 0 на 1 и с (elementCount -1) на elementCount, но это не сработало. Методы MergeSort и Merge:

Полная ошибка:

! Необработанное исключение: System.IO.EndOfStreamException: невозможно прочитать за пределы конца потока. в System.IO.BinaryReader.FillBuffer (Int32 numBytes) в System.IO.BinaryReader.ReadInt32 () в Merge_Sort.BinaryOperations.getElement (Int32 index) в C: \ Users \ Портативный компьютер \ source \ repos \ Merge_Sort \ Merge_Sort \ BinaryOperations.cs: строка 22 в Merge_Sort.Program.Merge (строка fileName, Int32 слева, Int32 mid, Int32 справа) в C: \ Users \ Laptop \ source \ repos \ Merge_Sort \ Merge_Sort \ Program.cs: строка 70 в Merge_Sort.Program.MergeSort (строковое имя файла, Int32 слева, Int32 справа) в C: \ Users \ Laptop \ source \ repos \ Merge_Sort \ Merge_Sort \ Program.cs: строка 35 в Merge_Sort.Program.MergeSort (строковое имя файла, Int32 слева, Int32 справа) в C: \ Users \ Laptop \ source \ repos \ Merge_Sort \ Merge_Sort \ Program.cs: строка 31 в Merge_Sort.Program.MergeSort (строковое имя файла, Int32 слева, Int32 справа) в C: \ Users \ Laptop \ source \ repos \ Merge_Sort \ Merge_Sort \ Program.cs: строка 33 в Merge_Sort.Program.MergeSort (строковое имя файла, Int32 слева, Int32 справа) в C: \ Users \ Laptop \ source \ repos \ Merge_Sort \ Merge_Sort \ Program.cs: строка 31 в Merge_Sort.Program.Main (String [] args) в C: \ Users \ Laptop \ source \ repos \ Merge_Sort \ Merge_Sort \ Program.cs: строка 16

static public int MergeSort(string fileName, int left, int right)
        {
            int opCounter = 0;
            opCounter++;
            if(left < right)
            {
                opCounter++;
                int mid = (left + right) / 2;
                opCounter++;
                opCounter += MergeSort(fileName, left, mid);
                opCounter++;
                opCounter += MergeSort(fileName, mid + 1, right);
                opCounter++;
                opCounter += Merge(fileName, left, mid, right);
                opCounter++;
            }
               return opCounter;
        }

        private static int Merge(string fileName, int left, int mid, int right)
        {
            int opCounter = 0;
            number++;
            BinaryOperations mainOp = new BinaryOperations(fileName);
            int num = (int)DateTime.Now.TimeOfDay.TotalSeconds;
            string temp = "b" + num.ToString() + "" + number.ToString() + ".bin";
            string tempFile = "E:/Merge_Sort/Merge_Sort/bin/Debug/temp/" + temp;
            BinaryOperations tempOp = new BinaryOperations(tempFile);

            int size = right - left;
            tempOp.newFile(size);

            int i = 0;
            int j = left;

            for(j = left; j <=mid; j++)
            {
                opCounter++;
                tempOp.setElement(i++, mainOp.getElement(j));
                opCounter += 6;
            }
            i = 0;
            int k = left;
            opCounter += 2;
            while (k < j && j <= right)
            {
                opCounter++;
                opCounter += 12;
                if ((tempOp.getElement(i)) <= (mainOp.getElement(j)))
                {
                    mainOp.setElement(k++, tempOp.getElement(i++));
                    opCounter += 11;
                }
                else
                {
                    mainOp.setElement(k++, mainOp.getElement(j++));
                    opCounter += 11;
                }
            }
            while( k < j)
            {
                opCounter++;
                mainOp.setElement(k++, tempOp.getElement(i++));
                opCounter += 11;
            }

            return opCounter;
        }

Класс BinaryOperations:

class BinaryOperations
    {
        string fileName;
        public BinaryOperations(string fileName)
        {
            this.fileName = fileName;
        }
        public int getElement(int index)
        {
            BinaryReader reader = new BinaryReader(File.Open(fileName,
                FileMode.Open, FileAccess.Read));
            reader.BaseStream.Seek(index * 4, SeekOrigin.Begin);
            int value = reader.ReadInt32();
            reader.Close();
            return value;
        }

        public void setElement(int index, int value)
        {
            BinaryWriter writer = new BinaryWriter(File.Open(fileName, FileMode.Open, FileAccess.ReadWrite));
            writer.Seek(index * 4, SeekOrigin.Begin);
            writer.Write(value);
            writer.Close();
        }
        public void newFile(int size)
        {
            using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
            {
                fs.SetLength(size);
            }
        }

    }
...