.net 从字节数组或流中获取文件名

7xllpg7q  于 2023-05-08  发布在  .NET
关注(0)|答案(5)|浏览(289)

是否可以从字节数组或流中获取文件名?我会保存文件。我只想找回它的名字。

fafcakar

fafcakar1#

如果Stream实际上是一个FileStream,那么这个 may 可以通过转换为FileStream并访问.Name属性来获得:

Stream stream = ...
FileStream fs = stream as FileStream;
if(fs != null) Console.WriteLine(fs.Name);

但是,在一般情况下:不,没有。byte[] * 当然 * 没有文件名的概念,大多数其他类型的流也没有。类似地,被其他流(压缩、加密、缓冲等) Package 的FileStream基本流将不会暴露此类信息,尽管底层流(向下几层)是一个文件。
我将单独处理文件名。

bakd9h0s

bakd9h0s2#

不,这是不可能的(好吧,也许在FileStream类上是可能的,每天都能学到新东西!)).
字节数组或字节流表示文件的内容,而不是文件的Windows元数据
有很多直接的方法来保留这些信息,但不知道任何更多的关于你的情况,我不能提供一个解决方案。

zdwk9cvp

zdwk9cvp3#

所有文件信息(如名称、扩展名等)都是实际文件的 meta数据的一部分。字节数组将只保存实际数据。如果字节数组本身包含 meta数据(例如xml文件),则可能是...但是,您需要知道类型以及具体的查找位置。

juud5qan

juud5qan4#

您将无法从字节数组中获取文件名。相反,您需要filestream来获取文件的名称。字节数组不存储名称。

af7jpaap

af7jpaap5#

可能有点晚了,但这是我的解决方案。这适用于PE文件,如.exe和. dll。代码逐字节读取,直到找到OriginalFilename属性(如果在记事本中打开.exe,也可以看到该属性)。需要设置.exe的OriginalFilename属性才能正常工作(否则返回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;
    }
}

二进制文件如下所示(\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
希望这对你有帮助

相关问题