for a small project, I would like to be able to store additional information about a file and keep that information with the file even when it is moved.
The additional information will be stored in a XML-file. To keep the file and its description together, I thought about using ZIP-archives without any compression, but I would like these ZIP-archives to behave just like the original files (i.e. if the original file was a video file, a double-click on the archive should open the file in the media player). This requires me to write a small program that handles this 'new' file format.
However, I have not found a solution that would allow me to open the file without first extracting the file from the archive (even without compression), which does take some time and is not what I want.
My questions are: Is there a library (for C# or C/C++) that allows me to open a zip file and directly play/open a file inside it wihout extracting the archive? Or is there an easier way to implement what I need (maybe I am thinking in the wrong direction)?
Windows already allows you to store additional metadata about a shell item (including files) through the Windows Property System.
The Windows API Code Pack includes samples and documentation on how to work with many of the native OS capabilities, including the Property System.
The following excerpts come from the PropertyEdit sample.
To get a file's property by name:
var myObject= ShellObject.FromParsingName(fileName);
IShellProperty prop = myObject.Properties.GetProperty(propertyName);
To set a string property:
if (prop.ValueType == typeof(string))
{
(prop as ShellProperty<string>).Value = value;
}
If you don't want to use the Property System, you can use NTFS alternate data streams to store additional info about a file. There is no direct support for ADS in .NET but a simple search returns multiple wrappers, libraries and SO questions about them, eg NTFS - Alternate Data Streams
Related
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}");
}
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
Suppose that I would like to add extra information about a file, without writing that information as content of that file. How would I do this? A couple of good examples are:
With Word documents, you can add Author tag to a document. And,
MP3 files have lots of info stored inside of them but when you play the file, you don't see that info (unless the program playing the file has been programmed to display that information).
How does Windows do this?
This information is stored in the file system (on windows - NTFS).
In NTFS, you can actually store another file, as part of this information, and it stores much more information about each file than you may expected.
NTFS file streams
Exapmle in C how to consume them
About MP3 and word - In these cases the information is stored inside the file, as part of its format.
How do I save my data...
(compressed/encrypted) not human readable in a portable file by
influencing on directory name and file name with using easily
addressable settings by "name" and "value" like in registry/ini
with the possibility to access the same one settings file (machine based)
with any executable
In VB I did that with INI Files, but now I have heard from MS that the Framework offers no function to access INI Files anymore. Since INI Files are also not any longer up-to-date for using them in a new application I wanted something similar. Just to write to a text file line by line is not what I want to do, I will explain why: If I will need a setting named "Label4" I have to read the entire file and search for the line containing it and then I have even to split the result in setting name and setting value (.NET has another syntax split function).
Let's say I have a thousand labels and a hundred textboxes in a form and wanna save its content easily to a file or whatever and read it the same easily back addressing the settings by a name already how would I do that? I am ready to use a DB but don't know how to setup and save information there. Easy would be to access the registry with "name" and "value", but I prefer a portable file.
The data shall be stored compressed or encrypted not in a plain text human readable way (I mean XML / html is not what I search for to store the data else I could research again how to use INI files with C# which might be possible I guess). I stumbled upon "application settings" but this doesn't save my data compressed nor can I simply influence on path and filename of the settings file. With each new EXE all the stored settings are lost again for those new EXE if I have used "application settings". I need not "user/application based" settings but "machine based", I hope you understand what I wanna say. Any App on my comp shall be able to get to my settings file
and I shall be able to choose the place/filename where to save the settings.
You should write to any xml file and get your desired results.
(compressed/encrypted) not human readable in a portable file
You can both encrypt/compress a normal file
influencing on directory name and file name with using easily
Can't understand what you mean
addressable settings by "name" and "value" like in registry/ini
xml gives you flexibility you need
with the possibility to access the same one settings file (machine based)
You can keep it machine based.
with any executable
What does it mean?
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).