Я пытаюсь сделать некоторый парсинг, который будет более легкими регулярными выражениями использования.
Вход является массивом (или перечисление) байтов.
Я не хочу преобразовывать байты в символы по следующим причинам:
Таким образом, я не могу использовать Regex.
Единственное решение, которое я знаю, использует Повышение. Regex (который работает над байтами - C символы), но это - библиотека C++, что обертывание использующий C++ / CLI возьмет значительную работу.
Как я могу использовать регулярные выражения на байтах в.NET непосредственно, не работая со строками.NET и символами?
Спасибо.
Здесь наблюдается небольшое несоответствие импеданса. Вы хотите работать с регулярными выражениями в .Net, которые используют строки (многобайтовые символы), но вы хотите работать с однобайтовыми символами. Вы не можете использовать оба одновременно, используя .Net, как обычно.
Однако, чтобы устранить это несоответствие, вы можете обработать строку побайтно-ориентированным образом и изменить ее. Затем измененная строка может действовать как повторно используемый буфер. Таким образом, вам не придется преобразовывать байты в символы или преобразовывать входной буфер в строку (согласно вашему вопросу).
Пример:
//BLING
byte[] inputBuffer = { 66, 76, 73, 78, 71 };
string stringBuffer = new string('\0', 1000);
Regex regex = new Regex("ING", RegexOptions.Compiled);
unsafe
{
fixed (char* charArray = stringBuffer)
{
byte* buffer = (byte*)(charArray);
//Hard-coded example of string mutation, in practice you would
//loop over your input buffers and regex\match so that the string
//buffer is re-used.
buffer[0] = inputBuffer[0];
buffer[2] = inputBuffer[1];
buffer[4] = inputBuffer[2];
buffer[6] = inputBuffer[3];
buffer[8] = inputBuffer[4];
Console.WriteLine("Mutated string:'{0}'.",
stringBuffer.Substring(0, inputBuffer.Length));
Match match = regex.Match(stringBuffer, 0, inputBuffer.Length);
Console.WriteLine("Position:{0} Length:{1}.", match.Index, match.Length);
}
}
Используя эту технику, вы можете выделить строковый «буфер», который можно повторно использовать в качестве входных данных для Regex, но вы можете каждый раз изменять его своими байтами.Это позволяет избежать накладных расходов на преобразование \ кодирование вашего массива байтов в новую строку .Net каждый раз, когда вы хотите выполнить сопоставление. Это может оказаться очень важным, поскольку я видел, как многие алгоритмы в .Net пытались разогнаться со скоростью миллион миль в час, но были поставлены на колени из-за генерации строки и последующего спама в куче и времени, проведенного в GC.
Очевидно, что это небезопасный код, но это .Net.
Однако результаты Regex будут генерировать строки, так что здесь у вас есть проблема. Я не уверен, есть ли способ использовать Regex, который не будет генерировать новые строки. Вы, конечно, можете получить информацию об индексе совпадения и длине, но генерация строки нарушает ваши требования к эффективности памяти.
Обновление
На самом деле после дизассемблирования Regex \ Match \ Group \ Capture похоже, что он генерирует захваченную строку только при доступе к свойству Value, поэтому вы можете, по крайней мере, не создавать строки, если вы обращаетесь только к индексу и длине характеристики. Однако вы будете генерировать все поддерживающие объекты Regex.
Ну, если бы я столкнулся с этой проблемой, я бы сделал обертку на C++/CLI, только я бы создал специализированный код для того, чего я хочу достичь. В конце концов, со временем я разработаю обертку для общих вещей, но это просто вариант.
Первый шаг - обернуть только вход и выход Boost::Regex. Создать специализированные функции на C++, которые делают все, что вы хотите, и использовать CLI только для передачи входных данных в код C++, а затем получить результат обратно с помощью CLI. Мне это не кажется слишком сложной работой.
Обновление:
Позвольте мне попытаться прояснить свою точку зрения. Даже если я могу ошибаться, я считаю, что вы не сможете найти ни одной реализации .NET Binary Regex, которую вы могли бы использовать. Поэтому - нравится вам это или нет - вы будете вынуждены выбирать между CLI-оберткой и преобразованием байтов в символы для использования .NET's Regex. На мой взгляд, обертка - лучший выбор, потому что она будет работать быстрее. Я не проводил никаких сравнительных тестов, это просто предположение, основанное на следующем: