c# ping

Привет! Зарегистрируйте свой аккаунт сегодня, чтобы стать участником! После входа в систему вы сможете участвовать на этом сайте, добавляя свои собственные темы и сообщения. Преимущество регистрации, даёт возможность целиком и полностью пользоваться всеми сервисами форума!

Создание собственного расширения файла на основе бинарного файла.

Роман Кощеев

...
Проверен
Best answers
0
Всем привет, буду первым!
Статья не для совсем новичков, а для тех, кто хоть овладел ООП.
Сегодня хочу рассказать как создать свой файл, а точнее файл со своим расширением на основе бинарного файла.
Большинство игр и программ написано по такому алгоритму. Создаётся бинарный файл, внутри со своей структурой, и просто меняем на своё расширение.

Итак приступим. Для начала придумаем свое расширение. Пусть будет *.galileo
В Классе формы объявим свою структуру.
C#:
 public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        struct GALILEO
        {
            public string Date;  // Создание файла
            public string NameCreator; // Кто создал файл
            public string _text; //Запишем какой-нибудь текст
            //======Так же "зашьем" файл внутрь===========//
            public long ByteSize; //Узнаем количество байт файла (это нам потом пригодится)
            public string FileExt; //Узнаем расширение файла (тоже пригодится)
            public byte[] ByteSource; //ну и сами байты файла

            public GALILEO(
                string _Date,
                string _NameCreator,
                string __text,
                long _ByteSize,
                string _FileExt,
                byte[] _ByteSource)
            {
                Date = _Date;
                Razdel = _Razdel;
                NameCreator = _NameCreator;
                _text = __text;
                ByteSize = _ByteSize;
                FileExt = _FileExt;
                ByteSource = _ByteSource;
            }

        } //Вот и вся структура бинарного файла
    }
Дальше на форму повесим кнопку (для того чтобы цеплять файл), и сделаем ей событие.
в событии пишем
C#:
    string PathAttachFile = ""; //Переменная для храения пути какой файл вшиваем
    private void button1_Click(object sender, EventArgs e)
            {
                OpenFileDialog ofd = new OpenFileDialog();
                ofd.Title = "Укажите файл который надо прикрепить";
                //ofd.Filter = "MP4 video (*.mp4)|*mp4|Docx files (*.docx)|*.docx|Текстовые файлы (*.txt)|*.txt|Все файлы (*.*)|*.*";
                //Фильтр файлов которые будем вшивать можно указать
                ofd.FileName = "Укажите файл";
                ofd.RestoreDirectory = true;
                var ResultDialog = ofd.ShowDialog();
                if(ResultDialog == DialogResult.OK)
                {
                    PathAttachFile = ofd.FileName;
                }

            }
Теперь осталось вшить данные. Закинем на форму textBox для того чтобы записать какой-нибудь текст.
И ещё одну кнопку, чтобы обработать запись в бинарный файл.

C#:
 private void button2_Click(object sender, EventArgs e)
        {
            try
            {
                //Запишем в переменную наш файл. Считаем все данные с него.
                byte[] byte_AttachFile = File.ReadAllBytes(PathAttachFile);
             
                //Пора узнать какое расширение будет у нашего вшиваемого файла
                //Можно конечно узнать и через FileInfo, но мне так проще
                string ExtFile = tbAttFilePath.Text.Substring(tbAttFilePath.Text.LastIndexOf(".") + 1);
             
                //И теперь открываем поток и начинаем писать.
                using (BinaryWriter writer = new BinaryWriter(File.Open(/*Укажем как назовём свой файл*/ test.galileo, FileMode.OpenOrCreate)))
                {
                    //Переопределим значения для структуры, чтобы записать какие то значения
                    GALILEO[] galileo = new GALILEO[1];
                    galileo[0] = new GALILEO( //Пойдём по-порядку как и создавали структуру файла
                        DateTime.Now.ToString("dd/MM/yy HH:mm"),
                        Environment.UserName,
                        textBox1.Text,
                        byte_AttachFile.Length,
                        ExtFile,
                        byte_AttachFile);
                        );
                  //Пишем
                    foreach (GALILEO l in galileo)
                    {
                        writer.Write(l.Date);
                        writer.Write(l.NameCreator);
                        writer.Write(l._text);
                        writer.Write(l.ByteSize);
                        writer.Write(l.FileExt);
                        writer.Write(l.ByteSource);
                    }
                }
            }
            catch (Exception ex) { MessageBox.Show(ex.Message); } //Если будет ошибка, отловим
            finally { MessageBox.Show("файл galileo успешно создан"); } //Если все хорошо, сообщим об этом

        }
