Here is my problem, i'm trying to make minecraft classic server and i'm using text system to make allow list for each map, problem is text system makes a file for each map and we got around 15k maps in total, so if 1k of players add allow list to their maps, it would be hard to upload / move server to another host. i want to make a zip file in main folder of my software and add each text file to it and also making it readable with system, i want to know how to read a file from GZip, and how to compress files also.
Thanks
Here is my very easy working code. No temporary file
using (FileStream reader = File.OpenRead(filePath))
using (GZipStream zip = new GZipStream(reader, CompressionMode.Decompress, true))
using (StreamReader unzip = new StreamReader(zip))
while(!unzip.EndOfStream)
ReadLine(unzip.ReadLine());
If you want to avoid creating temporary files, you can use this:
using (Stream fileStream = File.OpenRead(filePath),
zippedStream = new GZipStream(fileStream, CompressionMode.Decompress))
{
using (StreamReader reader = new StreamReader(zippedStream))
{
// work with reader
}
}
Details on how to use GZip to compress and decompress. After decompression, you can use the StreamReader() class to read the contents of the file (.NET 4.0).
using System;
using System.IO;
using System.IO.Compression;
namespace zip
{
public class Program
{
public static void Main()
{
string directoryPath = #"c:\users\public\reports";
DirectoryInfo directorySelected = new DirectoryInfo(directoryPath);
foreach (FileInfo fileToCompress in directorySelected.GetFiles())
{
Compress(fileToCompress);
}
foreach (FileInfo fileToDecompress in directorySelected.GetFiles("*.gz"))
{
Decompress(fileToDecompress);
}
}
public static void Compress(FileInfo fileToCompress)
{
using (FileStream originalFileStream = fileToCompress.OpenRead())
{
if ((File.GetAttributes(fileToCompress.FullName) & FileAttributes.Hidden) != FileAttributes.Hidden & fileToCompress.Extension != ".gz")
{
using (FileStream compressedFileStream = File.Create(fileToCompress.FullName + ".gz"))
{
using (GZipStream compressionStream = new GZipStream(compressedFileStream, CompressionMode.Compress))
{
originalFileStream.CopyTo(compressionStream);
Console.WriteLine("Compressed {0} from {1} to {2} bytes.",
fileToCompress.Name, fileToCompress.Length.ToString(), compressedFileStream.Length.ToString());
}
}
}
}
}
public static void Decompress(FileInfo fileToDecompress)
{
using (FileStream originalFileStream = fileToDecompress.OpenRead())
{
string currentFileName = fileToDecompress.FullName;
string newFileName = currentFileName.Remove(currentFileName.Length - fileToDecompress.Extension.Length);
using (FileStream decompressedFileStream = File.Create(newFileName))
{
using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
{
decompressionStream.CopyTo(decompressedFileStream);
Console.WriteLine("Decompressed: {0}", fileToDecompress.Name);
}
}
}
}
}
}
Source
Related
What I'm looking for is zip/compress S3 files without having them first downloaded to EFS or on a file system and then upload the zip file back to S3. Is there a C# way to achieve the same? I found the following post, but not sure its C# equivalent
https://www.antstack.io/blog/create-zip-using-lambda-with-files-streamed-from-s3/
I've written following code to zip files from a MemoryStream
public static void CreateZip(string zipFileName, List<FileInfo> filesToZip)
{
//zipFileName is the final zip file name
LambdaLogger.Log($"Zipping in progress for: {zipFileName}");
using (MemoryStream zipMS = new MemoryStream())
{
using (ZipArchive zipArchive = new ZipArchive(zipMS, ZipArchiveMode.Create, true))
{
//loop through files to add
foreach (var fileToZip in filesToZip)
{
//read the file bytes
byte[] fileToZipBytes = File.ReadAllBytes(fileToZip.FullName);
ZipArchiveEntry zipFileEntry = zipArchive.CreateEntry(fileToZip.Name);
//add the file contents
using (Stream zipEntryStream = zipFileEntry.Open())
using (BinaryWriter zipFileBinary = new BinaryWriter(zipEntryStream))
{
zipFileBinary.Write(fileToZipBytes);
}
}
}
using (FileStream finalZipFileStream = new FileStream(zipFileName, FileMode.Create))
{
zipMS.Seek(0, SeekOrigin.Begin);
zipMS.CopyTo(finalZipFileStream);
}
}
}
But problem is how to make it read file directly from S3 and upload the compressed file.
public static async Task CreateZipFile(List<List<KeyVersion>> keyVersions)
{
using MemoryStream zipMS = new MemoryStream();
using (ZipArchive zipArchive = new ZipArchive(zipMS, ZipArchiveMode.Create, true))
{
foreach (var key in keyVersions)
{
foreach (var fileToZip in key)
{
GetObjectRequest request = new GetObjectRequest
{
BucketName = "dev-s3-zip-bucket",
Key = fileToZip.Key
};
using GetObjectResponse response = await s3client.GetObjectAsync(request);
using Stream responseStream = response.ResponseStream;
ZipArchiveEntry zipFileEntry = zipArchive.CreateEntry(fileToZip.Key);
//add the file contents
using Stream zipEntryStream = zipFileEntry.Open();
await responseStream.CopyToAsync(zipEntryStream);
}
}
zipArchive.Dispose();
}
zipMS.Seek(0, SeekOrigin.Begin);
var fileTxfr = new TransferUtility(s3client);
await fileTxfr.UploadAsync(zipMS, "dev-s3-zip-bucket", "test.zip");
}
I'm making an compressor / decompressor console program in Visual Studio 2017 and I want to get the filepath by dragging the input file to the console (.txt).
i'm getting the right path for inputStream for Compress() but outPutStream fails and cant find the filepath (FileMode.OpenOrCreate!?!), even if the path is hardcoded.
Program executes correctly if both variables are hardcoded, but i can't understand why System.IO.FileNotFoundException is thrown by getting input file from dragging the file to console and have the output file hardcoded.
....
string outPutFileName = #"C:\bla\bla\bla\bla\gergrgr.gzip";
public static void Compress(string inPath)
{
using (FileStream inputStream = new FileStream(inPath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (FileStream outputStream = new FileStream(outPutFileName, FileMode.OpenOrCreate, FileAccess.Write))
{
using (GZipStream gzip = new GZipStream(outputStream, CompressionMode.Compress))
{
inputStream.CopyTo(gzip);
}
}
}
}
static void Main(string[] args)
{
string outPutFileName = #"C:\bla\bla\bla\bla\gergrgr.gzip";
//dummy var, cant find a better way to add '#' to variable set by console.readline
string filePath = #"test";
// info info info....
Console.WriteLine("Drag in txt file");
// Takes the path from dragged in file
string idk = Console.ReadLine();
// instead of of a loop to escape "/", just replace text in filePath
filePath = filePath.Replace("test", idk);
Compress(filePath);
}
I think the problem is actually that your app doesn't have permissions to write to the specified output location. Check the docs for FileMode.OpenOrCreate
If the file access is FileAccess.Write, Write permission is required.
The below works for me:
using System;
using System.IO;
using System.IO.Compression;
namespace ConsoleApp1
{
internal class Program
{
private static readonly string outPutFileName = #"C:<my desktop directory>\gergrgr.gzip";
public static void Compress(string inPath)
{
using (var inputStream = new FileStream(inPath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (var outputStream = new FileStream(outPutFileName, FileMode.OpenOrCreate, FileAccess.Write))
{
using (var gzip = new GZipStream(outputStream, CompressionMode.Compress))
{
inputStream.CopyTo(gzip);
}
}
}
}
private static void Main(string[] args)
{
// info info info....
Console.WriteLine("Drag in txt file");
// Takes the path from dragged in file
var filePath = Console.ReadLine();
if (!string.IsNullOrEmpty(filePath))
{
Compress(filePath.Trim('\\', '"'));
}
}
}
}
I have one example where all the files in the folder are zipped but not the folder itself .[This code is from MSDN]
using System;
using System.IO;
using System.IO.Compression;
namespace zip
{
public class Program
{
public static void Main()
{
string directoryPath = #"c ------------------------------------------------------------------------ :\users\public\reports";
DirectoryInfo directorySelected = new DirectoryInfo(directoryPath);
foreach (FileInfo fileToCompress in directorySelected.GetFiles())
{
Compress(fileToCompress);
}
foreach (FileInfo fileToDecompress in directorySelected.GetFiles("*.gz"))
{
Decompress(fileToDecompress);
}
}
public static void Compress(FileInfo fileToCompress)
{
using (FileStream originalFileStream = fileToCompress.OpenRead())
{
if ((File.GetAttributes(fileToCompress.FullName) & FileAttributes.Hidden) != FileAttributes.Hidden & fileToCompress.Extension != ".gz")
{
using
(FileStream compressedFileStream = File.Create(fileToCompress.FullName + ".gz"))
{
using (GZipStream compressionStream = new GZipStream(compressedFileStream, CompressionMode.Compress))
{
originalFileStream.CopyTo(compressionStream);
Console.WriteLine("Compressed {0} from {1} to {2} bytes.", fileToCompress.Name, fileToCompress.Length.ToString(), compressedFileStream.Length.ToString());
}
}
}
}
}
public static void Decompress(FileInfo fileToDecompress)
{
using (FileStream originalFileStream = fileToDecompress.OpenRead())
{
string currentFileName = fileToDecompress.FullName;
string newFileName = currentFileName.Remove(currentFileName.Length - fileToDecompress.Extension.Length);
using (FileStream decompressedFileStream = File.Create(newFileName))
{
using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
{
decompressionStream.CopyTo(decompressedFileStream);
Console.WriteLine("Decompressed: {0}", fileToDecompress.Name);
}
}
}
}
}
}
I don't think you can zip a complete folder using System.IO.Compression, you can only compress files inside the folder. You can use DotNetZip instead. It is a 100% managed code library that can be used in any .NET application - Console, Winforms, WPF, ASP.NET, Sharepoint, Web services apps, and so on.
Download developer's kit package from http://dotnetzip.codeplex.com/Release/ProjectReleases.aspx.
Reference necessaries including DotNetZip DLL in your application and do follows:
string[] MainDirs = Directory.GetDirectories(""c:\users\public\reports");
for (int i = 0; i < MainDirs.Length; i++)
{
using (ZipFile zip = new ZipFile())
{
zip.UseUnicodeAsNecessary = true;
zip.AddDirectory(MainDirs[i]);
zip.CompressionLevel = Ionic.Zlib.CompressionLevel.BestCompression;
zip.Comment = "This zip was created at " + System.DateTime.Now.ToString("G");
zip.Save(string.Format("test{0}.zip", i));
}
}
Hope this helps,
Thanks
I create a zip file in a controller from a byte array and I return the zip file as a fileresult. When I download the zip File and extract the file, it is corrupt. I'm doing it this way:
byte[] fileBytes =array
MemoryStream fileStream = new MemoryStream(fileBytes);
MemoryStream outputStream = new MemoryStream();
fileStream.Seek(0, SeekOrigin.Begin);
using (ZipFile zipFile = new ZipFile())
{
zipFile.AddEntry(returnFileName, fileStream);
zipFile.Save(outputStream);
}
outputStream.Position = 0;
FileStreamResult fileResult = new FileStreamResult(outputStream, System.Net.Mime.MediaTypeNames.Application.Zip);
fileResult.FileDownloadName = returnFileName + ".zip";
return fileResult;
You might be unlucky hitting one of the open bugs in DotNetZip. There is e.g. an issue depending on the file size (https://dotnetzip.codeplex.com/workitem/14087).
Unfortunately, DotNetZip has some critical issues and the project seems no longer be actively be maintained. Better alternatives would be to use SharpZipLib (if you comply with their GPL-based license), or one of the .NET ports of zlib.
If you are on .NET 4.5 you can use the built-in classes in the System.IO.Compression namespace. The following sample can be found in the documentation of the ZipArchive class:
using System;
using System.IO;
using System.IO.Compression;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
using (var zipToOpen =
new FileStream(#"c:\tmp\release.zip", FileMode.Open))
{
using (var archive =
new ZipArchive(zipToOpen, ZipArchiveMode.Update))
{
var readmeEntry = archive.CreateEntry("Readme.txt");
using (var writer = new StreamWriter(readmeEntry.Open()))
{
writer.WriteLine("Information about this package.");
writer.WriteLine("========================");
}
}
}
}
}
}
public class HomeController : Controller
{
public FileResult Index()
{
FileStreamResult fileResult = new FileStreamResult(GetZippedStream(), System.Net.Mime.MediaTypeNames.Application.Zip);
fileResult.FileDownloadName = "result" + ".zip";
return fileResult;
}
private static Stream GetZippedStream()
{
byte[] fileBytes = Encoding.ASCII.GetBytes("abc");
string returnFileName = "something";
MemoryStream fileStream = new MemoryStream(fileBytes);
MemoryStream resultStream = new MemoryStream();
using (ZipFile zipFile = new ZipFile())
{
zipFile.AddEntry(returnFileName, fileStream);
zipFile.Save(resultStream);
}
resultStream.Position = 0;
return resultStream;
}
}
I want to compress a file and a directory in C#. I found some solution in Internet but they are so complex and I couldn't run them in my project. Can anybody suggest me a clear and effective solution?
You could use GZipStream in the System.IO.Compression namespace
.NET 2.0.
public static void CompressFile(string path)
{
FileStream sourceFile = File.OpenRead(path);
FileStream destinationFile = File.Create(path + ".gz");
byte[] buffer = new byte[sourceFile.Length];
sourceFile.Read(buffer, 0, buffer.Length);
using (GZipStream output = new GZipStream(destinationFile,
CompressionMode.Compress))
{
Console.WriteLine("Compressing {0} to {1}.", sourceFile.Name,
destinationFile.Name, false);
output.Write(buffer, 0, buffer.Length);
}
// Close the files.
sourceFile.Close();
destinationFile.Close();
}
.NET 4
public static void Compress(FileInfo fi)
{
// Get the stream of the source file.
using (FileStream inFile = fi.OpenRead())
{
// Prevent compressing hidden and
// already compressed files.
if ((File.GetAttributes(fi.FullName)
& FileAttributes.Hidden)
!= FileAttributes.Hidden & fi.Extension != ".gz")
{
// Create the compressed file.
using (FileStream outFile =
File.Create(fi.FullName + ".gz"))
{
using (GZipStream Compress =
new GZipStream(outFile,
CompressionMode.Compress))
{
// Copy the source file into
// the compression stream.
inFile.CopyTo(Compress);
Console.WriteLine("Compressed {0} from {1} to {2} bytes.",
fi.Name, fi.Length.ToString(), outFile.Length.ToString());
}
}
}
}
}
http://msdn.microsoft.com/en-us/library/ms404280.aspx
I'm adding this answer as I've found an easier way than any of the existing answers:
Install DotNetZip DLLs in your solution (easiest way is to install the package from nuget)
Add a reference to the DLL.
Import the namespace by adding: using Ionic.Zip;
Zip your file
Code:
using (ZipFile zip = new ZipFile())
{
zip.AddFile("C:\test\test.txt");
zip.AddFile("C:\test\test2.txt");
zip.Save("C:\output.zip");
}
If you don't want the original folder structure mirrored in the zip file, then look at the overrides for AddFile() and AddFolder() etc.
For .Net Framework 4.5 this is the most clear example I found:
using System;
using System.IO;
using System.IO.Compression;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
string startPath = #"c:\example\start";
string zipPath = #"c:\example\result.zip";
string extractPath = #"c:\example\extract";
ZipFile.CreateFromDirectory(startPath, zipPath);
ZipFile.ExtractToDirectory(zipPath, extractPath);
}
}
}
You'll need to add a reference to System.IO.Compression.FileSystem
From: https://learn.microsoft.com/en-us/dotnet/standard/io/how-to-compress-and-extract-files
There is a built-in class in System.IO.Packaging called the ZipPackage:
http://msdn.microsoft.com/en-us/library/system.io.packaging.zippackage(v=vs.100).aspx
http://www.icsharpcode.net/opensource/sharpziplib/
You can just use ms-dos command line program compact.exe.
Look on a parameters compact.exe in cmd and start this process using .NET method Process.Start().
Using DotNetZip http://dotnetzip.codeplex.com/, there's an AddDirectory() method on the ZipFile class that does what you want:
using (var zip = new Ionic.Zip.ZipFile())
{
zip.AddDirectory("DirectoryOnDisk", "rootInZipFile");
zip.Save("MyFile.zip");
}
Bonne continuation...
just use following code for compressing a file.
public void Compressfile()
{
string fileName = "Text.txt";
string sourcePath = #"C:\SMSDBBACKUP";
DirectoryInfo di = new DirectoryInfo(sourcePath);
foreach (FileInfo fi in di.GetFiles())
{
//for specific file
if (fi.ToString() == fileName)
{
Compress(fi);
}
}
}
public static void Compress(FileInfo fi)
{
// Get the stream of the source file.
using (FileStream inFile = fi.OpenRead())
{
// Prevent compressing hidden and
// already compressed files.
if ((File.GetAttributes(fi.FullName)
& FileAttributes.Hidden)
!= FileAttributes.Hidden & fi.Extension != ".gz")
{
// Create the compressed file.
using (FileStream outFile =
File.Create(fi.FullName + ".gz"))
{
using (GZipStream Compress =
new GZipStream(outFile,
CompressionMode.Compress))
{
// Copy the source file into
// the compression stream.
inFile.CopyTo(Compress);
Console.WriteLine("Compressed {0} from {1} to {2} bytes.",
fi.Name, fi.Length.ToString(), outFile.Length.ToString());
}
}
}
}
}
}
Use http://dotnetzip.codeplex.com/ to ZIP files or directory, there is no builtin class to do it directly in .NET
Source code taken from MSDN that is compatible to .Net 2.0 and above
public static void CompressFile(string path)
{
FileStream sourceFile = File.OpenRead(path);
FileStream destinationFile = File.Create(path + ".gz");
byte[] buffer = new byte[sourceFile.Length];
sourceFile.Read(buffer, 0, buffer.Length);
using (GZipStream output = new GZipStream(destinationFile,
CompressionMode.Compress))
{
Console.WriteLine("Compressing {0} to {1}.", sourceFile.Name,
destinationFile.Name, false);
output.Write(buffer, 0, buffer.Length);
}
// Close the files.
sourceFile.Close();
destinationFile.Close();
}