How to create a basic package to store images? - c#

How can I create a basic package to store images, like a zip file?
All I want to do is to store 20000 images inside one package. It will be easier for my hard disk.
Also, I need to be able to enter and exit from that package, read/write , add/remove files, using C# code.
Another file format is .iso that is close to what I want, but is complicated to operate with.
I want something very basic, not complicated. Basic as a library if possible.
Is there such a thing?

If you decide to go with the virtual hard disk the steps are the following:
In Computer management right click Disk management and in the local menu click 'Create VHD'. Create a virtual hard disk with the parameters you prefer. I recommend the .vhdx and dynamically expanding flavor. After this you have a mounted, un-initialized, un formatted hard drive.
Prepare it with the necessary and usual steps. As the result you will have a hard drive with an assigned drive letter.
Use it as any hard drive you have.
After reboot it will not be automatically mounted, you have to do it manually in Disk Management or use a scheduled task to mount the drive. Here's the script for that: https://gallery.technet.microsoft.com/scriptcenter/How-to-automatically-mount-d623ce34
You can unmount it at Disk Management as well.
You can copy the file yourdiskname.vhd(x) to other computers and use it.

Thank you all for your input
It helped me decide and it direction me to this answer I find after many web search battles.
I find a practical solution, but not that efficient as I want it.
Is moving slow-ish when cycling the images from inside a zip file, because it is unpacking each of them. I must re-think the code and unzip all into a stream or some lists. I will see. For now, is working and I am very happy :)
Here is the result I came up with:
//My code so far - not very efficient but is working.
using Ionic.Zip;
using Ionic.Zlib;
string zipPath = "0Images.zip";
void CountZipFiles()
{
using (ZipFile zip = new ZipFile(zipPath))
{
totalzipFiles = zip.Count-1;
}
}
Image emptyImage = Image.FromFile("emptyFemale.jpg");
void ReadZipImage()
{
using (ZipFile zip = new ZipFile(zipPath))
{
MemoryStream tempS = new MemoryStream();
for (int i = 0; i < zip.Count; i++)
{
if (i == countMyZipImages)
{
label1.Text = zip[i].FileName;
if (zip[i].FileName.Contains(".niet"))
{
pictureBox1.Image = emptyImage;
}
else
{
zip[i].Extract(tempS);
pictureBox1.Image = Image.FromStream(tempS);
}
}
}
}
}
int totalzipFiles = 0, countMyZipImages = 0;
private void button2_Click(object sender, EventArgs e)
{
countMyZipImages--;
if (countMyZipImages < 0) countMyZipImages = totalzipFiles;
textBox1.Text = countMyZipImages.ToString();
ReadZipImage();
}
private void button3_Click(object sender, EventArgs e)
{
countMyZipImages++;
if (countMyZipImages > totalzipFiles) countMyZipImages = 0;
textBox1.Text = countMyZipImages.ToString();
ReadZipImage();
}
// and this is a HELP file for later use - hopefully will help others too. ;)
How to add Ionic.Zip.dll in c#.net project and use it:
To add a reference, right click (in Solution Explorer on your project) Reference folder and select Add Reference.
Then browse and add the file Ionic.Zip.dll
//Important to add this using's too after referencing.
using Ionic.Zip;
using Ionic.Zlib;
private void CreateZIP_Click(object sender, EventArgs e)
{
using (ZipFile zip = new ZipFile())
{
// add this map file into the "images" directory in the zip archive
zip.AddFile("c:\\images\\personal\\7440-N49th.png", "images");
// add the report into a different directory named "files" in the archive
zip.AddFile("c:\\Reports\\2008-Regional-Sales-Report.pdf", "files");
zip.AddFile("ReadMe.txt");
zip.Save("MyZipFile.zip");
Exception ex = new Exception();
label1.Text = ex.Message;
}
}
//You can extract to a stream, or a fizical file !
private void button5_Click(object sender, EventArgs e)
{
using (ZipFile zip = new ZipFile("0Images.zip"))
{
MemoryStream tempS = new MemoryStream(); //stream
//{
foreach (ZipEntry ze in zip) //foreach
{
// check if you want to extract the image.name
if (ze.FileName == "00002 Riley Reid.jpg")
{
ze.Extract(tempS);
pictureBox1.Image = Image.FromStream(tempS);
}
}
//OR
for (int i = 0; i < zip.Count; i++) //for
{
if (i == countMyZipImages)
{
zip[i].Extract(tempS);
pictureBox1.Image = Image.FromStream(tempS);
}
}
//}
}
}
This is a free library I find on internet! I like it because is very little - 435kb. Here is a link I find for others if they want to use it. Dropbox - Ionic.Zip.dll[^]

