Exemplo n.º 1
0
        internal static void SortDIFIle(string di_filename, string path, long start, long length)
        {
            string tmpfilename = path + "tmp.bin";
            long n_pairs = length / 16L;
            if (n_pairs < 40000001)
            {
                EntPredOff[] arr = new EntPredOff[n_pairs];
                using (FileStream inputstream = new FileStream(di_filename, FileMode.Open, FileAccess.Read))
                {
                    inputstream.Seek(start, SeekOrigin.Begin);
                    BinaryReader br = new BinaryReader(inputstream);

                    for (int cnt = 0; cnt < n_pairs; cnt++)
                    {
                        if (cnt >= arr.Length) break;
                        int ien = br.ReadInt32();
                        int ipr = br.ReadInt32();
                        long off = br.ReadInt64();
                        arr[cnt] = new EntPredOff(ien, ipr, off);
                    }
                }

                Array.Sort<EntPredOff>(arr, CompareEPO);

                // теперь запишем отсортированные
                using (FileStream outputstream = new FileStream(di_filename, FileMode.Open, FileAccess.Write))
                {
                    outputstream.Seek(start, SeekOrigin.Begin);
                    BinaryWriter bw = new BinaryWriter(outputstream);
                    foreach (var epo in arr)
                    {
                        bw.Write(epo.ientity);
                        bw.Write(epo.ipredicate);
                        bw.Write(epo.offset);
                    }
                }
            }
            else
            {
                // Разбиваем задачу на две подзадачи, используем точку start2 как начало второго массива
                long half_len = ((length / 16) / 2) * 16;
                SortDIFIle(di_filename, path, start, half_len);
                SortDIFIle(di_filename, path, start + half_len, length - half_len);

                // Теперь надо сливать результаты. Нужны два входных и один выходной файлы, надо не забыть поставить Share
                FileStream fs1 = new FileStream(di_filename, FileMode.Open, FileAccess.Read, FileShare.Read);
                FileStream fs2 = new FileStream(di_filename, FileMode.Open, FileAccess.Read, FileShare.Read);
                fs1.Seek(start, SeekOrigin.Begin);
                fs2.Seek(start + half_len, SeekOrigin.Begin);
                BinaryReader br1 = new BinaryReader(fs1);
                BinaryReader br2 = new BinaryReader(fs2);

                BinaryWriter bw = new BinaryWriter(new FileStream(tmpfilename, FileMode.Create, FileAccess.Write));

                long cnt1 = half_len / 16;
                int ient1 = br1.ReadInt32();
                int ipred1 = br1.ReadInt32();
                long off1 = br1.ReadInt64();

                EntPredOff epo1 = new EntPredOff(ient1, ipred1, off1);

                long cnt2 = (length - half_len) / 16;
                int ient2 = br2.ReadInt32();
                int ipred2 = br2.ReadInt32();
                long off2 = br2.ReadInt64();

                EntPredOff epo2 = new EntPredOff(ient2, ipred2, off2);

                while (cnt1 > 0 && cnt2 > 0)
                {
                    int cmp = CompareEPO(epo1, epo2);
                    if (cmp < 0)
                    { // Предполагаю, что надо работать с первой парой
                        bw.Write(epo1.ientity);
                        bw.Write(epo1.ipredicate);
                        bw.Write(epo1.offset);
                        cnt1--;

                        if (cnt1 > 0)
                        {
                            ient1 = br1.ReadInt32();
                            ipred1 = br1.ReadInt32();
                            off1 = br1.ReadInt64();
                            epo1 = new EntPredOff(ient1, ipred1, off1);
                        }
                    }
                    else
                    {
                        bw.Write(epo2.ientity);
                        bw.Write(epo2.ipredicate);
                        bw.Write(epo2.offset);
                        cnt2--;
                        if (cnt2 > 0)
                        {
                            ient2 = br2.ReadInt32();
                            ipred2 = br2.ReadInt32();
                            off2 = br2.ReadInt64();
                            epo2 = new EntPredOff(ient2, ipred2, off2);
                        }
                    }
                }
                // Дописывание остатка (это можно было бы оптимизировать, переписывая через буфер)
                if (cnt1 > 0)
                {
                    while (cnt1 > 0)
                    {
                        bw.Write(epo1.ientity);
                        bw.Write(epo1.ipredicate);
                        bw.Write(epo1.offset);
                        cnt1--;

                        if (cnt1 > 0)
                        {
                            ient1 = br1.ReadInt32();
                            ipred1 = br1.ReadInt32();
                            off1 = br1.ReadInt64();
                            epo1 = new EntPredOff(ient1, ipred1, off1);
                        }
                    }
                }
                else if (cnt2 > 0)
                {
                    while (cnt2 > 0)
                    {
                        bw.Write(epo2.ientity);
                        bw.Write(epo2.ipredicate);
                        bw.Write(epo2.offset);
                        cnt2--;
                        if (cnt2 > 0)
                        {
                            ient2 = br2.ReadInt32();
                            ipred2 = br2.ReadInt32();
                            off2 = br2.ReadInt64();
                            epo2 = new EntPredOff(ient2, ipred2, off2);
                        }
                    }
                }
                br1.Close(); fs1.Close();
                br2.Close(); fs2.Close();
                bw.Close();

                // Теперь надо переписать полученный массив на место
                BinaryReader br3 = new BinaryReader(new FileStream(tmpfilename, FileMode.Open, FileAccess.Read));
                FileStream fs3 = new FileStream(di_filename, FileMode.Open, FileAccess.Write);
                fs3.Seek(start, SeekOrigin.Begin);
                BinaryWriter bw3 = new BinaryWriter(fs3);

                long cnt3 = length / 16;
                while (cnt3 > 0)
                {
                    int ient3 = br3.ReadInt32();
                    int ipred3 = br3.ReadInt32();
                    long off3 = br3.ReadInt64();
                    bw3.Write(ient3);
                    bw3.Write(ipred3);
                    bw3.Write(off3);
                    cnt3--;
                }

                bw3.Close();
                fs3.Close();
                br3.Close();
            }
        }
Exemplo n.º 2
0
 private static int CompareEPO(EntPredOff x, EntPredOff y)
 {
     int c = x.ientity.CompareTo(y.ientity);
     return c != 0 ? c : x.ipredicate.CompareTo(y.ipredicate);
 }