и всё. Файл вшит и данные в тоже. Но вот если открыть файл блокнотом, то мы можем увидеть некоторые строковые значения
Вот как пример

111.png

Зато файл точно не прочитать. Строковые значения можно легко зашифровать, и тогда точно простой пользователь ничего не увидит.
Теперь нам осталось прочитать файл.

Можно создать отдельную форму, можно тут же.
C#:
         //Я решил в отдельной форме делать
        private string pathGalileo;
        private string ExtensionFile = "";
        private void Form1_Load(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Title = "Укажите файл galileo";
            ofd.Filter = "Special galileo Files (*.galileo)|*galileo";
            ofd.FileName = "galileo файл";
            ofd.RestoreDirectory = true;
            var ResultDialog = ofd.ShowDialog();
            if (ResultDialog == DialogResult.OK)
            {
                pathGalileo = ofd.FileName;
                ReadGALILEOFile();
            }
        }

  void ReadGALILEOFile()
        {
            using (BinaryReader reader = new BinaryReader(File.Open(pathGalileo, FileMode.Open)))
            {
                // пока не достигнут конец файла
                // считываем каждое значение из файла
                while (reader.PeekChar() > -1)
                {
                    string Date = reader.ReadString();
                    string Name= reader.ReadString();
                    string TEXT = reader.ReadString();
                    var Size = reader.ReadUInt64();
                    ExtensionFile = reader.ReadString();
                    string StrSize = (Size / 1024 / 1024).ToString() + " MB";
                    File.WriteAllBytes(@"tmp." + ExtensionFile, reader.ReadBytes((int)Size));
                    DialogResult result = MessageBox.Show($"Дата создания {Date}, Имя создателя {Name} \r\n" +
                                $"Текст {TEXT} Расширение вшитого файла {ExtensionFile} и его размер {StrSize}\r\n\r\n" +
                                "Открыть вшитый файл?" , "Galileo", MessageBoxButtons.YesNo, MessageBoxIcon.Question );

                    if(result == DialogResult.Yes)
                    {
                           //Тут открываем вшитый файл как угодно, так как он хранится рядом
                                 Process.Start(@"tmp." + ExtensionFile);
                    }
                }
            
            }
        }
И чтобы файлы не копились и не засоряли каталог мы егопросто удалим
C#:
 private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            string filename = Application.StartupPath;
            filename = Path.GetFullPath(
                Path.Combine(filename, ".\\tmp." + ExtensionFile));
            File.Delete(filename);
        }
Вот к примеру структура файла из игры.
Код:
type = class WEAPON_ESSENCE {
public:
unsigned int id;
unsigned int id_major_type;
unsigned int id_sub_type;
namechar name[32];
unsigned int require_projectile;
char file_model_right[128];
char file_model_left[128];
char file_matter[128];
char file_icon[128];
int require_strength;
int require_agility;
int require_energy;
int require_tili;
unsigned int character_combo_id;
int require_level;
int require_reputation;
int level;
int fixed_props;
int damage_low;
int damage_high_min;
int damage_high_max;
int magic_damage_low;
int magic_damage_high_min;
int magic_damage_high_max;
float attack_range;
unsigned int short_range_mode;
int durability_min;
int durability_max;
int levelup_addon;
int material_need;
int price;
int shop_price;
int repairfee;
float drop_probability_socket0;
float drop_probability_socket1;
float drop_probability_socket2;
float make_probability_socket0;
float make_probability_socket1;
float make_probability_socket2;
float probability_addon_num0;
float probability_addon_num1;
float probability_addon_num2;
float probability_addon_num3;
float probability_addon_num4;
float probability_unique;
Не бойтесь экспериментировать, и самое главное не запутаться. Но я бы рекомендовал использовать готовые решения типа XML
 
Сверху