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(); } }
private static int CompareEPO(EntPredOff x, EntPredOff y) { int c = x.ientity.CompareTo(y.ientity); return c != 0 ? c : x.ipredicate.CompareTo(y.ipredicate); }