Is it possible to get filename from the byte array or stream? I wont to save the file. I just want to retrieve its name.
If the Stream
is actually a FileStream
, then this may be available by casting to FileStream
and accessing the .Name
property:
Stream stream = ...
FileStream fs = stream as FileStream;
if(fs != null) Console.WriteLine(fs.Name);
However, in the general case: no, this is not available. A byte[]
certainly has no concept of a filename, nor do most other types of streams. Likewise, a FileStream
base-stream that is being wrapped by other streams (compression, encryption, buffering, etc) will not expose such information, despite the underlying stream (several layers down) being a file.
I would handle the filename separately.
No this isn't possible (ok so it might be possible on the FileStream
class, learn something new everyday!).
A byte array or stream represents the content of the file, not the Windows metadata about the file.
There are plenty of straightfoward ways to retain this information, but not knowing any more about your situation I can't offer a solution.
All file information (such as name, extension etc.) is part of meta data for an actual file. The byte array will only hold the actual data. It may be possible if the byte array itself holds meta data (example an xml file)... however, you'd need to know the type and specifically where to look.
You will not able to get filename from byte array. Instead you need filestream to get the name of the file. Byte array does not store name.
It might be late for this but here's my solution. This works for PE file such as .exe and .dll. The code reads byte by byte until it finds the OriginalFilename property (it can also be seen if you open the .exe in Notepad. OriginalFilename property of the .exe needs to be set in order to work properly (or it returns null)
public string GetOriginalFilenameFromStream(Stream stream)
{
if (stream == null)
return null;
string lookupString = "O\0r\0i\0g\0i\0n\0a\0l\0F\0i\0l\0e\0n\0a\0m\0e"; // OriginalFilename with null char between each letter
int originalFileNameLength = 550; // I bit more than 512 (256 * 2 (for the nulls)) + the possible extensions
//Go at the end of the stream
stream.Seek(0, SeekOrigin.Begin);
long currentPosition = 0;
bool hasFoundBytes = false;
byte[] bit = new byte[1] { 0 };
char[] lookupStringChars = lookupString.ToCharArray();
byte[] lookupBytes = Encoding.ASCII.GetBytes(lookupStringChars);
do
{
for (int i = 0; i < lookupBytes.Length; i++)
{
if (bit[0] == lookupBytes[i])
{
hasFoundBytes = true;
if (i == lookupBytes.Length - 1)
break; // Stops reading if the end of the lookupBytes has been reached (string has been found)
else
currentPosition = stream.Read(bit, 0, 1);
}
else
{
hasFoundBytes = false;
currentPosition = stream.Read(bit, 0, 1);
break;
}
}
} while (currentPosition != 0 && !hasFoundBytes && stream.Position < 1073741824 /* 1 MB */);
if (!hasFoundBytes)
{
// Lookup not found in the file
return null;
}
// Gets the OriginalFilename from the stream
byte[] originalFilenameByteArray = new byte[originalFileNameLength];
stream.Read(originalFilenameByteArray, 0, originalFileNameLength);
string parsedOriginalFilename = ParseOriginalFilename(Encoding.ASCII.GetString(originalFilenameByteArray));
_logWriter?.Info($"{this.GetType().Name} {nameof(GetOriginalFilenameFromStream)} returns {parsedOriginalFilename}");
return parsedOriginalFilename;
string ParseOriginalFilename(string stringToParse)
{
// Gets the text between the 2 first 3 nulls \0\0\0
string nullChar = "\0";
string threeNulls = string.Format("{0}{0}{0}", nullChar);
int pFrom = stringToParse.IndexOf(threeNulls) + threeNulls.Length;
int pTo = stringToParse.IndexOf(threeNulls, pFrom);
string originalFilename = stringToParse.Substring(pFrom, pTo - pFrom);
// Removes the nulls between each letters
originalFilename = originalFilename.Replace(nullChar, "");
return originalFilename;
}
}
The binary looks like this (\0 is a null characther):
O\0r\0i\0g\0i\0n\0a\0l\0F\0i\0l\0e\0n\0a\0m\0e\0\0\0T\0e\0s\0t\0A\0p\0p\0.\0e\0x\0e\0\0\0...
And the parsed Original Filename looks like this:
TestApp.exe
Hope this helps
if the bytes array contains file version informations like originalFilname,InternalName,FileVersion,ProductName you can get it
but if you want to get fullpath of a file from file byte array it would impossible since fullpath is related to disk path not to file data.
based on @Steve Rousseau answer i converted the code to work in powershell that i'm familiar with, and add minor modifications
function Get-AppInfoFromBytes{
[CmdletBinding()]
param(
$bytes,
[string]
$VersionInfo="OriginalFilename"
)
if ( $bytes -IsNot [byte[]] ) {throw 'byte data required';}
if ( $bytes.Length -gt 80kb -Or $bytes.Length -lt 3kb ) {write-warning 'A BYTE LENGTH OF 80KB MAX OR 3KB MIN FROM HEAD OR TAIL OF A FILE IS ENOUGH TO CONTAIN THE INFO';}
# preserving the nullchar effect in string
[string]$lookupString = iex -command "echo $( ($VersionInfo -replace '(.)','`0$1').remove(0,2) )"
[int16]$AppInfoValueLength = 550; # // I bit more than 512 (256 * 2 (for the nulls)) + the possible extensions
write-verbose "searching property `"$lookupString`""
[int32]$position=0
$position=([System.Text.Encoding]::ASCII.GetString($bytes)).Indexof($lookupString)
if ($Position -eq -1) {
write-verbose "VersionInfo `"$VersionInfo`" property was not Found`nplease check other properties or supply another bytes portion"
return $null;
}
write-verbose "Gets the Info from byte data...note that even the info exist it may contain an empty string"
[byte[]]$bytes=$bytes[$position..($position+$AppInfoValueLength)]
[string]$S=[System.Text.Encoding]::ASCII.GetString($bytes);
$3Nuls = "`0`0`0"
$3NulsStartIdx1 = $S.IndexOf($3Nuls) + 3
$3NulsStartIdx2 = $S.IndexOf($3Nuls, $3NulsStartIdx1);
return $S.Substring($3NulsStartIdx1,$3NulsStartIdx2-$3NulsStartIdx1).Replace("`0", "" )
}
you can call the function like that:
#getting the bytes methods:
PS > [byte[]]$bytes=cat "C:\Users\Zdilto\Desktop\File.exe" -tail 3kb -enc byte
PS > $bytes=cat "C:\Users\Zdilto\Desktop\File.exe" -total 76kb -AsByteStream
PS > $bytes=[io.file]::ReadAllBytes("C:\Users\Zdilto\Desktop\File.exe")
PS > $bytes=$bytes[0..10kb]
#calling the function:
PS > Get-AppInfoFromBytes -b $bytes -verbose;
PS > Get-AppInfoFromBytes -b $bytes -v "LegalCopyright" -verbose;
PS > Get-AppInfoFromBytes -b $bytes -v "InternalName";
PS > Get-AppInfoFromBytes -b $bytes -v "ProductName";
PS > Get-AppInfoFromBytes -b $bytes -v "Comments" -verbose;
#testing result:
PS > $result=Get-AppInfoFromBytes -byte $bytes -VersionInfo Comments -verbose;
PS > if( [string]::IsNullOrEmpty($result) ) {"got no value"} else {"success"}
© 2022 - 2024 — McMap. All rights reserved.