Writing a File that has the Name of a Device

2019-02-16 17:35发布

问题:

I have run into something curious. I have a decompiler that extracts information from a binary file. I am extracting a series of objects that I need to write separately to disk as binary files. These objects are graphic models compiled into a library. The objects have names embedded in them and I need to use that name as the file name.

I am using :

try {
            // Open file for reading . 
            using (var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write)) {
                // Writes a block of bytes to this stream using data from a byte array. . 
                fileStream.Write(byteArray, 0, byteArray.Length);
                // close file stream . 
                fileStream.Close();
            }
            return true;
        }

        catch (Exception exception) {
            return false;
        }

I realize my exception handling is not great! However the problem showed up when one of the objects to save had the name COM2 This caused an exception:

FileStream will not open Win32 devices such as disk partitions and tape drives.

So in my example I am trying to write a file called COM2.mdl and get this error. I really don't want to have to change these names since they are embedded by the developer.

I considered testing the names against a list of devices that may cause the error - but I really don't know what that list might be and also it would mean changing the name of the file which I don't want to do.

So my question: Is there a way to write a byte array as a binary file other than with FileStream that might get over this issue?

Many thanks

回答1:

The reserved names are AUX, CLOCK$, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, CON, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9, NUL and PRN.

You won't be able to create files with these names (and with any extension, e.g. COM2.txt on Windows on any File System - that's a Windows Kernel enforced thing, for backwards compatibility with CP/M. It MAY be a limitation on FAT filesystems though, but it's not on NTFS. See Wikipedia for some more info.

However, you can try to use UNC File Names, these should to work:

echo test > com2.txt
-> The system cannot find the file specified.

echo test > \\mypc\c$\Users\Michael\Desktop\com2.txt
-> works flawlessly

I'm not 100% sure if UNC Paths work with File Stream, but there certainly is a way to use them in .net.



回答2:

Wrap the call to "new FileStream" with a try/catch block to specifically catch System.ArgumentException. If you catch this, assume the the filename is invalid and try again with a different filename (e.g. prepend "foo" to the filename string).

Also, you can use System.IO.Path.GetInvalidPathChars() and System.IO.Path.GetInvalidFileNameChars(); to get the complete list of "invalid characters" that won't fit inside a windows filename. So you can strip out or replace those chars fromthe filename string before attempting to create the file.



标签: c# filestream