C# System.IO.InvalidDataException zip file - c#

System.IO.InvalidDataException: 'Number of entries expected in Central Directory Ending does not match the number of entries in the Central Directory.'
I'm getting this error on a code that i'm making "for fun" when i try to extract an zip file to a folder. Help ;-;
here's my situation: i made a Drag and Drop panel that recieve a file with a unique extension (the file is a zip but i changed the extension to test). Then the program will get the first line of text in the archive, and will create a folder to extract the files with the name given on that first line. But it gets that error on the extract code
string[] Arquivo = (string[])e.Data.GetData(DataFormats.FileDrop, false);
foreach (string arquivo in Arquivo)
{
MessageBox.Show(arquivo);
string[] allLines = File.ReadAllLines(arquivo);
string line = string.Empty;
if (allLines.Length >= 1)
{
line = allLines[0];
}
string Diretorio = #"C:\CommunicAlt\" + line;
MessageBox.Show(Diretorio);
if (!Directory.Exists(Diretorio))
{
Directory.CreateDirectory(Diretorio);
}
Path.ChangeExtension(arquivo, ".zip");
ZipFile.ExtractToDirectory(arquivo, Diretorio); //<--Here

I solved it, the problem is: the zip archive has a new line with a text to create a directory, but the visual studio can't extract it if the number of lines on the archive is different drom the default... so it won't extract.
The solution was to leave the zip archive untouched and create a new file with the config info.

Related

C# ASP System.IO.Compression - Unauthorized access exception when using zipArchive.CreateEntryFromFile for multiple files()

I have the following lines of code that work for creating a zip using ZipFile.CreateFromDirectory(selectedFile, zipPath)
if (selectedFolder == string.Empty)
{
Console.WriteLine("Invalid folder, try again");
}
else
{
Console.WriteLine("\nSelect zipfile name: ");
var zipName = Console.ReadLine();
// Also available: extractToDirectory
var zipPath = #"C:\Users\User\Documents\Dev\" + zipName + ".zip";
ZipFile.CreateFromDirectory(selectedFolder, zipPath);
However, the following code which should for all intents and purposes do the same thing except for multiple files being archived into a single zip folder refuses to work:
public static void CreateZipFile(string folderToCreateZip, IEnumerable<string> files)
{
var zipPath = folderToCreateZip + "\\test6.zip";
// Create a new ZIP in this location
using (var zip = ZipFile.Open(zipPath, ZipArchiveMode.Create))
{
foreach (var file in files)
{
// Add entry for files
zip.CreateEntryFromFile(file, zipPath, CompressionLevel.Optimal);
}
}
// Dispose of zip object after files have been zipped
//zip.Dispose();
}
var zip == ZipArchive zip
I've tried disabling read-only mode on the folders where the zip should get created, but I don't think this matters since the prior function with CreateFromDirectory() works fine. I've also tried creating a ZIP on desktop, but I get the same error.
This is the exception I'm getting:
As a note, I noticed that it does initially create the zip despite this error, just that it cannot add anything to it unlike CreateFromDirectory() can due to the folder either being in use, no permissions to that area or the folder already existing. Is there a way I can get CreateEntryFromFile() working or an alternative that would work for multiple files?
I had the same problem. The solution was post the full path name at the destinationArchiveFileName parameter (and also a write alowed path). For example c:\my apps folder\my app\my temp\zipfile.zip

Extracting files nested within a zip file using System.IO.Compression C#

I have a number of zip files that contain .txt files nested in sub directories within the zip file. I am trying to extract the .txt files and output them to another directory, however I am getting an error 'Could not find a part of the path...' This error occurs at the 'entry.FullName' point
I believe I need to remove the file path at some stage of the unzip process since I can get the code to run if I use zip files with .txt files in them without any sub-directories. Any pointers would be much appreciated.
Here is my code:
class Program
{
static void Main(string[] args)
{
DateTime dt = DateTime.Now;
foreach (var zp in Directory.GetFiles(#"D:\\My Documents\\DMU\\Frontrunner2015\\ZipIn\\", "*.zip"))
{
string zipPath = zp;
string extractPath = #"D:\\My Documents\\DMU\\Frontrunner2015\\ZipOut\\";
using (ZipArchive archive = ZipFile.OpenRead(zipPath))
{
foreach (ZipArchiveEntry entry in archive.Entries)
{
if (entry.FullName.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
{
entry.ExtractToFile(Path.Combine(extractPath, entry.FullName));
}
foreach (var file in Directory.GetFiles(extractPath))
{.....
Would have helped if you left the path in the error message there so people could see what path was not found. I would guess that when you combine extractPath and FullName you end up with a folder name that does not exist - as you mentioned the files in the zip file have subdirectories.
I think you really meant to use Name property in your Path.Combine call.

C# mass File renamer

i want to create C# mass file renamer, here is my UI
i have created tes folder, inside of tes there's a file which is 1.txt.
i want to create my program to add prefix and suffix to the files, so 1.txt will become
prefix1suffix
but then i got an error
it's said file already exist though there's only one file on tes folder, which is 1.txt how do i make it work ? where's the error comes from ?
i have tried the following code
private void Rename(string prefix, string filepath, string suffix)
{
//i don't use prefix suffix yet to make sure if my function works
DirectoryInfo d = new DirectoryInfo(filepath);
FileInfo[] file = d.GetFiles();
try
{
foreach (FileInfo f in file )
{
File.Move(f.FullName,"stackoverflow");
}
}
catch (Exception e)
{
cmd.cetakGagal(e.ToString(), title);
}
cmd.cetakSukses("Rename Success", title);
}
and it returns same error as the second picture above.
the following picture is tes folder, there's nothing in tes folder except 1.txt
You are calling File.Move() with a full path for your sourceFileName and a relative path for your destFileName. The relative file path is relative to the current working directory and not to the source file path. I expect that a stackoverflow file exists in the current working directory, most likely created the first time you ran this code.
your File.Move is changing them all to StackOverflow not using the prefix and suffix. If you only have one file in the directory it shouldn't be an issue. Are you sure there is only 1 file?
public static void Move(
string sourceFileName,
string destFileName
)
Looking at this answer might be the clue as you are specifying relative path for the destination file. To obtain the current working directory, see GetCurrentDirectory
The sourceFileName and destFileName arguments are permitted to specify
relative or absolute path information. Relative path information is
interpreted as relative to the current working directory.
You should change
File.Move(f.FullName,"stackoverflow");
to
string fileName = f.Name.Replace(f.Extenstion,string.Empty);
string newFileName = string.Format("{0}{1}{2}",prefix,fileName,suffix);
string newFileWithPath = Path.Combine(f.Directory,newFileName);
if (!File.Exists(newFileWithPath))
{
File.Move(f.FullName,newFileWithPath);
}
The code above will give you that error since, after the first run through, "stackoverflow" exists as a file. Make sure that you check if the destination file exists (using File.Exists) before calling File.Move.
Since your goal is renaming, I would suggest using a test folder filled with files rather than using a piecemeal approach. See if something like this helps:
private void Rename(string prefix, string filepath, string suffix)
{
//i don't use prefix suffix yet to make sure if my function works
DirectoryInfo d = new DirectoryInfo(filepath);
FileInfo[] file = d.GetFiles();
try
{
foreach (FileInfo f in file )
{
f.MoveTo(#filepath + #"\" + prefix + f.Name.Insert(f.Name.LastIndexOf('.'),suffix));
}
}
catch (Exception e)
{
cmd.cetakGagal(e.ToString(), title);
}
cmd.cetakSukses("Rename Success", title);
}
on a side note using a listview to display the filenames and the changes before they're committed will help prevent unwanted changes.

Why does the Name Property of FileInfo object start with "~$"?

So I'm writing some code that is going through a directory of .xlsx files and picking the file that was created last. It's a simple task, but there is something a bit strange happening with the Name property of a particular FileInfo object and potentially there are more cases of this occurring.
Here is my code:
DirectoryInfo di = new DirectoryInfo(FolderPath);
FileInfo[] FileArray = di.GetFiles("*.xlsx", SearchOption.AllDirectories);
if (FileArray.Count() != 0)
{
DateTime latestDate = DateTime.MinValue;
string FileName = String.Empty;
foreach (FileInfo File in FileArray)
{
if (File.CreationTime > latestDate)
{
latestDate = File.CreationTime;
FileName = File.FullName;
}
}
}
The FileName is important because I use it to query the latest file for information and display it. However, the Name property of a particular .xlsx file (potentially more) is appearing like this ~$File.xlsx when in fact the file name is really File.xlsx. This causes the FullName property to contain these characters as well.
Is there any way to fix this? What triggers this?
Opening an xlsx file results in Excel creating a hidden file with the same name preceded by "~$". So if one of these Excel files are open at the time you retrieve the content of the directory, you will also get the temp file.
Add a filter that excludes hidden files and your issue is fixed.
Example:
FileAttributes attributes = File.GetAttributes(path);
if((attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
{
// Hidden file, just skip it
}
From http://msdn.microsoft.com/en-us/library/system.io.file.getattributes.aspx
~$ indicates that the file is a temporary file used by Microsoft Office. See here for additional information.

write the list of files in a folder to afile

I wrote a code to read all the files in a folder, then write them to a file. All the code complies and runs okay, but the filenames of the files are not displayed in the new file.
Code:
private void Form1_Load(object sender, EventArgs e)
{
DialogResult result = folderBrowserDialog1.ShowDialog(); // Show the dialog.
// create a list to insert the data into
//put all the files in the root directory into array
string[] array1 = Directory.GetFiles(#"C:\Users\a3708906\Documents\Filereader m 15062012", "*.csv");
// Display all files.
TextWriter tw1 = new StreamWriter("C:/Users/a3708906/Documents/Filereader m 15062012/Filereader m 15062012/listoffiles.txt");
List<string> filenames = new List<string>();
tw1.WriteLine("--- Files: ---");
foreach (string name in array1)
{
tw1.WriteLine(name);
}
tw1.Close();
}
I would be grateful for your assistance.
You took the trouble to ask the user the folder location, yet you don't retrieve that folder location. The code should be
string[] array1 = Directory.GetFiles(folderBrowserDialog1.SelectedPath, "*.csv");
// Display all files.
TextWriter tw1 = new StreamWriter(folderBrowserDialog1.SelectedPath+"/listoffiles.txt");
If the file isn't created (ie its just not there, even if it's just blank) then you problem lies with the stream writer. If this is the case I would suggest changing the direction of slashes so that your path is
TextWriter tw1 = new StreamWriter("C:\\Users\\a370890\\Documents\\Filereader m 15062012\\Filereader m 15062012\\listoffiles.txt");
If the file is created but nothing is written have a look at the flush command.
tw1.Flush();
Set a breakpoint to verify that GetFiles is returning files.
(Consider renaming array1 to something more meaningful)
Set a breakpoint on tw1.WriteLine(name) and ensure it is being hit.
It should be pretty easy to see the problem. My guess is that you simply aren't getting any files returned from GetFiles, but the breakpoints will tell you for sure. If your output file is created but missing the files - this is most likely the case.
If your output file doesn't exist; take a closer look at your file writing code.
I would say that your "space" in your folderpath is messing things up. Try to escape the "whitespace" by following the explanations in the msdn
I think problem is with your file path or file writing capability.
You use folderbrowserdialog but do not use it to get selected file
name. Instead you give path manually. also your output path can have
problem.
Try this :
using(system.IO.StreamWriter tw1 =
new system.IO.StreamWriter(#"C:/Users/a3708906/Documents/Filereader m 15062012/Filereader m 15062012/listoffiles.txt")
{
foreach (string name in array1)
{
tw1.WriteLine(name);
}
}

Categories

Resources