Quote-Enclosing 600+ CSV files in a directory c# - c#

I currently have this method that can successfully quote-enclose a single CSV file but I am trying to loop through 600+ CSV files in a directory and perform the Quote Enclose method on each one. I am unsure how to do this effectively. Any feedback is appreciated.
Below is my code:
public void QuoteEnclosingCSV()
{
string fileNamePath = Path.GetTempPath() + #"\Reports\*.csv";
var stringBuilder = new StringBuilder();
foreach (var line in File.ReadAllLines(fileNamePath))
{
stringBuilder.AppendLine(string.Format("\"{0}\"", string.Join("\",\"", line.Split(','))));
}
File.WriteAllText(string.Format(fileNamePath, Path.GetDirectoryName(fileNamePath)), stringBuilder.ToString());
}
string marFolder = Path.GetTempPath() + #"\Reports\";
var dir = new DirectoryInfo(marFolder);
foreach (var file in dir.EnumerateFiles("*.csv"))
{
QuoteEnclosingCSV();
}
Below is the error I'm receiving:
Illegal characters in path.

My first step in unraveling this conundrum would be to guess what the error message is trying to tell me. My first guess would be that it's trying to say that the path has illegal characters in it. Did you stop to check what characters were in the path that you get the error on?
I'll show you:
C:\Users\YoungStamos\AppData\Local\Temp\\Reports\*.csv
That's the path you pass to File.ReadAllLines(). The single argument to that method is a path to one single file. You can't have an asterisk (*) in a filename in Windows, because it's a wildcard.
What you seem to be trying to do is pass a parameter to QuoteEnclosingCSV(). In this loop, you carefully list each file, but you never tell QuoteEnclosingCSV() about any of them.
foreach (var file in dir.EnumerateFiles("*.csv"))
{
QuoteEnclosingCSV();
}
This is more like what you want:
public void QuoteEnclosingCSV(string fileNamePath)
{
var stringBuilder = new StringBuilder();
foreach (var line in File.ReadAllLines(fileNamePath))
{
stringBuilder.AppendLine(string.Format("\"{0}\"", string.Join("\",\"", line.Split(','))));
}
// I don't know what string.Format() is meant to do here; I'm guessing your guess is
// as good as mine, so I'm eliminating it.
//File.WriteAllText(string.Format(fileNamePath, Path.GetDirectoryName(fileNamePath)), stringBuilder.ToString());
File.WriteAllText(fileNamePath, stringBuilder.ToString());
}
And then call it like this:
string marFolder = Path.Combine(Path.GetTempPath(), "Reports");
var dir = new DirectoryInfo(marFolder);
foreach (var fileInfo in dir.EnumerateFiles("*.csv"))
{
QuoteEnclosingCSV( fileInfo.FullName );
}

Related

How to validate multi part compressed (i.e zip) files have all parts or not in C#?

