Ответ 1
Вы хотите BlockCopy
В соответствии с этот пост в блоге он быстрее, чем Array.CopyTo.
Есть ли лучший способ (см. ниже) добавить два байтовых массива в С#?
Притворяясь, что у меня есть полный контроль, я могу сделать первый массив байтов достаточно большим для хранения второго массива байтов в конце и использовать Array.CopyTo. Или я могу перебрать отдельные байты и выполнить назначение.
Есть ли лучшие способы? Я не могу себе представить, что вы делаете что-то вроде преобразования массивов байтов в строку и их присоединения, а их преобразование будет лучше, чем любой из вышеперечисленных методов.
С точки зрения лучшего/лучшего (по порядку):
Ограничение состоит в том, что я должен работать в среде .NET 2.0.
Рекомендуются два варианта: MemoryStream и BlockCopy. Я пропустил простой тест скорости 10 000 000 циклов 3 раза и получил следующие результаты:
Результаты списка <byte> AddRange более 10 миллионов циклов: Список <byte> Время: 16694
Тест показывает, что в общем случае, если вы не делаете много копий байта [ , которые я], просмотр байтовых копий не стоит особого внимания (например, 10 миллионов запусков дают разницу в 1,1 секунды].
Вы хотите BlockCopy
В соответствии с этот пост в блоге он быстрее, чем Array.CopyTo.
Создайте новый MemoryStream, передав в конструктор буфер, который точно совпадает с размером объединенного. Напишите отдельные массивы, а затем, наконец, используйте буфер:
byte[] deadBeef = new byte[] { 0xDE, 0xAD, 0xBE, 0xEF};
byte[] baadF00d = new byte[] { 0xBA, 0xAD, 0xF0, 0x0D};
int newSize = deadBeef.Length + baadF00d.Length;
var ms = new MemoryStream(new byte[newSize], 0, newSize, true, true);
ms.Write(deadBeef, 0, deadBeef.Length);
ms.Write(baadF00d, 0, baadF00d.Length);
byte[] merged = ms.GetBuffer();
Многие низкоуровневые функции ввода/вывода в .NET берут байтовые массивы и смещения. Это было сделано для предотвращения ненужных копий. Убедитесь, что вам действительно нужен объединенный массив, если он чувствителен к производительности, иначе просто используйте буферы и смещения.
Вы также можете использовать подход с MemoryStream. Предположим, что b1 и b2 - это два байтовых массива, вы можете получить новый, b3, используя MemoryStream следующим образом:
var s = new MemoryStream();
s.Write(b1, 0, b1.Length);
s.Write(b2, 0, b2.Length);
var b3 = s.ToArray();
Это должно работать без LINQ и на самом деле довольно быстро.
Другой вариант, хотя я не тестировал его, чтобы увидеть, как он работает с точки зрения скорости и потребления памяти, будет ли подход LINQ:
byte[] combined = bytesOne.Concat(bytesTwo).Concat(bytesThree).ToArray();
... где bytesOne, bytesTwo и bytesThree - массивы байтов. Поскольку Concat использует отложенное выполнение, это не должно создавать промежуточные массивы и не должно дублировать исходные массивы до тех пор, пока они не конструируют окончательный объединенный массив в конце.
Изменить: LINQBridge позволит вам использовать LINQ-to-Objects (это пример) в фреймворке 2.0. Я понимаю, если вы не хотите зависеть от этого, но это вариант.
Если у вас есть массивы, размер которых будет меняться время от времени, вам, вероятно, лучше использовать List<T>
в первую очередь. Затем вы можете просто вызвать метод AddRange()
списка.
В противном случае Array.Copy() или Array.CopyTo() будут такими же хорошими, как и все, что вы, вероятно, увидите.
Вы учили использовать List или ArrayList вместо массива? С этими типами они могут расти или сжиматься и добавлять через InsertRange
Вам нужен вывод для фактического байтового массива?
Если нет, вы можете создать себе "умный курсор" (что похоже на то, что делает LINQ): создать пользовательский IEnumerator <byte> который сначала перебирает первый массив, а просто продолжит второй, без перерыва.
Это будет работать в среде 2.0 быстро (в том, что объединение массивов практически не требует затрат), и не используйте больше RAM, чем массивы уже потребляют.
Ваша первая возможность сделать первый массив достаточно большим, чтобы содержать второй массив, и использование Array.CopyTo заканчивается примерно таким же, как ручное повторение каждого элемента и выполнение задания. Array.CopyTo() просто делает его более кратким.
Преобразование в строку и обратно в массив будет ужасно медленным, в отличие от вышеизложенного. И, скорее всего, будет использовать больше памяти.