How to Use DotNetZip to extract XML file from zip - c#

I'm using the latest version of DotNetZip, and I have a zip file with 5 XMLs on it. I want to open the zip, read the XML files and set a String with the value of the XML.
How can I do this?
Code:
//thats my old way of doing it.But I needed the path, now I want to read from the memory
string xfile = System.IO.File.ReadAllText(strNewFilePath, System.Text.Encoding.Default);
using (ZipFile zip = ZipFile.Read(this.uplZip.PostedFile.InputStream))
{
foreach (ZipEntry theEntry in zip)
{
//What should I use here, Extract ?
}
}
Thanks

ZipEntry has an Extract() overload which extracts to a stream. (1)
Mixing in this answer to How do you get a string from a MemoryStream?, you'd get something like this (completely untested):
string xfile = System.IO.File.ReadAllText(strNewFilePath, System.Text.Encoding.Default);
List<string> xmlContents;
using (ZipFile zip = ZipFile.Read(this.uplZip.PostedFile.InputStream))
{
foreach (ZipEntry theEntry in zip)
{
using (var ms = new MemoryStream())
{
theEntry.Extract(ms);
// The StreamReader will read from the current
// position of the MemoryStream which is currently
// set at the end of the string we just wrote to it.
// We need to set the position to 0 in order to read
// from the beginning.
ms.Position = 0;
var sr = new StreamReader(ms);
var myStr = sr.ReadToEnd();
xmlContents.Add(myStr);
}
}
}

Related

Reading file from SharePoint not returning correct value

