Binary reading data from exe file - c#

I want to read data from exe file.
On java i read exe perfect from start to end,
bun on c# i cannot read all file.
File lenth is true but in result show only head of exe file
string fileLoc = filePaths[0];
FileStream fs = new FileStream(fileLoc, FileMode.Open, FileAccess.Read, FileShare.Read);
BinaryReader br = new BinaryReader(fs);
byte[] bin = br.ReadBytes(Convert.ToInt32(fs.Length));
foreach(byte b in bin){
Console.Write((char)b);
}
fs.Close();
output is only the head of exe: MZP

Cannot reproduce:
string fileLoc = //my path to git.exe
FileStream fs = new FileStream(fileLoc, FileMode.Open, FileAccess.Read, FileShare.Read);
BinaryReader br = new BinaryReader(fs);
byte[] bin = br.ReadBytes(Convert.ToInt32(fs.Length));
foreach (byte b in bin)
{
Console.Write((char)b);
}
fs.Close()
It writes all data from it.
But i see many problems in your code:
1) never do work with files with such unsafer way (if error occured file will not close) rewrite:
string fileLoc = //my path to git.exe
using(FileStream fs = new FileStream(fileLoc, FileMode.Open, FileAccess.Read, FileShare.Read)) {
BinaryReader br = new BinaryReader(fs);
byte[] bin = br.ReadBytes(Convert.ToInt32(fs.Length));
foreach (byte b in bin)
{
Console.Write((char)b);
}
} // no more explicit close required, but it will closed with guarantee
2) not mistake but in C# it's preferable use var (analoug to auto in c++)
using(var fs = new FileStream(fileLoc, FileMode.Open, FileAccess.Read, FileShare.Read)) {
var br = new BinaryReader(fs);
var bin = br.ReadBytes(Convert.ToInt32(fs.Length));
foreach (var b in bin)
{
Console.Write((char)b);
}
} //it still strong typed, but type referenced only once at right side of assigment
3) Not require use Convert for explicitly castable types (long->int)
var bin = br.ReadBytes((int)fs.Length);
4) I don't know why only MZP is written in your case, but can imagine that if you cast byte to char you will get many not-printable symbols including \r \n \f and so on in output - how your concrete terminal will be react? - i don't know
5) If you print (char)b just for test of bin - why so badly - why you not simply test bin.Length or why you print (char)b and not b+" " ? Otherwise if you really want to print bytes to console - it's bad idea anyway - look (4)
6) Why BinaryReader? if you just want read all
using(var fs = new FileStream(fileLoc, FileMode.Open, FileAccess.Read, FileShare.Read)) {
var bin = new byte[(int)fs.Length];
// u can use usual stream pattern
int l=0; while((l+=fs.Read(bin,t,bin.Length-t))<bin.Length);
foreach (var b in bin)
{
Console.Write((char)b);
}
}

Related

C# equivalent to zlib.decompress

