Read / write binary string data - BinaryReader

I wrote a method below to archive files into a single file using binary mode:

// 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; } } 

I am reading data files using ReadFileData, which is in the method above the method that returns the data string. (StreamReader) Next, I extract my archive. Everything was done perfectly, but the data that will be stored in the extraction method does not give me the correct data, so the extracted files have incorrect data to show their original functionality.

Extraction method:

  // 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; } } 

Structure:

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

Thanks.

+4
source share
3 answers

Consider using byte arrays to write and protect data.

Byte array (write)

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

Byte array (read)

 Int32 byteCount = myStream.ReadInt32(); Byte[] bytes = new Byte[byteCount]; myStream.Read(bytes, 0, byteCount); 
+1
source

If your Data can be binary, then you should not have them in string . They must be byte[] .

When you write a string using ASCII encoding, just like you, and try to write binary data, many of the bytes (treated as Unicode characters) cannot be encoded and therefore you will get corrupted data.

The moral of the story: never treat binary data as text.

+1
source

An example of an icon makes it clear; you use string APIs to process data that is not strings (icons are not string-based). Moreover, you are usig ASCII, so only characters in the range 0-127 would be correct. In principle, you cannot do this. You need to process binary data using binary methods (possibly using the Stream API).

Other parameters:

  • use serialization to store object instances with data properties and BLOB (bytes []) for content
  • use something like zip (maybe SharpZipLib) which does something very similar, essentially
0
source

Source: https://habr.com/ru/post/1382069/


All Articles