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;
}
}
5条答案
按热度按时间fafcakar1#
如果
Stream
实际上是一个FileStream
,那么这个 may 可以通过转换为FileStream
并访问.Name
属性来获得:但是,在一般情况下:不,没有。
byte[]
* 当然 * 没有文件名的概念,大多数其他类型的流也没有。类似地,被其他流(压缩、加密、缓冲等) Package 的FileStream
基本流将不会暴露此类信息,尽管底层流(向下几层)是一个文件。我将单独处理文件名。
bakd9h0s2#
不,这是不可能的(好吧,也许在
FileStream
类上是可能的,每天都能学到新东西!)).字节数组或字节流表示文件的内容,而不是文件的Windows元数据。
有很多直接的方法来保留这些信息,但不知道任何更多的关于你的情况,我不能提供一个解决方案。
zdwk9cvp3#
所有文件信息(如名称、扩展名等)都是实际文件的 meta数据的一部分。字节数组将只保存实际数据。如果字节数组本身包含 meta数据(例如xml文件),则可能是...但是,您需要知道类型以及具体的查找位置。
juud5qan4#
您将无法从字节数组中获取文件名。相反,您需要filestream来获取文件的名称。字节数组不存储名称。
af7jpaap5#
可能有点晚了,但这是我的解决方案。这适用于PE文件,如.exe和. dll。代码逐字节读取,直到找到OriginalFilename属性(如果在记事本中打开.exe,也可以看到该属性)。需要设置.exe的OriginalFilename属性才能正常工作(否则返回null)
二进制文件如下所示(\0是空字符):
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...
解析后的原始文件名如下所示:TestApp.exe
希望这对你有帮助