What is the equivalent of the Python function zlib.decompress() in C#? I need to decompress some zlib files using C# and I don't know how to do it.
Python example:
import zlib
file = open("myfile", mode = "rb")
data = zlib.decompress(file.read())
uncompressed_output = open("output_file", mode = "wb")
uncompressed_output.write(data)
I tried using the System.IO.Compression.DeflateStream class, but for every file I try it gives me an exception that the file contains invalid data while decoding.
byte[] binary = new byte[1000000];
using (DeflateStream compressed_file = new DeflateStream(new FileStream(#"myfile", FileMode.Open, FileAccess.Read), CompressionMode.Decompress))
compressed_file.Read(binary, 0, 1000000); //exception here
using (BinaryWriter outputFile = new BinaryWriter(new FileStream(#"output_file", FileMode.Create, FileAccess.Write)))
outputFile.Write(binary);
//Reading the file like normal with a BinaryReader and then turning it into a MemoryStream also didn't work
I should probably mention that the files are ZLIB compressed files. They start with the 78 9C header.
So, luckily, I found this post: https://stackoverflow.com/a/33855097/10505778
Basically the file must be stripped of its 2 header bytes (78 9C). While the 9C is important in decompression (it specifies whether a preset dictionary has been used or not), I don't need it, but I am pretty sure it is not that difficult to modify this to accomodate it:
byte[] binary, decompressed;
using (BinaryReader file = new BinaryReader(new FileStream(#"myfile", FileMode.Open, FileAccess.Read, FileShare.Read))
binary = file.ReadBytes(int.MaxValue); //read the entire file
output = new byte[int.MaxValue];
int outputSize;
using (MemoryStream memory_stream = new MemoryStream(binary, false))
{
memory_stream.Read(decompressed, 0, 2); //discard 2 bytes
using (DeflateStream compressed_file = new DeflateStream(memory_stream, CompressionMode.Decompress)
outputSize = compressed_file.Read(decompressed, 0, int.MaxValue);
}
binary = new byte[outputSize];
Array.Copy(decompressed, 0, binary, 0, outputSize);
using (BinaryWriter outputFile = new BinaryWriter(new FileStream(#"output_file", FileMode.Create, FileAccess.Write)))
outputFile.Write(binary);

Read and write from/to the same line with BinaryReader/BinaryWriter

I want to read a binary file line by line (I'm writing of course continously, but I know that after 457 bytes new data start and I know exactly the byte structure and where which information is written to) and change a special entry of the line. I get an System.IO.IOException when I try to access the same file with both BinaryReader and BinaryWriter. I use locking to prevent that the file is accessed from somewhere else.
My code is:
using (FileStream fs2 = new FileStream(testfile, FileMode.Open, FileAccess.Read))
{
using (BinaryReader r = new BinaryReader(fs2))
{
using (BinaryWriter bw = new BinaryWriter(new FileStream(testfile, FileMode.Open, FileAccess.Write), utf8))
{
for (int i = 0; i < 11000; i+=457)
{
int myint = r.ReadInt64();
bw.Seek(i, SeekOrigin.Current);
bw.Write(myint*2);
}
}
}
}
How can I do this?
Do not create the second FileStream because the file is locked for the read operation by the first FileStream object.
If you are sure about file structure, the exception only can come out from 2nd FileStream instantiation. See link below for more information:
Read and Write to File at the same time
It is working for me using the following code:
if (File.Exists(testfile))
{
FileInfo fi = new FileInfo(testfile);
using (FileStream fs2 = new FileStream(testfile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (BinaryReader r = new BinaryReader(fs2))
{
r.BaseStream.Seek(0, SeekOrigin.Begin);
using (BinaryWriter bw = new BinaryWriter(new FileStream(testfile, FileMode.Open, FileAccess.Write, FileShare.ReadWrite)))
{
for (int i = 0; i <= (fi.Length-177); i += 177)//181
{
}
}
}
}
}

How to split a Filestream into two substreams

Is there a way to split a filestream which is obtained via
File.Open("100GB.bin", FileMode.Open, FileAccess.Read, FileShare.Read)
into 2 equally sized substreams?
I would like to upload the file partially to a website, but the webserver has limitations on the maximum filesize allowed for posting.
Two streams are necessary to simultaneously upload the parts to the website.
Thanks in advance.
If the website doesn't provide a multi-part upload mechanism, just read N bytes into different streams:
using (var fs = File.Open("100GB.bin", FileMode.Open, FileAccess.Read, FileShare.Read))
{
var chunkSizeInBytes = ...; // whatever you like, below code assumes it's evenly divisible into your 100GB file
var numChunks = fs.Length / chunkSizeInBytes;
var buf = new byte[chunkSizeInBytes];
for (int i = 0, bufIndex = 0; i < numChunks; ++i, bufIndex += chunkSizeInBytes)
{
fs.Read(buf, bufIndex, chunkSizeInBytes);
// if, for whatever reason, you actually need a new stream,
// just create a MemoryStream and use fs.CopyTo(stream, size)
PostMyData(buf);
}
}

Uploading ".xlsx" file using DropBox API making file corrupted

DropboxClient dbx = new DropboxClient("************************");
var file = "/Excel/FileName.xlsx";
byte[] bytes = null;
FileStream fs = new FileStream("C:\\Users\\Admin\\Desktop\\Test.xlsx", FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
long numBytes = fs.Length;
bytes = br.ReadBytes((int)numBytes);
var mem = new MemoryStream(Encoding.UTF8.GetBytes(bytes.ToString()));
var updated = await dbx.Files.UploadAsync(file, WriteMode.Overwrite.Instance, body: mem);
Here is the code, it overwrite the existing file as per need but make that file corrupted.
I think you're thinking too complex here. UploadAsync expects a Stream. MemoryStream is indeed a Stream, but so is FileStream. Getting rid of the extra reader will result in:
var source = "C:\\Users\\Admin\\Desktop\\Test.xlsx";
var target = "/Excel/FileName.xlsx";
using(var dbx = new DropboxClient("***"))
using(var fs = new FileStream(source, FileMode.Open, FileAccess.Read))
{
var updated = await dbx.Files.UploadAsync(
target, WriteMode.Overwrite.Instance, body: fs);
}
The reason the file will get corrupt is because of reading the data incorrectly. bytes.ToString() will result in System.Byte[]. You're actually uploading System.Byte[] literally instead of the file's contents, which is not a valid Excel document. Also converting a binary file into UTF-8 text doesn't work as expected, because it alters the content being uploaded.

How to Overwrite Existing Text Using FileStream

NOTE: I can't use FileMode.Create or FileMode.Truncate because they would cause some unwanted problem
byte[] data = new UTF8Encoding().GetBytes(this.Box.Text);
FileStream f = File.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
f.Write(data, 0, data.Length);
f.Close();
This will append new text to the top of the old one. How can I overwrite everything?
your code
byte[] data = new UTF8Encoding().GetBytes(this.Box.Text);
FileStream f = File.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
f.Write(data, 0, data.Length);
f.Close();
how come you can't do something like this..? please explain why you can't use FileMode.Create
byte[] data = new UTF8Encoding().GetBytes(this.Box.Text);
using(Stream f = File.Open(path, FileMode.Write))
{
f.Write(data, 0, data.Length);
}
you could also do something like the following
1. Let the users write to the same file
2. capture the users Machine Name or User Id then
2. write a line in your file like this
strSeprate = new string('*',25);
//will write to the file "*************************";
f.Write(strSeprate);
f.Write(Machine Name or UserId);
f.Write(data);
f.Write(DateTime.Now.ToString());
f.Write(strSeprate);
just an idea..

Categories

Resources