Чтение / запись строковых двоичных данных - BinaryReader - PullRequest
4 голосов
/ 19 ноября 2011

Я написал следующий метод для архивирования файлов в один файл в двоичном режиме:

        // Compile archive
        public void CompileArchive(string FilePath, ListView FilesList, Label Status, ProgressBar Progress)
        {
            FileTemplate TempFile = new FileTemplate();
            if (FilesList.Items.Count > 0)
            {
                BinaryWriter Writer = new BinaryWriter(File.Open(FilePath, FileMode.Create), System.Text.Encoding.ASCII);
                Progress.Maximum = FilesList.Items.Count - 1;
                Writer.Write((long)FilesList.Items.Count);
                for (int i = 0; i <= FilesList.Items.Count - 1; i++)
                {
                    TempFile.Name = FilesList.Items[i].SubItems[1].Text;
                    TempFile.Path = "%ARCHIVE%";
                    TempFile.Data = this.ReadFileData(FilesList.Items[i].SubItems[2].Text + "\\" + TempFile.Name);
                    Writer.Write(TempFile.Name);
                    Writer.Write(TempFile.Path);
                    Writer.Write(TempFile.Data);
                    Status.Text = "Status: Writing '" + TempFile.Name + "'";
                    Progress.Value = i;
                }
                Writer.Close();
                Status.Text = "Status: None";
                Progress.Value = 0;
            }
        }

Я читаю данные файлов, используя ReadFileData, который находится в методе вышеупомянутого метода, который возвращает строку данных.(StreamReader) Далее я извлекаю свой архив.Все сделано отлично, но данные, которые будут сохранены в методе извлечения, не дают мне правильных данных, поэтому извлеченные файлы не имеют правильных данных, чтобы показать их исходную функциональность.

Метод извлечения:

    // Extract archive
    public void ExtractArchive(string ArchivePath, string ExtractPath, ListView FilesList, Label Status, ProgressBar Progress)
    {
        FileTemplate TempFile = new FileTemplate();
        BinaryReader Reader = new BinaryReader(File.Open(ArchivePath, FileMode.Open), System.Text.Encoding.ASCII);
        long Count = Reader.ReadInt64();
        if (Count > 0)
        {
            Progress.Maximum = (int)Count - 1;
            FilesList.Items.Clear();
            for (int i = 0; i <= Count - 1; i++)
            {
                TempFile.Name = Reader.ReadString();
                TempFile.Path = Reader.ReadString();
                TempFile.Data = Reader.ReadString();
                Status.Text = "Status: Reading '" + TempFile.Name + "'";
                Progress.Value = i;
                if (!Directory.Exists(ExtractPath))
                {
                    Directory.CreateDirectory(ExtractPath);
                }
                BinaryWriter Writer = new BinaryWriter(File.Open(ExtractPath + "\\" + TempFile.Name, FileMode.Create), System.Text.Encoding.ASCII);
                Writer.Write(TempFile.Data);
                Writer.Close();
                string[] ItemArr = new string[] { i.ToString(), TempFile.Name, TempFile.Path };
                ListViewItem ListItem = new ListViewItem(ItemArr);
                FilesList.Items.Add(ListItem);
            }
            Reader.Close();
            Status.Text = "Status: None";
            Progress.Value = 0;
        }
    }

Структура:

struct FileTemplate
        {
            public string Name, Path, Data;
        }

Спасибо.

Ответы [ 3 ]

1 голос
/ 19 ноября 2011

Если ваши Data могут быть двоичными данными, то их не должно быть в string.Они должны быть byte[].

Когда вы пишете строку, используя кодировку ASCII, как вы делаете, и пытаетесь записать двоичные данные, многие из байтов (рассматриваемых как символы Юникода) не могут быть закодированы итаким образом, вы получите поврежденные данные.

Мораль истории: никогда не рассматривайте двоичные данные как текст.

1 голос
/ 19 ноября 2011

Рассмотрите возможность использования байтовых массивов для записи и сохранения данных.

Массив байтов (запись)

Byte[] bytes = File.ReadAllBytes(..);
// Write it into your stream
myStream.Write(bytes.Count);
myStream.Write(bytes, 0, bytes.Count);

Массив байтов (чтение)

Int32 byteCount = myStream.ReadInt32();
Byte[] bytes = new Byte[byteCount];
myStream.Read(bytes, 0, byteCount);
0 голосов
/ 19 ноября 2011

Пример иконки проясняет; вы используете API на основе строк для обработки данных, которые не являются строками (значки не основаны на строках). Более того, вы используете ASCII, поэтому только символы в диапазоне 0-127 будут правильными. По сути, вы не можете этого сделать. Вам нужно обрабатывать двоичные данные, используя двоичные методы (возможно, используя Stream API).

Другие опции:

  • использовать сериализацию для хранения экземпляров объектов со свойствами данных и BLOB (байт []) для содержимого
  • используйте что-то вроде zip (может быть SharpZipLib), что делает что-то очень похожее, по существу
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...