Я создаю простой самораспаковывающийся архив, используя магический номер, чтобы отметить начало содержимого. Пока это текстовый файл:
MAGICNUMBER .... содержимое текстового файла
Далее текстовый файл копируется в конец исполняемого файла:
скопировать programm.exe/b+textfile.txt/b sfx.exe
Я пытаюсь найти второе вхождение магического числа (очевидно, первое будет жестко запрограммированной константой), используя следующий код:
string my_filename = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
StreamReader file = new StreamReader(my_filename);
const int block_size = 1024;
const string magic = "MAGICNUMBER";
char[] buffer = new Char[block_size];
Int64 count = 0;
Int64 glob_pos = 0;
bool flag = false;
while (file.ReadBlock(buffer, 0, block_size) > 0)
{
var rel_pos = buffer.ToString().IndexOf(magic);
if ((rel_pos > -1) & (!flag))
{
flag = true;
continue;
}
if ((rel_pos > -1) & (flag == true))
{
glob_pos = block_size * count + rel_pos;
break;
}
count++;
}
using (FileStream fs = new FileStream(my_filename, FileMode.Open, FileAccess.Read))
{
byte[] b = new byte[fs.Length - glob_pos];
fs.Seek(glob_pos, SeekOrigin.Begin);
fs.Read(b, 0, (int)(fs.Length - glob_pos));
File.WriteAllBytes("c:/output.txt", b);
но почему-то я копирую почти весь файл, а не последние несколько килобайт. Это из-за оптимизации компилятора, встраивания магической константы в цикл while чего-то подобного?
Как мне правильно сделать самораспаковывающийся архив?
Думаю, я должен читать файл задом наперед, чтобы избежать проблем с компилятором, многократно встраивающим магическую константу. Итак, я изменил свой код следующим образом:
string my_filename = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
StreamReader file = new StreamReader(my_filename);
const int block_size = 1024;
const string magic = "MAGIC";
char[] buffer = new Char[block_size];
Int64 count = 0;
Int64 glob_pos = 0;
while (file.ReadBlock(buffer, 0, block_size) > 0)
{
var rel_pos = buffer.ToString().IndexOf(magic);
if (rel_pos > -1)
{
glob_pos = block_size * count + rel_pos;
}
count++;
}
using (FileStream fs = new FileStream(my_filename, FileMode.Open, FileAccess.Read))
{
byte[] b = new byte[fs.Length - glob_pos];
fs.Seek(glob_pos, SeekOrigin.Begin);
fs.Read(b, 0, (int)(fs.Length - glob_pos));
File.WriteAllBytes("c:/output.txt", b);
}
Итак, я просмотрел весь файл один раз, обнаружил, что это будет последнее вхождение магического числа, и скопировал его отсюда до конца. Хотя файл, созданный этой процедурой, кажется меньше, чем в предыдущей попытке, это никоим образом не тот файл, который я прикрепил к моему «самораспаковывающемуся» архиву. Почему?
Я предполагаю, что вычисление позиции начала прикрепленного файла неверно из-за используемого преобразования из двоичного кода в строку. Если да, то как мне изменить расчет позиции, чтобы сделать его правильным?
Также как мне выбрать магический номер, а затем работать с реальными файлами, например, с pdf? Я не смогу легко изменить pdf-файлы, чтобы включить в него предопределенный магический номер.