Getting "Operation not permitted on IsolatedStorageFileStream." Error - c#

"Operation not permitted on IsolatedStorageFileStream." is pointing towards the line of codes:
var fileStream = storage.OpenFile(item.FileName, FileMode.Open, FileAccess.Read)
in the codes below:
private void OnReadSelected()
{
IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication();
List<FileItem> readItems = new List<FileItem>();
foreach (var item in Files)
{
if (item.IsChecked)
if (storage.FileExists(item.FileName))
{
storage.DeleteFile(item.FileName);
readItems.Add(item);
}
}
foreach (var item in readItems)
using (var fileStream = storage.OpenFile(item.FileName, FileMode.Open, FileAccess.Read))
{
using (var reader = new StreamReader(fileStream))
{
item.FileName = reader.ReadLine();
item.FileText1 = reader.ReadLine();
item.RdbText1 = reader.ReadLine();
}
}
}
Am I to use another derivative besides StreamReader?

foreach (var item in Files)
{
if (item.IsChecked)
if (storage.FileExists(item.FileName))
{
storage.DeleteFile(item.FileName);
readItems.Add(item);
}
}
You have used this code to delete some files from the store depending upon the condition if(item.IsChecked). And you are adding those items to the readItems collection.
But in this code
foreach (var item in readItems)
using (var fileStream = storage.OpenFile(item.FileName, FileMode.Open, FileAccess.Read))
{
using (var reader = new StreamReader(fileStream))
{
item.FileName = reader.ReadLine();
item.FileText1 = reader.ReadLine();
item.RdbText1 = reader.ReadLine();
}
}
you are trying to open the files which you have just deleted from the store.
So, you are getting the exception Operation not permitted on IsolatedStorageFileStream as the files doesn't exist in the store.

Related

How can I put a txt file (that is in a zip file) in a string, without extracting the zip?

Here is my code:
using (ZipArchive zip = ZipFile.Open(path, ZipArchiveMode.Read))
foreach (ZipArchiveEntry entry in zip.Entries)
if (entry.Name == "example.txt")
entry.ExtractToFile(???);
The ??? is what I'm having trouble with. I want it to go to a string, not a file on disk.
The first code will get you an Array of String, as if it were "ReadAllLines". The second one will get you a single String (as if it were "ReadAllText").
List<string> lines = new List<string>();
using (ZipArchive archive = ZipFile.OpenRead(zipPath))
{
foreach (ZipArchiveEntry entry in archive.Entries.Where(e_ => e_.Name == "example.txt"))
{
Stream stream = entry.Open();
using (var sr = new StreamReader(stream, Encoding.UTF8))
{
string line;
while ((line = sr.ReadLine()) != null)
{
lines.Add(line);
}
}
}
}
string[] result = lines.ToArray();
string result = "";
using (ZipArchive archive = ZipFile.OpenRead(zipPath))
{
foreach (ZipArchiveEntry entry in archive.Entries.Where(e_ => e_.Name == "example.txt"))
{
Stream stream = entry.Open();
using (var sr = new StreamReader(stream, Encoding.UTF8))
{
result = sr.ReadToEnd();
}
}
}

Moving file directly into zip file

