Create a "directory" in memory? - c#

I'm working in c#, and looking for a way to create a path to a directory that will map to an IO.Stream instead of to the actual file system.
I want to be able to "save" files to that path, manipulate the content or file names, and then save them from that path to a regular file in the file system.
I know I can use a temporary file, but I would rather use the memory for both security and performance.
This kind of thing exists, according to this answer, in Java, using the FileSystemProvider class. I'm looking for a way to do it in c#.
I've tried every search I could think of and came up only with the java answer and suggestions to use Temporary files.
Is it even possible using .net?
Basically, I'm looking for a way to enable saving files directly to memory as if they where saved into the file system.
so, for instance, if I had a 3rd party class that exposes a save method (save(string fullPath)), or something like the SmtpServer.Send(MyMsg) in this question, i could choose that path and save it into the memory stream instead of onto the drive. (the main thing here is that I want to provide a path that will lead directly to a memory stream).

.NET doesn't have an abstraction layer over the host OS's file system. So unless you can build your own for use in custom code, and you need to have 3rd party libraries covered, there are just two workable optilns:
Use streams and avoid any APIs working with file names.
Build a virtual file system plugged into your host OS's storage architecture; however, the effort needed versus benefits is highly questionable.

I went through a similar situation lately, and there is no out of the box solution in .NET for doing that although I used a workaround which was efficient and safe for me.
Using Ionic.Zip Nuget package you can create a whole directory with a complex structure as a stream in memory and although it will be created as a zip file, you can extract it as a stream or even send the zip file as a stream.
using (var zip = new Ionic.Zip.ZipFile())
{
zip.AddEntry($"file1.json", new MemoryStream(Encoding.UTF8.GetBytes(someJsonContent)));
for (int i = 0; i < 4; i++)
{
zip.AddEntry($"{myDir}/{i}.json", new MemoryStream(Encoding.UTF8.GetBytes(anotherJsonContent)));
}
}
And here is how to extract a zip file as a stream using Ionic.Zip

Related

Storing PDF in RamDisk vs MemoryMappedFile

I am using a library to create a PDF file from HTML, then I print that file and delete it from disk. The issue is, we don't want anything stored on disk, not even temporarily. I thought about using some kind of RamDisk, but I see MemoryMappedFile thrown around everywhere. I looked into it, but I don't think that provides the functionality I want since the file should already exist on disk before using it in a MemoryMappedFile.
My question is: Is my assumption true about the file needing to be on disk FIRST before using it in a MemoryMappedFile? IS there a way to create a MemoryMappedFile and access it using a virtual path without it existing on disk?
In case MemoryMappedFile doesn't work, what library can I use to create a virtual RamDisk with C#? It will only be storing 1 file at a time.

Convert .sav(spss) file to .csv file using c#

Can i Convert an spss(.sav) file to a .csv file by using C#. Here i want to browse 1 .sav file and i need to generate .csv file of the same.Can anyone provide any link or code for the conversion.
i have some 100 spss files so i need to create a console app which will take each file from the parent folder and generate the corresponding csv file for each sav file
There are several possibilities:
1) Use a library
There seems to be a library to read SPSS files.
You can install the NuGet package SpssLib and create a SpssReader object from a FileStream
using(var fileStream = File.OpenRead("spss-file.sav"))
{
var spssReader = new SpssReader(fileStream);
// read variable names from spssReader.Variables and store to CSV
// read records from spssReader.Records and store to CSV
}
2) Hand-code the solution
If you can't use the library for whatever reason, you may hand-code a solution.
2.1) Have a look at PSPP
If (and only if) you are planning (or at least fine with) releasing your code under the GPL, you can have a look at the PSPP source code. Anyway, if you can't GPL your code, Don't. Do. It. Do a clean-room implementation instead, since otherwise you'll always be on slippery grounds.
2.2) Have a look at the spec
There is a documentation of the SAV file format online. It may take some time, but you may eventually figure out how to convert this to CSV.
3) Use PSPP
If you have no problem shipping a GPLed software (or are able to download the files on demand somehow), you can make use of PSPPs console application. PSPP is a GNU replacement for SPSS, which aims at (but does not, yet) providing the funcitonality that SPSS provides. Obviously it comes with a handy little CLI tool pspp-convert (see the documentation). You can invoke it via the command line with
pspp-convert input.sav output.csv
With the help of the Process class you're able to start another process (i.e. program in this case). If pspp-convert is located in the current directory or in any directory that's in the PATH variable, converting a file to CSV is a easy as
public ConvertSpssFile(string inputFile)
{
var outputFile = Path.ChangeExtension(inputFile, "csv");
Process.Start("pspp-convert", $"{inputFile} {outputFile}");
}