I want to validate multipart compressed files like Zip because when any part missing for compressed files then it raises an error, but I want to validate it before extraction and different software creates a different naming structure.
I also refer one DotNetZip related questions.
The below screenshot is from 7z software.
And the second screenshot is from DotNetZip from C#.
One more thing is that I also want to test that it's also corrupted or not like 7z software. Please refer below screenshot for my requirements.
Please help me with these issues.
I am not sure if you will be able to see the exact error as shown in your snapshot. But I have a code which may help you to find if the multipart file is readble.
I have used nuget Package CombinationStream.
The ZipArchive constructor throws ArgumentException or InvalidDataException if the stream is not readable.
Below is the code:
public static bool IsZipValid()
{
try
{
string basePath = #"C:\multi-part-zip\";
List<string> files = new List<string> {
basePath + "somefile.zip.001",
basePath + "somefile.zip.002",
basePath + "somefile.zip.003",
basePath + "somefile.zip.004",
basePath + "somefile.zip.005",
basePath + "somefile.zip.006",
basePath + "somefile.zip.007",
basePath + "somefile.zip.008"
};
using (var zipFile = new ZipArchive(new CombinationStream(files.Select(x => new FileStream(x, FileMode.Open) as Stream).ToList()), ZipArchiveMode.Read))
{
// Do whatever you want
}
}
catch(InvalidDataException ex)
{
return false;
}
return true;
}
I am not sure if this is what you are looking for or you need more details in the error. But hope this helps you to come to solution of your issue.
From your comments I understood that the issue you have is to identify the files (get the list of parts belonging together). You can get a list of files like
List<string> files = System.IO.Directory.EnumerateFiles(#"D:\Zip\ForExtract\multipart\",
"500mbInputData.*", SearchOption.TopDirectoryOnly).OrderBy(x => x).ToList();
or for your second case
List<string> files = System.IO.Directory.EnumerateFiles(#"D:\Zip\ForExtract\multipart\",
"500mbInputData.zip.*", SearchOption.TopDirectoryOnly).OrderBy(x => x).ToList();
and then use the file list in your CombinationStream. The rest of the code would look like Manoj Choudhari wrote. You could also put the path and the file name with wild card into a parameter, so I'd suggest to add the following parameters to the function:
public static bool IsZipValid(string basePath, string fileNameWithWildcard)
{
try
{
List<string> files = System.IO.Directory.EnumerateFiles(
basePath, fileNameWithWildcard,
SearchOption.TopDirectoryOnly).OrderBy(x => x).ToList();
using (var zipFile = // ... rest is as Manoj wrote
and use it like:
if (IsZipValid(#"D:\Zip\ForExtract\multipart\", "500mbInputData.*")) { // ... }
or
if (IsZipValid(#"D:\Zip\ForExtract\multipart\", "500mbInputData.zip.*")) { // ... }
To find out which kind of files you have in the basepath, you could write a helper function like
List<string> getZipFormat(string path)
{
bool filesFound(string basePath, string pattern) => System.IO.Directory.EnumerateFiles(
basePath, pattern, SearchOption.TopDirectoryOnly).Any();
var isTar = filesFound(path, "*.tar.???");
var isZip = filesFound(path, "*.z??");
var is7Zip = filesFound(path, "*.7z.???");
var result = new List<string>();
if (isTar) result.Add("TAR");
if (isZip) result.Add("ZIP");
if (is7Zip) result.Add("7ZIP");
return result;
}
Modify it to your needs - it will return a list of strings containing "TAR", "ZIP" or "7ZIP" (or more than one of them), depending on the patterns matching against the files in the base directory.
Usage (example for multi-zipformat check):
var isValid = true;
var basePath = #"D:\Zip\ForExtract\multipart\";
foreach(var fmt in getZipFormat(basePath))
switch (fmt)
{
case "TAR":
isValid = isValid & IsZipValid(basePath, "500mbInputData.tar.*");
break;
case "ZIP":
isValid = isValid & IsZipValid(basePath, "500mbInputData.zip.*");
break;
case "7ZIP":
isValid = isValid & IsZipValid(basePath, "500mbInputData.7z.*");
break;
default:
break;
}
Note: As per my experiments with this, it could happen that the files remain open although your program has ended - meaning your files will still be locked the next time you run your code. So, I'd strongly suggest to explicitly close them, like
var fStreams = files.Select(x =>
new FileStream(x, FileMode.Open) as System.IO.Stream).ToList();
using (var cStream = new CombinationStream(fStreams))
using (var zipFile = new ZipArchive(cStream, ZipArchiveMode.Read))
{
// Do whatever you want...
// ... but ensure you close the files
fStreams.Select(s => { s.Close(); return s; });
};

Checking to see File exists is not working

I am trying to check to see if the file exists if it doesn't leave the textbox blank! it doesn't work
string[] filePaths = Directory.GetFiles(#"C:\TwinTable\LeftTableO0201", "*.*");
if (!File.Exists(filePaths.ToString()))
{
TboxLeftTable.Text = "";
}
else
{
TboxLeftTable.Text = System.IO.Path.GetFileName(filePaths[0]);
}
Well, one problem you have is that you are just trying to use ToString() on an array. Since Directory.GetFiles() returns an array of file names, you need to iterate over those files and check them one at a time. Something like this:
string[] filePaths = Directory.GetFiles(#"C:\TwinTable\LeftTableO0201", "*.*");
foreach (string curFilePath in filePaths)
{
if (!File.Exists(curFilePath))
{
TboxLeftTable.Text = "";
}
else
{
TboxLeftTable.Text = System.IO.Path.GetFileName(curFilePath);
}
}
Once your code is fixed you still have weird logic. If we take your logic and spell it out in a sentence it reads like this:
Get a list of files from a folder, then immediately check to see if the file(s) in that folder exist
I think what you want to do instead is:
Get a list of files from a folder, if one exists display the very first one's name in a textbox, if it does not, display nothing
If I am right, then your code would look like this:
// Gets all string file paths in a folder
// then grabs the first one, or null if there are none
string filePath = Directory.GetFiles(#"C:\TwinTable\LeftTableO0201", "*.*").FirstOrDefault();
// if the path is not null, empty or whitespace
if(!string.IsNullOrWhiteSpace(filePath)
{
// then get the filename and put it in the textbox
TboxLeftTable.Text = Path.GetFileName(filePath);
}
else
{
// There were no files in the folder so make the textbox empty
TboxLeftTable.Text = string.Empty;
}
This is the working code. Thanks for the help!
string[] filePaths = Directory.GetFiles(#"C:\TwinTable\LeftTableO0201", "*.*");
if (filePaths.Length > 0)
TboxLeftTable.Text = System.IO.Path.GetFileName(filePaths[0]);

Getting "Could not find part of the path" error

im working on a project and what i try to do is to delete the
files in my folder.
but I get the error:
Could not find part of the path.
The problem is that the path have a ' which does make part of the path. Here is my code:
foreach (var a in attachments)
{
string[] files = System.IO.Directory.GetFiles(Server.MapPath("~/Files/'"+ a.FileName +"'"));
foreach (string pathfile in files)
{
System.IO.File.Delete(pathfile);
}
}
the result path is this:
'c:.....\Files\'14d75c4e-c25f-4288-9a75-08a359fe6d844.png'"
How can I solve this?
You don't need single quotes.
string[] files = System.IO.Directory.GetFiles(Server.MapPath("~/Files/"+ a.FileName));
This is because your code has extra (un needed) single quotes.
....MapPath("~/Files/'"+ a.FileName +"'"));
Change this line;
string[] files = System.IO.Directory.GetFiles(Server.MapPath("~/Files/'"+ a.FileName +"'"));
to
string[] files = System.IO.Directory.GetFiles(Server.MapPath(string.Format("~/Files/{0}", a.FileName));
Notice the change at the end of the code snippet(s).
Also, if I could suggest, wrap this in a Try / Catch (this would will help any future debugging as well).
Hope this helps.
Finally i have solved it.
the problem was the path and what i have done was little
different what i had before.
i have create a method to return the root path.
And then i have add it a simple variable and execute the
delete command.
Here is my code:
Method:
private string StorageRoot
{
get { return Path.Combine(System.Web.HttpContext.Current.Server.MapPath("~/Files/")); }
}
Delete Command:
foreach (var a in attachments)
{
var myfilename = a.FileName;
var filetoDelete = StorageRoot + myfilename;
System.IO.File.Delete(filetoDelete);
}
Hope this solution helps someone in the future.

file content comparison issue c#

my requirement is to move files from one directory to another after certain interval. So basic copy works, but during the next subsequent interval I want to move only the new files.
Following is my approach:
I am creating the file list of both source & target directory in target location, the idea is based on the difference of these two files copy only the files that are new from last iteration.
For 1st iteration it will create a blank file in target indicating copy everything. But my file comparison is hitting issues here, based on logic in below code it's creating this excpetion "System.Linq.Enumerable+d__99`1[System.String]"
Here's the code:
static void Main(string[] args)
{
create_source_fileList();
string source_dir = System.Configuration.ConfigurationSettings.AppSettings["SourceDir"];
string target_dir = System.Configuration.ConfigurationSettings.AppSettings["TargetDir"];
string dpath = target_dir + "Diff" + ".txt";
TextWriter df = new StreamWriter(dpath);
DirectoryInfo sourceinfo = new DirectoryInfo(source_dir);
DirectoryInfo targetinfo = new DirectoryInfo(target_dir);
string[] source_f_list = File.ReadAllLines(target_dir + "Source_File_List.txt");
string[] target_f_list = File.ReadAllLines(target_dir + "Target_File_List.txt");
IEnumerable<String> file_list_diff = source_f_list.Except(target_f_list);
df.WriteLine(file_list_diff);
df.Close();
if (!Directory.Exists(targetinfo.FullName))
{
Directory.CreateDirectory(targetinfo.FullName);
}
foreach (FileInfo fi in sourceinfo.GetFiles())
{
fi.CopyTo(Path.Combine(targetinfo.ToString(), fi.Name), true);
}
create_target_fileList();
}
Need help in fixing this issue,also will this approach down the line work in loop where I will iterate only the names in diff file.
Thanks!!
It's not creating an exception; rather, it's writing the result of calling ToString on an IEnumerable<string> instance. You need to replace:
df.WriteLine(file_list_diff);
with
df.WriteLine(string.Join(Environment.NewLine, file_list_diff));
or, prior to .NET 4:
df.WriteLine(string.Join(Environment.NewLine, file_list_diff.ToArray()));

Can't add files to listbox...READ

I'm using a code to show all startup items in listbox with environment variable "%appdata%
There is some errors in this code that I need help with....
Check code for commented errors
Is there any other solution but still using %appdata%?
This is the code:
private void readfiles()
{
String startfolder = Environment.ExpandEnvironmentVariables("%appdata%") + "\\Microsoft\\Windows\\Start Menu\\Programs\\Startup";
foldertoread(startfolder);
}
private void foldertoread(string folderName)
{
FileInfo[] Files = folderName.GetFiles("*.txt"); // HERE is one error "Getfiles"
foreach (var file in Directory.GetFiles(folderName))
{
startupinfo.Items.Add(file.Name); // here is another error "Name"
}
}
This line won't work because folderName is a string (and does not have a GetFiles method):
FileInfo[] Files = folderName.GetFiles("*.txt");
The second error is occurring because the file variable is a string containing the filename. You don't need to call file.Name, just try the following:
startupinfo.Items.Add(file);
I don't think you need the following line:
FileInfo[] Files = folderName.GetFiles("*.txt");
The foreach loop will generate what you need.
Secondly, the file variable is a string, so rather than calling:
startupinfo.Items.Add(file.Name);
...call instead:
startupinfo.Items.Add(file);
Finally, instead of a var type for your loop, you can use a string, and you can specify the file type filter:
foreach (string fileName in Directory.GetFiles(folderName, "*.txt"))
The string object doesn't have a GetFiles() method. Try this:
string startfolder = Environment.GetFolderPath(Environment.SpecialFolder.Startup);
string[] files = Directory.GetFiles(startfolder, "*.txt");
foreach (string file in files)
{
startupinfo.Items.Add(Path.GetFileNameWithoutExtension(file));
}
Path.GetFileNameWithoutExtension(file) returns just the file name instead of full path.

Categories