I'm trying move Source_File.mp4 into Destination_Zip.zip directly. I'm currently trying it by creating a new entry Transfer.mp4 and copying the bytes over. The code runs to the end but the file is never added to the ZIP file. I'm not sure if I'm missing something or if this isn't possible.
string sourceFile = basePath + "Source_File.mp4";
string destinationZip = basePath + "Desintation_Zip.zip";
using (var file = File.OpenRead(destinationZip))
{
MemoryStream memoryStream = new MemoryStream();
memoryStream.SetLength(file.Length);
file.Read(memoryStream.GetBuffer(), 0, (int)file.Length);
using (var zip = new ZipArchive(memoryStream, ZipArchiveMode.Update))
{
var entry = zip.CreateEntry("Transfer.mp4");
using (var destinationStream = entry.Open())
using (var sourceStream = File.OpenRead(sourceFile))
{
sourceStream.CopyTo(destinationStream);
}
}
}
My guess is that even though you've read the file and altered it, you didn't write anything back, i.e. changes persisted to MemoryStream, and didn't go anywhere after that.
You could try this (assumes you're using System.IO.Compression.ZipFile):
using (var zip = ZipFile.Open(destinationZip, ZipArchiveMode.Update))
{
var entry = zip.CreateEntry("Transfer.mp4");
using (var destinationStream = entry.Open())
using (var sourceStream = File.OpenRead(sourceFile))
{
sourceStream.CopyTo(destinationStream);
}
}
Or, if you're using ICSharpCode.SharpZipLib.Zip.ZipFile, do this:
using (var fileStream = new FileStream(destinationZip, FileMode.Open))
using (var zip = new ZipArchive(fileStream, ZipArchiveMode.Update))
{
var entry = zip.CreateEntry("Transfer.mp4");
using (var destinationStream = entry.Open())
using (var sourceStream = File.OpenRead(sourceFile))
{
sourceStream.CopyTo(destinationStream);
}
}
I'm still not sure why my initial code did not work, but I got it working by doing this instead:
string sourceFile = basePath + "Source_File.mp4";
string destinationZip = basePath + "Desintation_Zip.zip";
using (var destinationZipFileStream = new FileStream(destinationZip, FileMode.Open))
using (var destinationZipArchive = new ZipArchive(destinationZipFileStream, ZipArchiveMode.Update))
{
ZipArchiveEntry destinationWriter = destinationZipArchive.CreateEntry("Transfer.mp4");
using (var writer = new StreamWriter(destinationWriter.Open()))
using (var sourceStream = File.OpenRead(sourceFile))
{
sourceStream.CopyTo(writer.BaseStream);
}
}
Note: you will need to double check to make sure the file doesn't exist already or else you'll make duplicate files this way.

Update an existing ooxml file with C# and System.IO.Compression.ZipArchive

I am trying to update an nearly empty docx/ooxml file. I dont get an exception, the code is running through but the file is not modified.
I think I am missing something :/
The code below is not the actual code, but a simplified example. It is also running without an exception but the file is not updated.
using (var fs = new FileStream(docxFile, FileMode.Open))
{
var archive = new ZipArchive(fs, ZipArchiveMode.Update);
foreach (var entry in archive.Entries)
{
if (entry.Name == "[Content_Types].xml")
{
using (var entryStream = entry.Open())
{
var doc = new XmlDocument();
doc.Load(entryStream);
var element = doc.CreateElement("Override");
element.SetAttribute("PartName", "/docProps/example.xml");
doc.DocumentElement.AppendChild(element);
doc.Save(entryStream);
entryStream.Flush();
}
break;
}
}
}
Seems like it was late yesterday :(
Either use using with the ZipArchive instance or calling Dispose after the loop will do the job ;)
using (var fs = new FileStream(docxFile, FileMode.Open))
{
using (var archive = new ZipArchive(fs, ZipArchiveMode.Update))
{
foreach (var entry in archive.Entries)
{
if (entry.Name == "[Content_Types].xml")
{
using (var entryStream = entry.Open())
{
var doc = new XmlDocument();
doc.Load(entryStream);
var element = doc.CreateElement("Override");
element.SetAttribute("PartName", "/docProps/example.xml");
doc.DocumentElement.AppendChild(element);
doc.Save(entryStream);
entryStream.Flush();
}
break;
}
}
}
}

Re-create zip file from another zip file

Given a zip file, I need to re-create it with a specified compression level (eg, no compression).
I'm nearly there, but get the error:
Failed: Number of entries expected in End Of Central Directory does not correspond to number of entries in Central Directory.
If I save the recreated zip file to windows, it looks like it's correct (correct file size, entries all exist with correct file sizes) but none of the files are extractable.
public static byte[] ReCompress(byte[] originalArchive, CompressionLevel newCompressionLevel)
{
var entries = new Dictionary<string, byte[]>();
///////////////////////////
// STEP 1: EXTRACT ALL FILES
///////////////////////////
using (var ms = new MemoryStream(originalArchive))
using (var originalZip = new ZipArchive(ms, ZipArchiveMode.Read))
{
foreach (var entry in originalZip.Entries)
{
var isFolder = entry.FullName.EndsWith("/");
if (!isFolder)
{
using (var stream = entry.Open())
using (var entryMS = new MemoryStream())
{
stream.CopyTo(entryMS);
entries.Add(entry.FullName, entryMS.ToArray());
}
}
else
{
entries.Add(entry.FullName, new byte[0]);
}
}
}
///////////////////////////
// STEP 2: BUILD ZIP FILE
///////////////////////////
using (var ms = new MemoryStream())
using (var newArchive = new ZipArchive(ms, ZipArchiveMode.Create, true))
{
foreach (var uncompressedEntry in entries)
{
var newEntry = newArchive.CreateEntry(uncompressedEntry.Key, newCompressionLevel);
using (var entryStream = newEntry.Open())
using (var writer = new BinaryWriter(entryStream, Encoding.UTF8))
{
writer.Write(uncompressedEntry.Value);
}
}
return ms.ToArray();
}
}
At the end of the function if I do:
File.WriteAllBytes(#"D:\test.zip", ms.ToArray());
It creates a correctly structure archive sized 90mb but no files are extractable.
If I end with return ms.ToArray() it returns a ~130kb byte array.
Zip archive is broken because you read its content from MemoryStream before it is finished. In order to finish archive creation you need to call newArchive.Dispose() before calling ms.ToArray().
In this particular case you can do it like this:
using (var ms = new MemoryStream())
{
using (var newArchive = new ZipArchive(ms, ZipArchiveMode.Create, true))
{
foreach (var uncompressedEntry in entries)
{
var newEntry = newArchive.CreateEntry(uncompressedEntry.Key, newCompressionLevel);
using (var entryStream = newEntry.Open())
using (var writer = new BinaryWriter(entryStream, Encoding.UTF8))
{
writer.Write(uncompressedEntry.Value);
}
}
}
return ms.ToArray();
}

C# Create ZIP Archive with multiple files

I'm trying to create a ZIP archive with multiple text files as follows:
Dictionary<string, string> Values = new Dictionary<string, string>();
using (var memoryStream = new MemoryStream())
{
string zip = #"C:\Temp\ZipFile.zip";
foreach (var item in Values)
{
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
var file = archive.CreateEntry(item.Key + ".txt");
using (var entryStream = file.Open())
using (var streamWriter = new StreamWriter(entryStream))
{
streamWriter.Write(item.Value);
}
}
}
using (var fileStream = new FileStream(zip, FileMode.Create))
{
memoryStream.Seek(0, SeekOrigin.Begin);
memoryStream.CopyTo(fileStream);
}
}
However, the ZIP is created with only the last text file, what's wrong?
You are creating ZipArchive on each iteration. Swapping foreach and using should solve it:
Dictionary<string, string> Values = new Dictionary<string, string>();
using (var memoryStream = new MemoryStream())
{
string zip = #"C:\Temp\ZipFile.zip";
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
foreach (var item in Values)
{
var file = archive.CreateEntry(item.Key + ".txt");
using (var entryStream = file.Open())
using (var streamWriter = new StreamWriter(entryStream))
{
streamWriter.Write(item.Value);
}
}
}
using (var fileStream = new FileStream(zip, FileMode.Create))
{
memoryStream.Seek(0, SeekOrigin.Begin);
memoryStream.CopyTo(fileStream);
}
}
Each time your foreach loop runs it has the ZipArchiveMode as Create. That should be the problem, so it generates new zip everytime with new content on it, such as the last text file. Create an exception for each loop run after the first one it should be solved.

Categories