I am using the below code to read a file from sharepoint 2019 and the return values are not string. Example of return values: 0\0\0(\u0001\0\0\u001e\0\0\0\0\0\0
using (ClientContext clientContext = new ClientContext("http://sharepoint2019/sites/test/"))
{
KeywordQuery keywordQuery = new KeywordQuery(clientContext);
keywordQuery.QueryText = "SharePoint";
keywordQuery.EnablePhonetic = true;
SearchExecutor searchExecutor = new SearchExecutor(clientContext);
ClientResult<ResultTableCollection> results = searchExecutor.ExecuteQuery(keywordQuery);
clientContext.ExecuteQuery();
foreach (var resultRow in results.Value[0].ResultRows)
{
Console.WriteLine("{0}: {1} ({2})", resultRow["Title"], resultRow["Path"], resultRow["Write"]);
File file= clientContext.Web.GetFileByUrl(resultRow["Path"].ToString());
var stream = file.OpenBinaryStream();
clientContext.Load(file);
clientContext.ExecuteQuery();
FileInformation fileInformation = File.OpenBinaryDirect(clientContext, (string)file.ServerRelativeUrl);
using (System.IO.StreamReader sr = new System.IO.StreamReader(fileInformation.Stream))
{
// Read the stream to a string, and write the string to the console.
String line = sr.ReadToEnd();
Console.WriteLine(line);
}
}
}
If you are reading some files like Word (not txt file), you will need use Open Xml library to read the string in Word, filestream can't return the real string as expected:
Get Plain Text of a Word Document using Open XML (CSOpenXmlGetPlainText)
Open a word processing document from a stream (Open XML SDK)

C# - How can I download a zip file from url, unzip it, and read the extracted files, all in memory? [duplicate]

I have files (from 3rd parties) that are being FTP'd to a directory on our server. I download them and process them even 'x' minutes. Works great.
Now, some of the files are .zip files. Which means I can't process them. I need to unzip them first.
FTP has no concept of zip/unzipping - so I'll need to grab the zip file, unzip it, then process it.
Looking at the MSDN zip api, there seems to be no way i can unzip to a memory stream?
So is the only way to do this...
Unzip to a file (what directory? need some -very- temp location ...)
Read the file contents
Delete file.
NOTE: The contents of the file are small - say 4k <-> 1000k.
Zip compression support is built in:
using System.IO;
using System.IO.Compression;
// ^^^ requires a reference to System.IO.Compression.dll
static class Program
{
const string path = ...
static void Main()
{
using(var file = File.OpenRead(path))
using(var zip = new ZipArchive(file, ZipArchiveMode.Read))
{
foreach(var entry in zip.Entries)
{
using(var stream = entry.Open())
{
// do whatever we want with stream
// ...
}
}
}
}
}
Normally you should avoid copying it into another stream - just use it "as is", however, if you absolutely need it in a MemoryStream, you could do:
using(var ms = new MemoryStream())
{
stream.CopyTo(ms);
ms.Position = 0; // rewind
// do something with ms
}
You can use ZipArchiveEntry.Open to get a stream.
This code assumes the zip archive has one text file.
using (FileStream fs = new FileStream(path, FileMode.Open))
using (ZipArchive zip = new ZipArchive(fs) )
{
var entry = zip.Entries.First();
using (StreamReader sr = new StreamReader(entry.Open()))
{
Console.WriteLine(sr.ReadToEnd());
}
}
using (ZipArchive archive = new ZipArchive(webResponse.GetResponseStream()))
{
foreach (ZipArchiveEntry entry in archive.Entries)
{
Stream s = entry.Open();
var sr = new StreamReader(s);
var myStr = sr.ReadToEnd();
}
}
Looks like here is what you need:
using (var za = ZipFile.OpenRead(path))
{
foreach (var entry in za.Entries)
{
using (var r = new StreamReader(entry.Open()))
{
//your code here
}
}
}
You can use SharpZipLib among a variety of other libraries to achieve this.
You can use the following code example to unzip to a MemoryStream, as shown on their wiki:
using ICSharpCode.SharpZipLib.Zip;
// Compresses the supplied memory stream, naming it as zipEntryName, into a zip,
// which is returned as a memory stream or a byte array.
//
public MemoryStream CreateToMemoryStream(MemoryStream memStreamIn, string zipEntryName) {
MemoryStream outputMemStream = new MemoryStream();
ZipOutputStream zipStream = new ZipOutputStream(outputMemStream);
zipStream.SetLevel(3); //0-9, 9 being the highest level of compression
ZipEntry newEntry = new ZipEntry(zipEntryName);
newEntry.DateTime = DateTime.Now;
zipStream.PutNextEntry(newEntry);
StreamUtils.Copy(memStreamIn, zipStream, new byte[4096]);
zipStream.CloseEntry();
zipStream.IsStreamOwner = false; // False stops the Close also Closing the underlying stream.
zipStream.Close(); // Must finish the ZipOutputStream before using outputMemStream.
outputMemStream.Position = 0;
return outputMemStream;
// Alternative outputs:
// ToArray is the cleaner and easiest to use correctly with the penalty of duplicating allocated memory.
byte[] byteArrayOut = outputMemStream.ToArray();
// GetBuffer returns a raw buffer raw and so you need to account for the true length yourself.
byte[] byteArrayOut = outputMemStream.GetBuffer();
long len = outputMemStream.Length;
}
Ok so combining all of the above, suppose you want to in a very simple way take a zip file called
"file.zip" and extract it to "C:\temp" folder. (Note: This example was only tested for compress text files) You may need to do some modifications for binary files.
using System.IO;
using System.IO.Compression;
static void Main(string[] args)
{
//Call it like this:
Unzip("file.zip",#"C:\temp");
}
static void Unzip(string sourceZip, string targetPath)
{
using (var z = ZipFile.OpenRead(sourceZip))
{
foreach (var entry in z.Entries)
{
using (var r = new StreamReader(entry.Open()))
{
string uncompressedFile = Path.Combine(targetPath, entry.Name);
File.WriteAllText(uncompressedFile,r.ReadToEnd());
}
}
}
}

Converting DotNetZip memory stream to string

I am trying to read a file within a zip to check if that file has a certain string in it. But I can seem to get the "file" (memory stream) into a string in order to search it.
When I use the following code "stringOfStream" is always blank, what am I doing wrong? The reader always has a length and read byte returns different numbers.
using (ZipFile zip = ZipFile.Read(currentFile.FullName))
{
ZipEntry e = zip[this.searchFile.Text];
using (MemoryStream reader = new MemoryStream())
{
e.Extract(reader);
var stringReader = new StreamReader(reader);
var stringOfStream = stringReader.ReadToEnd();
}
}
Thanks
I think when you call Extract the position of the stream goes to the end of the file, so you need to reposition again to get the data.
Can you try this please :
using (ZipFile zip = ZipFile.Read(currentFile.FullName))
{
ZipEntry e = zip[this.searchFile.Text];
using (MemoryStream reader = new MemoryStream())
{
e.Extract(reader);
reader.Position = 0;
var stringReader = new StreamReader(reader);
var stringOfStream = stringReader.ReadToEnd();
}
}
Check if it works or not.

How can I unzip a file to a .NET memory stream?

I have files (from 3rd parties) that are being FTP'd to a directory on our server. I download them and process them even 'x' minutes. Works great.
Now, some of the files are .zip files. Which means I can't process them. I need to unzip them first.
FTP has no concept of zip/unzipping - so I'll need to grab the zip file, unzip it, then process it.
Looking at the MSDN zip api, there seems to be no way i can unzip to a memory stream?
So is the only way to do this...
Unzip to a file (what directory? need some -very- temp location ...)
Read the file contents
Delete file.
NOTE: The contents of the file are small - say 4k <-> 1000k.
Zip compression support is built in:
using System.IO;
using System.IO.Compression;
// ^^^ requires a reference to System.IO.Compression.dll
static class Program
{
const string path = ...
static void Main()
{
using(var file = File.OpenRead(path))
using(var zip = new ZipArchive(file, ZipArchiveMode.Read))
{
foreach(var entry in zip.Entries)
{
using(var stream = entry.Open())
{
// do whatever we want with stream
// ...
}
}
}
}
}
Normally you should avoid copying it into another stream - just use it "as is", however, if you absolutely need it in a MemoryStream, you could do:
using(var ms = new MemoryStream())
{
stream.CopyTo(ms);
ms.Position = 0; // rewind
// do something with ms
}
You can use ZipArchiveEntry.Open to get a stream.
This code assumes the zip archive has one text file.
using (FileStream fs = new FileStream(path, FileMode.Open))
using (ZipArchive zip = new ZipArchive(fs) )
{
var entry = zip.Entries.First();
using (StreamReader sr = new StreamReader(entry.Open()))
{
Console.WriteLine(sr.ReadToEnd());
}
}
using (ZipArchive archive = new ZipArchive(webResponse.GetResponseStream()))
{
foreach (ZipArchiveEntry entry in archive.Entries)
{
Stream s = entry.Open();
var sr = new StreamReader(s);
var myStr = sr.ReadToEnd();
}
}
Looks like here is what you need:
using (var za = ZipFile.OpenRead(path))
{
foreach (var entry in za.Entries)
{
using (var r = new StreamReader(entry.Open()))
{
//your code here
}
}
}
You can use SharpZipLib among a variety of other libraries to achieve this.
You can use the following code example to unzip to a MemoryStream, as shown on their wiki:
using ICSharpCode.SharpZipLib.Zip;
// Compresses the supplied memory stream, naming it as zipEntryName, into a zip,
// which is returned as a memory stream or a byte array.
//
public MemoryStream CreateToMemoryStream(MemoryStream memStreamIn, string zipEntryName) {
MemoryStream outputMemStream = new MemoryStream();
ZipOutputStream zipStream = new ZipOutputStream(outputMemStream);
zipStream.SetLevel(3); //0-9, 9 being the highest level of compression
ZipEntry newEntry = new ZipEntry(zipEntryName);
newEntry.DateTime = DateTime.Now;
zipStream.PutNextEntry(newEntry);
StreamUtils.Copy(memStreamIn, zipStream, new byte[4096]);
zipStream.CloseEntry();
zipStream.IsStreamOwner = false; // False stops the Close also Closing the underlying stream.
zipStream.Close(); // Must finish the ZipOutputStream before using outputMemStream.
outputMemStream.Position = 0;
return outputMemStream;
// Alternative outputs:
// ToArray is the cleaner and easiest to use correctly with the penalty of duplicating allocated memory.
byte[] byteArrayOut = outputMemStream.ToArray();
// GetBuffer returns a raw buffer raw and so you need to account for the true length yourself.
byte[] byteArrayOut = outputMemStream.GetBuffer();
long len = outputMemStream.Length;
}
Ok so combining all of the above, suppose you want to in a very simple way take a zip file called
"file.zip" and extract it to "C:\temp" folder. (Note: This example was only tested for compress text files) You may need to do some modifications for binary files.
using System.IO;
using System.IO.Compression;
static void Main(string[] args)
{
//Call it like this:
Unzip("file.zip",#"C:\temp");
}
static void Unzip(string sourceZip, string targetPath)
{
using (var z = ZipFile.OpenRead(sourceZip))
{
foreach (var entry in z.Entries)
{
using (var r = new StreamReader(entry.Open()))
{
string uncompressedFile = Path.Combine(targetPath, entry.Name);
File.WriteAllText(uncompressedFile,r.ReadToEnd());
}
}
}
}

ResXResourceWriter not writing to stream?

I'm trying to create a resx file and write it to a stream so that I might return it as a string instead of immediately saving it to a file. However, when I try to read that stream, it is empty. What am I doing wrong here? i did verify that the entries are not null. I can actually use the ResXResourceWriter constructor that saves it to disk successfully, but I'm trying to avoid using temp files. Also, I can see the stream is 0k before the loop and about 8k in length after the loop.
using (var stream = new MemoryStream())
{
using (var resx = new ResXResourceWriter(stream))
{
// build the resx and write to memory
foreach (var entry in InputFile.Entries.Values)
{
resx.AddResource(new ResXDataNode(entry.Key, entry.Value) { Comment = entry.Comment });
}
var reader = new StreamReader(stream);
var text = reader.ReadToEnd(); // text is an empty string here!
return null;
}
}
You need to flush and reset the output/stream before trying to read it. This should work, using Generate and Position:
resx.Generate();
stream.Position = 0;
var reader = new StreamReader(stream);
var text = reader.ReadToEnd();
return text;

Categories

Resources