Related

FileSystemWatcher: System.IO.IOException ("File used by another process")

Currently i'm working on an application, that should watch a specific directory for changes (say a new file was created) and then in turn upload the file to Sharepoint. Thatfore i'm using the FileSystemWatcher class which throws an event with the path to the created file, which in turn i use in another method to upload the file. The problem is: While in debug mode in Visual Studio i realized that the first file i create in the watched directory gets uploaded perfectly, even if i drag multiple files into the directory at once all are uploaded, BUT when i do it one file after another i get an exception that the second file is already in use. So i drag File1.txt into the directory, it works, but then, when i drag file2.txt into the directory right after i get a System.IO.IOException while trying to create a filestream to upload to Sharepoint telling me that file2.txt is in use by another process.
The code for the FileSystemWatcher:
public void StartWatcher()
{
FileSystemWatcher fsw = new FileSystemWatcher(this.path);
fsw.IncludeSubdirectories = true;
fsw.EnableRaisingEvents = true;
fsw.Created += new FileSystemEventHandler(CreateFile);
try
{
while (true)
{
fsw.WaitForChanged(WatcherChangeTypes.All);
}
}
catch
{ }
fsw.EnableRaisingEvents = false;
}
The CreateFile() method called by
fsw.Created += new FileSystemEventHandler(CreateFile);
looks like this:
private void CreateFile(object sender, FileSystemEventArgs e)
{
path = String.Format(e.FullPath);
filename = Path.GetFileName(path);
Stream fs = File.OpenRead(#path);
SPAPI spobj = new SPAPI();
spobj.SPUploader(fs, filename);
fs.Close();
}
The exception is thrown at
Stream fs = File.OpenRead(#path);
BUT only when a second file is dragged into the directory after the first one. The strange thing is that not the first file is in use, but the second one that i want to open as a stream. So it's not the stream that is still open and causing the exception. It seems that the second file is in use by the FileSystemWatcher. But why does the first file work just fine but the exception is just thrown when a second file is dragged into the directory?
You can modify and use like this. I hope this helps you
private void CreateFile(object sender, FileSystemEventArgs e)
{
int until = 5;
int i = 0;
bool success = false;
while (!success && i < until)
{
try
{
path = String.Format(e.FullPath);
filename = Path.GetFileName(path);
using (Stream fs = File.OpenRead(#path);)
{
SPAPI spobj = new SPAPI();
spobj.SPUploader(fs, filename);
}
success = true;
}
catch
{
i++;
Thread.Sleep(TimeSpan.FromSeconds(1));
}
}
}

c# Novacode.Picture to System.Drawing.Image

I'm reading in a .docx file using the Novacode API, and am unable to create or display any images within the file to a WinForm app due to not being able to convert from a Novacode Picture (pic) or Image to a system image. I've noticed that there's very little info inside the pic itself, with no way to get any pixel data that I can see. So I have been unable to utilize any of the usual conversion ideas.
I've also looked up how Word saves images inside the files as well as Novacode source for any hints and I've come up with nothing.
My question then is is there a way to convert a Novacode Picture to a system one, or should I use something different to gather the image data like OpenXML? If so, would Novacode and OpenXML conflict in any way?
There's also this answer that might be another place to start.
Any help is much appreciated.
Okay. This is what I ended up doing. Thanks to gattsbr for the advice. This only works if you can grab all the images in order, and have descending names for all the images.
using System.IO.Compression; // Had to add an assembly for this
using Novacode;
// Have to specify to remove ambiguous error from Novacode
Dictionary<string, System.Drawing.Image> images = new Dictionary<string, System.Drawing.Image>();
void LoadTree()
{
// In case of previous exception
if(File.Exists("Images.zip")) { File.Delete("Images.zip"); }
// Allow the file to be open while parsing
using(FileStream stream = File.Open("Images.docx", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using(DocX doc = DocX.Load(stream))
{
// Work rest of document
// Still parse here to get the names of the images
// Might have to drag and drop images into the file, rather than insert through Word
foreach(Picture pic in doc.Pictures)
{
string name = pic.Description;
if(null == name) { continue; }
name = name.Substring(name.LastIndexOf("\\") + 1);
name = name.Substring(0, name.Length - 4);
images[name] = null;
}
// Save while still open
doc.SaveAs("Images.zip");
}
}
// Use temp zip directory to extract images
using(ZipArchive zip = ZipFile.OpenRead("Images.zip"))
{
// Gather all image names, in order
// They're retrieved from the bottom up, so reverse
string[] keys = images.Keys.OrderByDescending(o => o).Reverse().ToArray();
for(int i = 1; ; i++)
{
// Also had to add an assembly for ZipArchiveEntry
ZipArchiveEntry entry = zip.GetEntry(String.Format("word/media/image{0}.png", i));
if(null == entry) { break; }
Stream stream = entry.Open();
images[keys[i - 1]] = new Bitmap(stream);
}
}
// Remove temp directory
File.Delete("Images.zip");
}

How to run the installer from an iso file using c# code

I have created an iso image with the installation folder of an application. I want to intialize the execution of the application form a .net code. I have been using the following code to open the image as a drive given that file explorer is the default application for opening iso files, then read the drives to check if there exists the file i want to run.
System.Diagnostics.Process.Start("C:\Users\tjdtud\Desktop\done\publish.iso");
private void button1_Click(object sender, EventArgs e)
{
DriveInfo[] diLocalDrives = DriveInfo.GetDrives();
try
{
foreach (DriveInfo diLogicalDrive in diLocalDrives)
{
if (File.Exists(diLogicalDrive.Name + "setup.exe"))
{
MessageBox.Show(diLogicalDrive.Name + "setup.exe");
System.Diagnostics.Process.Start(diLogicalDrive.Name + "\\setup.exe");
//MessageBox.Show("Logical Drive: " + diLogicalDrive.Name,
// "Logical Drives",
// MessageBoxButtons.OK,
// MessageBoxIcon.Information);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
This code failes to work if file explorer is not the default iso opening application. Besides i have a strong feeling that it is not even close to the right way of doing it. Will very much appreciate any form of help or pointers to help links. Thank you for reading
You can use .NET DiscUtils to extract the file as follows:
using (FileStream isoStream = File.Open(#"C:\temp\sample.iso"))
{
CDReader cd = new CDReader(isoStream, true);
Stream fileStream = cd.OpenFile(#"Folder\Hello.txt", FileMode.Open);
// Use fileStream...
}
Extract the file to a temporary location and then execute it.

How can I write to a specific location in Windows Phone 8

When I press a button, I want it to overwrite a file to a specific folder.
I use this code:
private void btnArial_Click(object sender, RoutedEventArgs e)
{
string cssDocument = "body{font-family:\"Arial\";}";
//I want to write file style.css to folder css inside html
string path = Package.Current.InstalledLocation.Path + "\\Html\\css\\style.css";
if (File.Exists(path))
{
StreamWriter writer = new StreamWriter(path);
writer.Write(cssDocument);
writer.Close();
}
changeStyle(new FontFamily("Arial"));
}
When I tested on emulator and actual devide, it worked properly.
But when I submit app to store, it got error - the app exits when I press that button.
The install directory (Package.Current.InstalledLocation) is a read-only location. Unfortunately, due to the way that Visual Studio optimizes development-time deployment, it is set to read-write when the app is deployed from VS. That's why you see a difference in behavior after you submit the app to the store.
If you need to modify a file in your install directory, you must first copy it over to a writeable location - eg. your Local folder.
I prefer using Isolated storage in WP8 to write files and it never fails. Also you can use Windows.Storage apis.
private async void MyButton_Click(object sender, RoutedEventArgs e)
{
string cssDocument = "body{font-family:\"Arial\";}";
// using Windows.Storage
StorageFolder folder = ApplicationData.Current.LocalFolder;
folder = await folder.CreateFolderAsync("HTML", CreationCollisionOption.OpenIfExists);
folder = await folder.CreateFolderAsync("CSS", CreationCollisionOption.OpenIfExists);
StorageFile file = await folder.CreateFileAsync("style.css", CreationCollisionOption.ReplaceExisting);
using (var writer = new StreamWriter(await file.OpenStreamForWriteAsync()))
{
writer.Write(cssDocument);
}
// using using System.IO.IsolatedStorage;
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
if (!store.DirectoryExists("HTML/CSS"))
store.CreateDirectory("HTML/CSS");
using (var writer = new StreamWriter(store.OpenFile("HTML/CSS/style.css", FileMode.Create)))
{
writer.Write(cssDocument);
}
}
changeStyle(new FontFamily("Arial"));
}
Exactly..
Write the file in Isolated storage. Its easier and pretty straight forward. The files here can be accessed, viewed, modified, removed, replaced in a very clear way. I personally prefer the Isolated Storage.

save file without using save file dialog

I am working on this project still and I am running into a problem. Well here is what I need to do.
When the user clicks the “Save” button, write the selected record to
the file specified in txtFilePath (absolute path not relative) without
truncating the values currently inside and handle any exceptions that arise.
Ok here is my code:
private void Save_Click(object sender, EventArgs e)
{
string filePath = txtFilePath.Text;
if (!File.Exists(filePath))
{
FileStream fs = File.Create(filePath);
fs.Close();
}
using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
{
using (StreamWriter sw = new StreamWriter(fs))
{
foreach (string line in employeeList.Items)
{
sw.WriteLine(line);
}
}
}
}
Now when I go onto my program and want to save something from the employeelist.text that its not being saved to the place I am saving it at. I don;t know if I am missing something in my code or what but it will not save. Here is an example:
I add a person name to this list in employeelist and in the textbox I
have a file called C:\employess\employeelist.txt I want to save it to.
I click the save button then I go to that employeelist and it is not
being saved.
I don't know what I am doing wrong I have been looking online for a solution but I haven't found anything yet. Thanks
Some things to double-check:
Make sure you don't have the employeelist.txt file open when you're testing
Make sure you don't have invalid characters in your file name
Make sure your application has permission to save the file to the location you specified
Use the debugger to step-through your code and look for swallowed exceptions -- there must be a reason the file is not created.
Check that your Save_Click event is wired up to your button -- is the code in your example even running?
Once you check those things, you may want to follow this example for the create vs. append requirement of your project:
string path = txtFilePath.Text;
// This text is added only once to the file.
if (!File.Exists(path))
{
using (StreamWriter sw = File.CreateText(path))
{
foreach (var line in employeeList.Items)
sw.WriteLine(line.ToString());
}
}
else
{
using (StreamWriter sw = File.AppendText(path))
{
foreach (var line in employeeList.Items)
sw.WriteLine(line.ToString());
}
}
This will create the file if it doesn't exist, or append to it if it does.
Checking that the file exists and then creating it is a bit unnecessary as this can all be handled by the StreamWriter/FileStream parts. So your above function can be simplified into the following:
public void Save_Click(object sender, EventArgs e)
{
StreamWriter file =
new StreamWriter(txtFilePath.Text, true);//Open and append
foreach (object item in employeeList.Items) {
file.WriteLine(item.toString());
}
file.Close();
}
[Updated]
What are the types of txtFilePath and employeeList the former suggests it's a text box, the later suggests it's bound to a non-GUI element perhaps? (WAG)
You might also want to append a blank line at the end so that on further saves you can tell it was an append rather than one long list (depending on your needs of course)
Starting with .Net Framework 4 you can do it like this:
private void Save_Click(object sender, EventArgs e)
{
File.AppendAllLines(txtFilePath.Text, employeeList.Items);
}
Of course, you probably would want to add a check to have a valid path and a valid enumeration of strings.
If the path looks like a relative one (i.e. doesn't begin with a drive letter), then it will be interpreted that way.
If you put a full path in the text box, does the file get saved in the proper place? If so, perhaps this is what was intended.
If the user doesn't put in a full path, do you have a way to make it one (for example, just sticking C:\ at the beginning)? Or at least can you tell when there isn't a full path, and reject the request?

Categories