2016-10-27 7 views
0

Так что в основном я пишу приложение, которое ищет файлы PNG в двоичном файле. Он делает это, читая в целом двоичный файл в массив байтов, а затем преобразовывая его в строку с помощью метода Convert.ToBase64String, а затем используя регулярное выражение, которое соответствует информации заголовка PNG и концевому фрагменту, чтобы найти изображения. Проблема заключается в использовании метода ToBase64String генерирует совершенно разные выходы в зависимости от длины массива байтов, и документация по MSDN, похоже, не описывает его. В любом случае, вот пример того, что я имею в виду.Как надежно regex a Base64String

byte[] somebytes = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; 

Console.WriteLine(Convert.ToBase64String(somebytes)); 

Выход в этом случае «AQIDBAUGBwg =» Теперь, если я пропущу байт ...

byte[] somebytes = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; 

somebytes = somebytes.Skip(1).ToArray(); 

Console.WriteLine(Convert.ToBase64String(somebytes)); 

Выход теперь «AgMEBQYHCA ==» так почти каждый персонаж изменился от предыдущий пример.

Так я безнадежно следую неправильному пути для регулярного выражения двоичного файла или есть метод (может быть, дополнением?) Я могу гарантировать большую согласованность между этими преобразованиями?

Update: На основе обратной связи я собрал, кажется, я просто должен отойти от решения Regex и ручного поиска последовательностей начала и конца байта вручную сам. Не уверен, почему меня задерживают, так как я просто хотел понять, почему мое другое решение действительно сработало, и, похоже, нет никаких других сообщений по этой теме. В любом случае, спасибо всем за быструю обратную связь. Я отправлю алгоритм, который я использовал для поиска изображений, когда я закончил, если он может принести пользу кому-то другому.

+1

Да, вы. Нет смысла делать base64, а затем пытаться найти заголовок. Почему бы просто не найти в двоичном коде? Или если вы должны использовать шестнадцатеричный для согласования –

+3

* «Он делает это, читая в целом двоичный файл в массив байтов, а затем преобразовывая его в строку с использованием метода Convert.ToBase64String, а затем используя регулярное выражение, соответствующее заголовку PNG информацию и конец фрагмента, чтобы найти изображения. "* Что ...? У вас есть байтовый массив, поэтому выполните поиск массива байтов. –

+1

Что касается изменения, это изменяется, потому что вы перемещаете массив. Base64 принимает по 6 бит за раз и переводит в символ. Если вы переместитесь на байты (8 бит), вы получите совершенно разные символы. –

ответ

0

Вы подтвердили в комментариях, что пытаетесь извлечь ресурсы из структурированного файла C# (EXE или DLL). Вы можете использовать методы отражения, чтобы вытащить их: GetManifestResourceStream, GetManifestResourceNames, GetManifestResourceInfo - хорошая отправная точка.

+0

Спасибо за то, что я обязательно попробую испортить это. Я все еще могу продолжать читать байты вручную, но в идеале было бы неплохо, если бы заменитель изображений работал больше, чем просто .Net-бинарные файлы, но эта информация по-прежнему очень полезна! – Thermonuclear

+1

@Thermonuclear, родные двоичные файлы C++ также структурированы и имеют apis для взаимодействия с ресурсами. Вы не должны пытаться делать это самостоятельно, поскольку это более сложно, чем вы думаете. Что, если текущий PNG составляет 1000 байтов, и вы хотите заменить его на то, что составляет 1010 байт? Вы перезапишете код/​​другие ресурсы. API позаботятся об этом для вас. – SledgeHammer

+0

Мое приложение изначально предназначалось только для замены изображений на изображениях, которые были либо равны, либо меньше, чем оригинал, заменяемый, тем самым избегая этой проблемы, по крайней мере, он работал, когда я делал это вручную для приложения WPF. Однако, если эти API-интерфейсы дают мне возможность обменивать изображение для более крупного, что дает мне очень веские основания пересмотреть мою сферу для этой способности. – Thermonuclear

0

Как и было сказано, логика, которую я написал, чтобы найти изображения в двоичном формате, в случае, если это может помочь кому-то другому. Тем не менее, я могу в конечном счете использовать метод SledgeHammers, но для меня было важно, что я могу справиться с этим, используя этот метод.

public class BinarySearch 
{ 
    public static IEnumerable<byte[]> Match(byte[] source, byte[] beginningSequence, byte[] endSequence) 
    { 
     int index = 0; 

     IList<byte[]> matches = new List<byte[]>(); 

     while (index < source.Length) 
     { 
      var startIndex = FindSequence(source, beginningSequence, index); 

      if (startIndex >= 0) 
      { 
       var endIndex = FindSequence(source, endSequence, startIndex + beginningSequence.Length); 

       if (endIndex >= 0) 
       { 
        var length = (endIndex - startIndex) + endSequence.Length; 
        var buffer = new byte[length]; 

        Array.Copy(source, startIndex, buffer, 0, length); 

        matches.Add(buffer); 

        index = endIndex + endSequence.Length; 
       } 
       else 
       { 
        index = source.Length; 
       } 
      } 
      else 
      { 
       index = source.Length; 
      } 
     } 

     return matches; 
    } 

    private static int FindSequence(byte[] bytes, byte[] sequence, int startIndex = 0) 
    { 
     int currentIndex = startIndex; 
     int sequenceIndex = 0; 
     bool found = false; 

     while (!found && currentIndex < bytes.Length) 
     { 
      if (bytes[currentIndex] == sequence[sequenceIndex]) 
      { 
       if (sequenceIndex == (sequence.Length - 1)) 
       { 
        found = true; 
       } 
       else 
       { 
        sequenceIndex++; 
       } 
      } 
      else 
      { 
       currentIndex -= sequenceIndex; 
       sequenceIndex = 0; 
      } 

      currentIndex++; 
     } 

     return found ? (currentIndex - sequence.Length) : -1; 
    } 
} 

Приведен пример использования PNG-файлов.

var imageHeaderStart = new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00 }; 

var imageEOF = new byte[] { 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82 }; 

var matches = BinarySearch.Match(binaryData, imageHeaderStart, imageEOF); 

Я добавлю ссылку на проект Github на это завершение в случае, если кто заинтересован в моем «полной» реализации.