Alternatives to ZIP for combining many files into one on Windows using .NET

Im looking for methods to combine files including their name and relative path into one single file. A folder disguised as a file. I don't need any compression or encryption. Just the file data including some binary metadata attached to each file.
It would be great if this file was possible to open/inspect/unpack with a standard file browser in Windows such as with regular zip-files.
Yes I could use zip. But I'm researching alternatives and I would prefer a simple method I could implement myself in C#/.NET.
UPDATE
I've researched this some more and came across Microsoft's Structured Storage format. It looked promising at first but it seemes to be an obsolete format, replaced with the Open Package Format. And then I found out about the TAR-format. It seemes to be the most basic format. But I'm not sure yet if I can add any custom metadata to the entries with TAR.
UPDATE
I went with DotNetZip at the end anyway...
Why not use zip? You can use a third party library, like dotnetzip, to make the code easy to write. And, as you mentioned, Windows handles zip files well.
If you have specific reason to search an alternative to ZIP, take a look on virtual file systems, eg. CodeBase File System or our Solid File System. Solid File System lets you add alternate data streams (like in NTFS) or tags (small chunks of binary or text data) to each file or directory. And with OS edition of SolFS you can make the filesystem visible to Windows (including Explorer and third-party applications).
I must admit that while virtual file systems are easy to use (easier than ZIP), they are commercial products (I didn't see free virtual file system implementations yet).

Is it possible to substitue a MemoryStream or StreamReader when an object expects a filename? (C#/.NET)

Say you have a method or property on a third party sealed component that expects a file name. You do not have the source for the third party component. You want that component to do what it's supposed to do (read only) on a file you have, but your file is encrypted on disk and you only want the decrypted version in memory so it cannot be easily copied in its plain form.
Is it possible to create a wrapper or some other approach to trick the component to think it's reading from a file when it's actually reading from a MemoryStream? Or is it totally impossible? Can it be done outside .NET in native Windows code?
Thanks
You can't do that the way that you are proposing, no. My recommendation would be to use the Encrypting Filesystem functionality built into windows. That way the file is stored in encrypted form on disk, but is available via the normal IO methods to the application (provided that the account that is running the application has access to the file).
Can it read from "CON" as input (like many text utilities grep/findstr, more,...)? In this case you can try to redirect input/output stream and feed results thata way.
Is it possible to create a wrapper or some other approach to trick the
component to think it's reading from a file when it's actually reading
from a MemoryStream?
No, sorry. You will have to decrypt the file into a temporary file and then pass this temporary file to the plugin. Once it finishes its work delete the temporary file.
This short answer is if a component is expecting a filename e.g. a string you can not parse it a memory stream.
However if the file is encrypted with Encrypting File System (EFS) or something native to Windows it may be able to decrypt the file without knowing the file is encrypted.
These might help:
http://en.wikipedia.org/wiki/Encrypting_File_System
http://en.wikipedia.org/wiki/BitLocker_Drive_Encryption
You could have a look at Dokan. I haven't tried it, but it's a way of creating a virtual file system in .Net.
You can create an in-memory disk drive (either in code or by using third-party application) and put a file there. Another approach is to implement virtual file system and handle all file requests. Both approaches are possible for example using our Virtual Storage products.
Also, I don't know about .NET in particular, but in Windows you can hook API functions and substitute certain operations (including file operations). There even exist components for this, but, again, I don't know if they offer their functionality for .NET.

Creating File On Full Disk

Is it possible to create a file on a disk which is full??
Does creation of the file take any space??
Basically I am seeing a case where C# has created but failed to write anything whhich I think points to a full disk.
Does anyone know whether creating a file on a full disk will fail or not??
This wa done using c# o Windw xSerevr- The log file was also written to the same drive
Creating (empty) files should still be possible in most cases. The MFT is a separate part of the volume which won't get used for file data.
It should even be possible to store small amounts of data without needing more than the file entry in the MFT. NTFS can store streams as "resident data" in the stream descriptor which doesn't need any additional space, but only works for very small files.
I think your issue is another problem, though. It may be that you have permissions to create a file but not to write anything to it. You might want to check the ACLs of the location where you're trying to write.

Categories

Resources