I need help in writing a function which zips all files with same name but different extensions in a folder.I am using Ionic.Zip dll to achieve this.I am using .Net compact framework 2.0,VS2005. My code looks like this:
public void zipFiles()
{
string path = "somepath";
string[] fileNames = Directory.GetFiles(path);
Array.Sort(fileNames);//sort the filename in ascending order
string lastFileName = string.Empty;
string zipFileName = null;
using (ZipFile zip = new ZipFile())
{
zip.AlternateEncodingUsage = ZipOption.AsNecessary;
zip.AddDirectoryByName("Files");
for (int i = 0; i < fileNames.Length; i++)
{
string baseFileName = fileNames[i];
if (baseFileName != lastFileName)
{
zipFileName=String.Format("Zip_{0}.zip",DateTime.Now.ToString("yyyy-MMM-dd-HHmmss"));
zip.AddFile(baseFileName, "Files");
lastFileName = baseFileName;
}
}
zip.Save(zipFileName);
}
}
The problem:The folder will have 3 files with same name but their extensions will be different.Now,these files are being FTPed by a device so the filenames are auto-generated by it and I have no control over it.So,for example,there are 6 files in the folder:"ABC123.DON","ABC123.TGZ","ABC123.TSY","XYZ456.DON","XYZ456.TGZ","XYZ456.TSY". I have to zip the 3 files whose names are "ABC123" together and other 3 files with names "XYZ456".As I said,I wouldnt know the names of the files and my function has to run in background.My current code zips all the files in a single zip folder.
Can anyone please help me with this?
Try out the following code
string path = #"d:\test";
//First find all the unique file name i.e. ABC123 & XYZ456 as per your example
List<string> uniqueFiles=new List<string>();
foreach (string file in Directory.GetFiles(path))
{
if (!uniqueFiles.Contains(Path.GetFileNameWithoutExtension(file)))
uniqueFiles.Add(Path.GetFileNameWithoutExtension(file));
}
foreach (string file in uniqueFiles)
{
string[] filesToBeZipped = Directory.GetFiles(#"d:\test",string.Format("{0}.*",file));
//Zip all the files in filesToBeZipped
}
Related
I'm struggling with creating zip archives and could use some guidance from more experienced coders. I am attempting to create a zip archive of 800 folders and subfolders and about 8,000 files with the following method. This code works in so far that it will create an archive but there is no internal directory structure. All 8,000 files are stored in the zip in a single flat list. Is there a way to do this so that its like a typical zip archive in that the folder structure is also stored in the zip file? I am aware of the ZipFile.CreateFromDirectory() method [which does preserve folder structure] but do not want to use it because it fails in the event that a file is locked. I am also aware that there are other libraries but I'd like to use the C# library if that is possible. Any guidance will be appreciated. Thank you.
{
SearchOption searchOption = SearchOption.AllDirectories;
IEnumerable<string> fileSystem;
fileSystem = Directory.EnumerateFileSystemEntries(_zipRoot, "*.*", searchOption);
using (ZipArchive archive = ZipFile.Open(_zipPath, ZipArchiveMode.Create))
{
foreach (var fPath in fileSystem)
{
try
{
archive.CreateEntryFromFile(fPath,Path.GetFileName(fPath));
}
catch
{
FailedFiles.Add(fPath);
Debug.Log(fPath);
}
}
}
Debug.Log($"{FailedFiles.Count} files failed to archive.");
}```
After reading the thread posted by #mjwills which discusses several approaches, the following code suggested by #Curti works like a charm.
public static void StructuredZip(this ZipArchive archive, string sourceDirName, CompressionLevel compressionLevel = CompressionLevel.Fastest)
{
int fileCount = 0;
int folderCount = 0;
int failedCount = 0;
var folders = new Stack<string>();
folders.Push(sourceDirName);
do
{
var currentFolder = folders.Pop();
folderCount++;
foreach (var item in Directory.GetFiles(currentFolder))
{
try
{
archive.CreateEntryFromFile(item, item.Substring(sourceDirName.Length + 1),
compressionLevel);
fileCount++;
}
catch
{
failedCount++;
}
}
foreach (var item in Directory.GetDirectories(currentFolder))
{
folders.Push(item);
}
}
while (folders.Count > 0);
Debug.Log($"Archived {fileCount} in {folderCount} folders. There were {failedCount} failed files!");
}
}
using (var zip = ZipFile.Open(_zipPath, ZipArchiveMode.Create))
{
zip.StructuredZip(_zipRoot);
}
I have 10 folders (C:\Import)
Folder1
Folder2
.
.
Folder10
Each folder have some .txt and .html files.
Let me take example of Folder1 having 3 documents
file.txt
file2.html
file3.txt
files in it.
I need script to read the folder and create a txt file in below format.
Folder name 'separator' file name without extension 'separator' filename with extension
So output text file should be :
Folder1:file:file.txt
Folder1:file2:file2.html
Folder1:file3:file3.txt
and Move html, txt files and newly create text file too C:\Output.
This has to be repeated for all the 10 folders and all the corresponding files and created text file should be dropped to same C:\Output
Tried below :
1:
foreach (string file in Directory.GetFiles("C:\\Import\\", "*.html", SearchOption.AllDirectories))
{
string contents = File.ReadAllText(file);
}
2:
public static List<string> AllFilesInFolder(string folder)
{
var result = new List<string>();
foreach (string f in Directory.GetFiles(folder))
{
result.Add(f);
}
foreach (string d in Directory.GetDirectories(folder))
{
result.AddRange(AllFilesInFolder(d));
}
return result;
}
I would suggest you to write PowerShell script. The file manipulation is much easier in powershell, and you can always use .NET libriaries.
Please, take a look at this link, it's Microsoft doc about "Working with Files and Folders" using PowerShell.
But if you don't want to use PowerShell, you can do something like that:
using System;
using System.IO;
using System.Text;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("APP START");
string inputDirectory = #"C:\Import\";
string outputDirectory = #"C:\Output\";
FileStream stream = File.Create(outputDirectory + "report.txt");
string [] folders = Directory.GetDirectories(inputDirectory);
foreach(String path in folders)
{
Directory.CreateDirectory(path.Replace(inputDirectory, outputDirectory));
string[] files = Directory.GetFiles(path);
foreach (String file in files)
{
String record = ConvertPathToReportFormat(file);
stream.Write(Encoding.UTF8.GetBytes(record), 0, record.Length);
File.Copy(file, file.Replace(inputDirectory, outputDirectory));
}
}
stream.Close();
Console.WriteLine("DONE");
Console.ReadKey();
}
private static String ConvertPathToReportFormat(string path)
{
string [] splitedPath = path.Split('\\');
string[] splitedName = splitedPath[splitedPath.Length - 1].Split('.');
String folder = splitedPath[splitedPath.Length - 2];
String name = splitedName[0];
String extension = splitedName[1];
return String.Format("{0}:{1}:{2}.{3}\n", folder, name, name, extension);
}
}
}
This little program copy files from one directory to another, and generates report file (report.txt) in following format:
Folder1:File:File.html
Folder1:File:File.txt
Folder1:File2:File2.html
Folder1:File2:File2.txt
Folder1:File3:File3.html
Folder1:File3:File3.txt
I am trying to zip a folder using IonicZip library in C#. It is able to zip .txt, .exe, .pdf etc. in the folder, but not able to zip folder in folder.
It is able to zip MusicLogs.txt and Video.exe but cannot Music folder.Music folder contains some folder also. It doesnt see Music folder even while debugging. My code is :
string zipPath = #"C:\" + DateTime.Now.ToString("yyyy-MM-dd HH-mm") + ".zip"; // zipped file extracts here
string filename = #"E:\"; // the fodler which should be zipped. File must be exist
using (ZipFile zipFile = new ZipFile())
{
zipFile.Password = "asd";
zipFile.Encryption = EncryptionAlgorithm.PkzipWeak;
foreach (string file in Directory.GetFiles(filename)) // this foreach is for getting all files in a folder.
{
zipFile.AddFile(file, "YESMusic"); // set file
}
zipFile.Save(zipPath);
}
Where is the problem ? Need a change in AddFile function ? Thanks
This will work:
using (ZipFile zipFile = new ZipFile())
{
zipFile.Password = "asd";
zipFile.Encryption = EncryptionAlgorithm.PkzipWeak;
// Adding folders in the base directory
foreach (var item in Directory.GetDirectories(filename))
{
string folderName = new DirectoryInfo(item).Name;
zipFile.AddDirectory(item, folderName);
}
// Adding files in the base directory
foreach (string file in Directory.GetFiles(filename))
{
zipFile.AddFile(file);
}
zipFile.Save(zipPath);
}
I'm receiving an error Access to the path ... is denied when I attempt to read the files from a specified path. The code that demonstrates the error is below:
string path = "D:\\Study\\Прога 4 семестр\\Курсач\\tests";
StreamReader sr = new StreamReader(path);
while(!sr.EndOfStream)
{
string s = Path.GetFileNameWithoutExtension(path);
listBox1.Items.Add(s);
}
sr.Close();
What exactly is wrong with the code that an error occurs? How do I accomplish my goal?
Use Directory.EnumerateFiles to get all files in directory, and then project each file path to file name:
var names = Directory.EnumerateFiles(path)
.Select(f => Path.GetFileNameWithoutExtension(f));
Or even shorter way:
Directory.EnumerateFiles(path).Select(Path.GetFileNameWithoutExtension);
Unfortunately your using incorrect syntax. StreamReader will read a file, it will not retrieve a file. What you should do is use the Directory functionality from System.IO.
Example:
string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string[] files = Directory.GetFiles(path);
foreach(string item in files)
Console.WriteLine(item);
That would actually retrieve file data.
A secondary example:
var path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var file = Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories)
.Select(Path.GetFileName);
The Microsoft Developer Network has some terrific articles on different approaches to handle retrieval of files or directories from the system.
You can use Directory which has a method GetFiles(String) (+ 2 overloads) to enumerate and process files on older versions of .NET Frameworks.
string path = "D:\\Study\\Прога 4 семестр\\Курсач\\tests";
string[] fileNames = Directory.GetFiles(path);
for(int i = 0; i < fileNames.Length; i++)
{
string fileName = Path.GetFileNameWithoutExtension(path + "\\" + fileNames[i]);
listBox1.Items.Add(fileName);
}
Background: I'm developing a WinForms application using C# with an OpenFileDialog & FileBrowserDialog that will 1) search for a specific string in the filenames of a specified source directory 2) copy files to consolidated directory 3) convert multiple files from excel to csv files, and then 3) convert all the generated csv files into 1 big csv file using a command line executable
Example: MSDN provides a code example that lists all of the directories and files that begin with the letter "c" in "c:\". at http://msdn.microsoft.com/en-us/library/ms143448.aspx so I based my code on that...
Problem: The code doesn't copy any files to the consolidated folder so I'm pretty sure the search doesn't work.
What should I change on here? It doesn't work :
string files = "*.xlsx";
void DirSearch(string sDir)
{
try
{
foreach (string d in Directory.GetDirectories(sDir))
{
foreach (string f in Directory.GetFiles(d, files))
{
// Is this the file we are looking for?
// check excel files for corp name in the filename.
if (f.Contains(m_sc.get_Corp()))
{
// check if thread is cancelled
if (m_EventStop.WaitOne(0, true))
{
// clean-up operations may be placed here
// ...
// inform main thread that this thread stopped
m_EventStopped.Set();
return;
}
else
{
string path = sDir;
string searchPattern = m_sc.get_Corp();
// A file has been found in this directory
DirectoryInfo di = new DirectoryInfo(path);
DirectoryInfo[] directories = di.GetDirectories(searchPattern, SearchOption.TopDirectoryOnly);
foreach (FileInfo file in files)
{
try
{
// Copy each selected xlsx files into the specified TargetFolder
System.IO.File.Copy(FileName, consolidatedFolder + #"\" + System.IO.Path.GetFileName(FileName));
Log("File" + FileName + " has been copied to " + consolidatedFolder + #"\" + System.IO.Path.GetFileName(sourceFileOpenFileDialog.FileName));
// Convert each selected XLSX File to CSV Using the command prompt code...
}
}
}
}
The code you've posted does two separate search loops:
first:
foreach (string d in Directory.GetDirectories(sDir))
{
foreach (string f in Directory.GetFiles(d, files))
{
// Is this the file we are looking for?
// check excel files for corp name in the filename.
if (f.Contains(m_sc.get_Corp()))
{
then within that it also does:
string path = sDir;
string searchPattern = m_sc.get_Corp();
// A file has been found in this directory
DirectoryInfo di = new DirectoryInfo(path);
DirectoryInfo[] directories = di.GetDirectories(searchPattern, SearchOption.TopDirectoryOnly);
foreach (FileInfo file in files)
{
In the first one you are looking for files matching m_sc.get_Corp();, in the second one you are lookinf for directories...
In fact... your code (pseudo-code?) makes no sense...
Try:
taking your time
tidying up the code yourself
if you rewrite it slowly and break this into smaller chunks, you might spot what you are doing wrong.
Try cleaning up a bit, below is some code that will put you on the path, I've excluded the CSV conversion and the merge, hopefully you will get the idea.
private void YourFileRoutine(string sourceDirectoryPath, string consolidatedDirectoryPath)
{
var excelFiles = new DirectoryInfo(sourceDirectoryPath).GetFiles().Where(x => x.Extension == ".xlsx");
//Copy all Excel Files to consolidated Directory
foreach (var excelFile in excelFiles)
{
FileInfo copiedFile = excelFile.CopyTo(String.Concat(consolidatedDirectoryPath, excelFile.Name)); // Make sure consolidatedDirectoryPath as a "\" maybe use Path.Combine()?
// ConvertToCSV( Do your CSV conversion here, the Path will be = Path.GetFullPath(copiedFile);
}
// Merge CSV's
var csvFiles = new DirectoryInfo(consolidatedDirectoryPath).GetFiles().Where(x => x.Extension == ".csv");
// SomeMergeMethod that iterates through this FileInfo collection?
}