How to remove guid from file name when creating zip file? - c#

When user uploads multiple documents I am storing their files in my project like this:
Guid id;
id = Guid.NewGuid();
string filePath = Path.Combine(HttpContext.Server.MapPath("../Uploads"),
Path.GetFileName(id + item.FileName));
item.SaveAs(filePath);
So files are saved like this in my project:
1250a2d5-cd40-4bcc-a979-9d6f2cd62b9fLog.txt
bdb31966-e3c4-4344-b02c-305c0eb0fa0aLogging.txt
Now when creating zip files I am getting same name of this files when extracting zip files but I don't want guid in my file name after user downloads file.
However I have tried to remove guid from my file name but getting error System.IO.FileNotFoundException.
This is my code:
using (var zip = new ZipFile())
{
var str = new string[] { "1250a2d5-cd40-4bcc-a979-9d6f2cd62b9fLog.txt", "bdb31966-e3c4-4344-b02c-305c0eb0fa0aLogging.txt" }; //file name are Log.txt and Logging.txt
string[] str1 = str .Split(',');
foreach (var item in str1)
{
string filePath = Server.MapPath("~/Uploads/" + item.Substring(36));//as guid are of 36 digits
zip.AddFile(filePath, "files");
}
zip.Save(memoryStream);//Getting error here
}

ZipFile is throwing an exception because it can't find the file on disk as you have given it a name of a file that does not exist (by doing a .Substring()). To make it work you would have to rename the file using File.Copy with your new file name and then give that same file name to Zip.AddFile().
var orgFileName = "1250a2d5-cd40-4bcc-a979-9d6f2cd62b9fLog.txt";
var newFileName = orgFileName.Substring (36);
File.Copy (orgFileName, newFileName, true);
zip.AddFile (newFileName);

You should use archive and ArchiveEntry. The rough code snipets how to do it (i don't test it):
using(var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true)) {
{
//using(var zip = new ZipFile()) {
var str = new string[] { "1250a2d5-cd40-4bcc-a979-9d6f2cd62b9fLog.txt", "bdb31966-e3c4-4344-b02c-305c0eb0fa0aLogging.txt" }; //file name are Log.txt and Logging.txt
//string[] str = str.Split(',');
foreach(var item in str) {
using(var entryStream = archive.CreateEntry("files/" + item.Substring(36)).Open()) {
string filePath = Server.MapPath("~/Uploads/" + item);
var content = File.ReadAllBytes(filePath);
entryStream.Write(content, 0, content.Length);
}
}
}
}
sample for using DotNetZip:
using (ZipFile zip = new ZipFile())
{
var str = new string[] { "1250a2d5-cd40-4bcc-a979-9d6f2cd62b9fLog.txt", "bdb31966-e3c4-4344-b02c-305c0eb0fa0aLogging.txt" };
foreach(var item in str) {
string filePath = Server.MapPath("~/Uploads/" + item);
var content = File.ReadAllLines(filePath);
ZipEntry e = zip.AddEntry("files/" + item.Substring(36), content);
}
}
zip.Save(memoryStream);
}

Taking source from #kevin answer i have manage to solve this:
List<string> newfilename1 = new List<string>();
using (var zip = new ZipFile())
{
var str = new string[] { "1250a2d5-cd40-4bcc-a979-9d6f2cd62b9fLog.txt", "bdb31966-e3c4-4344-b02c-305c0eb0fa0aLogging.txt" }; //file name are Log.txt and Logging.txt
string[] str1 = str .Split(',');
foreach (var item in str1)
{
string filePath = Server.MapPath("~/Uploads/" + item);
string newFileName = Server.MapPath("~/Uploads/" + item.Substring(36));
newfilename1.Add(newFileName);
System.IO.File.Copy(filePath,newFileName);
zip.AddFile(newFileName,"");
}
zip.Save(memoryStream);
foreach (var item in newfilename1)
{
System.IO.File.Delete(item);
}
}

Related

Best way to return zip file built on the fly using ASP.NET MVC action without delay

I'm creating zip archive using selected file pattern and need to have a fast method that can return it async when it is being built.
public async Task<FileStreamResult> DownloadStudy(long studyId, string Pattern= "*_70_0_70_0.dcm")
{
var FilePaths = System.IO.Directory.EnumerateFiles(studyDir, Pattern, SearchOption.AllDirectories);
var dir = new DirectoryInfo(studyDir);
var fName = dir.Name + ".zip";
var zipPath = Path.Combine(dir.Parent.FullName, fName);
var zipFileMemoryStream = new FileStream(zipPath,FileMode.Create);
using (ZipArchive archive = new ZipArchive(zipFileMemoryStream, ZipArchiveMode.Update, leaveOpen: true))
{
foreach (var filePath in FilePaths)
{
var filename = Path.GetFileName(filePath);
var pdir = Path.GetFileName(Path.GetDirectoryName(filePath));
archive.CreateEntryFromFile(filePath, pdir + "/" + filename);
}
}
zipFileMemoryStream.Seek(0, SeekOrigin.Begin);
return new FileStreamResult(zipFileMemoryStream, "application/octet-stream") { FileDownloadName = studyId.ToString() + ".zip" };
}
Is there a better way to have the download starts once the action is called and while the zip archive is being built?

Delete specific line from a text file which i don't have the name

i need to find and delete all lines wich contain the word "recto",
i did search in stackoverflow forum, but all what i found is do that (delete the line) using path (Directory & FileName).
in my case i want to delete the line contain "recto" in all fils with specific extention (*.txt) in the directory.
thanks for help
here is my code so far
string sourceDir = #"C:\SRCE\";
string destinDir = #"C:\DIST\";
string[] files = Directory.GetFiles(sourceDir);
foreach (string file in files)
{
using (StreamReader sr_ = new StreamReader
(sourceDir + Path.GetFileName(file)))
{
string line = sr_.ReadLine();
if (line.Contains("recto"))
{
File.Copy(file, destinDir + Path.GetFileName(file));
string holdName = sourceDir + Path.GetFileName(file);
}
sr_.DiscardBufferedData();
sr_.Close();
}
}
}
You can try something like this. You were only identifying the files with the word but not making any try to remove it. At the end, you were copying the files that included the word "recto"
string sourceDir = #"C:\SRCE\";
string destinDir = #"C:\DIST\";
string[] files = Directory.GetFiles(sourceDir);
foreach (string file in files)
{
using (StreamReader sr_ = new StreamReader
(sourceDir + Path.GetFileName(file)))
{
string res = string.Empty;
while(!sr_.EndOfStream)
{
var l = sr_.ReadLine();
if (l.Contains("recto"))
{
continue;
}
res += l + Environment.NewLine;
}
var streamWriter = File.CreateText(destinDir + Path.GetFileName(file));
streamWriter.Write(res);
streamWriter.Flush();
streamWriter.Close();
}
}
If the files are not really big you can simplify a lot your code reading all lines in memory, processing the lines with Linq and then rewriting the files
string sourceDir = #"C:\SRCE\";
string destinDir = #"C:\DIST\";
string[] files = Directory.GetFiles(sourceDir);
foreach (string file in files)
{
var lines = File.ReadLines(file);
var result = lines.Where(x => x != "recto").ToArray();
File.WriteAllLines(Path.Combine(destinDir, Path.GetFileName(file)), result);
}

Get files from a folder that I have created in Xamarin.Android

I want get all files from an external storage folder(wall_e_imgs)..Here are codes-
public void getImages()
{
var path1 = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath.ToString();
string path = System.IO.Path.Combine(path1, "wall_e_imgs");
//var files= System.IO.Directory.GetFiles(Android.OS.Environment.ExternalStorageDirectory.ToString() + "wall_e_imgs");
//var files = System.IO.Directory.GetFiles(path);
//string path = Android.OS.Environment.ExternalStorageDirectory.ToString() + "/wall_e_imgs";
//File directory=new File(path);
Java.IO.File directory = new Java.IO.File(path);
Java.IO.File[] files = directory.ListFiles();//always count is 0 even though there are lot files there
foreach (var i in files)
{
FileInfo info = new FileInfo(i.Name);
if (info.Name.Contains("Wall_e"))
{
di.Add(new DownloadedImages { Path1 = info.DirectoryName, Name1 = info.FullName });
}
}
}
But it always give 0 files even though there are lot of files.
Try this
var folder = Android.OS.Environment.ExternalStorageDirectory + Java.IO.File.Separator + "yourfoldername";
if (!Directory.Exists(folder))
Directory.CreateDirectory(folder);
var filesList = Directory.GetFiles(folder);
foreach (var file in filesList)
{
var filename = Path.GetFileName(file);
}
Try something like this:
// Use whatever folder path you want here, the special folder is just an example
string folderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "wall_e_imgs");
if (Directory.Exists(folderPath))
{
var files = Directory.EnumerateFiles(folderPath);
foreach (var file in files)
{
// Do your stuff
}
}
Please note that this uses the Directory class from System.IO, not Java.IO
ffilelist will contain a list of mp3 files in "/storage/emulated/0/Music/"
string phyle;
string ffilelist = "";
public void listfiles()
{
try
{
var path1 = "/storage/emulated/0/Music/";
var mp3Files = Directory.EnumerateFiles(path1, "*.mp3", SearchOption.AllDirectories);
foreach (string currentFile in mp3Files)
{
phyle = currentFile;
ffilelist = ffilelist + "\n" + phyle;
}
//playpath(phyle); // play the last file found
}
catch (Exception e9)
{
Toast.MakeText(ApplicationContext, "ut oh\n"+e9.Message , ToastLength.Long).Show();
}
}

Reading, Manipulating, and Writing text files C#

I need to convert any flat delimited file into a pipe delimited format. I wrote this console app as a POC but the second file it tries to write will include the all of the text from the first file. Any suggestions?
string sourceDir = #"c:\temp\";
string targetDir = #"c:\dest\";
List<string> listLines = new List<string>();
string[] files = Directory.GetFiles(sourceDir);
foreach(string file in files)
{
using (StreamReader sr = new StreamReader(sourceDir + Path.GetFileName(file)))
{
do
{
listLines.Add(sr.ReadLine());
} while (!sr.EndOfStream);
for (int i = 0; i < listLines.Count; i++)
{
listLines[i] = listLines[i].Replace(',', '|');
listLines[i] = listLines[i].Replace('\t', '|');
}
}
using (StreamWriter sw = new StreamWriter(targetDir + Path.GetFileName(file)))
{
foreach (string line in listLines)
{
sw.WriteLine(line);
}
}
}
You need to either move the instantiation of listLines into the foreach, or re-initialize the list at the end of the loop.
string sourceDir = #"c:\temp\";
string targetDir = #"c:\dest\";
string[] files = Directory.GetFiles(sourceDir);
foreach(string file in files)
{
List<string> listLines = new List<string>();
using (StreamReader sr = new StreamReader(sourceDir + Path.GetFileName(file)))
{
do
{
listLines.Add(sr.ReadLine());
} while (!sr.EndOfStream);
for (int i = 0; i < listLines.Count; i++)
{
listLines[i] = listLines[i].Replace(',', '|');
listLines[i] = listLines[i].Replace('\t', '|');
}
}
using (StreamWriter sw = new StreamWriter(targetDir + Path.GetFileName(file)))
{
foreach (string line in listLines)
{
sw.WriteLine(line);
}
}
}
You're adding lines to listLines and never clearing the list after the foreach iteration.
by #Jonathan Carroll
Beside that, you can improve your code to this:
string sourceDir = #"c:\temp\";
string targetDir = #"c:\dest\";
List<string> listLines = new List<string>();
string[] files = Directory.GetFiles(sourceDir);
foreach (string file in files)
{
using (StreamReader sr = new StreamReader(sourceDir + Path.GetFileName(file)))
using (StreamWriter sw = new StreamWriter(targetDir + Path.GetFileName(file)))
{
do
{
var line = sr.ReadLine();
line = line.Replace(',', '|').Replace('\t', '|');
sw.WriteLine(line);
} while (!sr.EndOfStream);
}
}
I'd argue that the other answers are considerably clearer, but just thought I'd throw in a short alternative solution using LINQ and Regex:
foreach (var file in Directory.GetFiles(sourceDir).Select(x => Path.GetFileName(x)))
File.WriteAllText(targetDir + file, new Regex("[,\t]").Replace(File.ReadAllText(sourceDir + file), "|"));
The LINQ select query is used to transform the full paths into file names - this collection of file names is then iterated over.
Regex is used to match all ',' and '\t' characters that are read from the source file and replace them with the '|' character. This resulting string is then written to the target file.

How do I delete the files in a directory after I have converted them from XML to Txt using a Visual C# console application?

I am creating a Visual C# application to covert xml files to x12 edi txt files. I would like to delete all the files in the xml directory after I have created their txt equivalents. I have tried adding a foreach method with file.delete, but cannot get it to work. When I place it within the main method, I am told the file is in use. When I place it outside of the main method, it is not executed at all. Below is the code for my application with the file.delete at the end, outside of the main method and class.
namespace XMLParse
{
class Class1
{
public static void Main()
{
string[] Files = Directory.GetFiles(#"C:\onlinesales");
foreach (string filename in Files)
{
StringBuilder orderid = new StringBuilder();
StringBuilder ordernumber = new StringBuilder();
StringBuilder name = new StringBuilder();
StringBuilder staddress = new StringBuilder();
StringBuilder city = new StringBuilder();
StringBuilder state = new StringBuilder();
StringBuilder zip = new StringBuilder();
StringBuilder country = new StringBuilder();
StringBuilder email = new StringBuilder();
StringBuilder partnumber = new StringBuilder();
StringBuilder quantity = new StringBuilder();
using (XmlReader reader = XmlReader.Create(new StreamReader(filename)))
{
reader.ReadToFollowing("OrderID");
orderid.Append(reader.ReadElementContentAsString());
reader.ReadToFollowing("OrderNumber");
ordernumber.Append(reader.ReadElementContentAsString());
reader.ReadToFollowing("Name");
name.Append(reader.ReadElementContentAsString());
reader.ReadToFollowing("Line1");
staddress.Append(reader.ReadElementContentAsString());
reader.ReadToFollowing("City");
city.Append(reader.ReadElementContentAsString());
reader.ReadToFollowing("StateProvinceCode");
state.Append(reader.ReadElementContentAsString());
reader.ReadToFollowing("PostalCode");
zip.Append(reader.ReadElementContentAsString());
reader.ReadToFollowing("CountryCode");
country.Append(reader.ReadElementContentAsString());
reader.ReadToFollowing("Email");
email.Append(reader.ReadElementContentAsString());
reader.ReadToFollowing("ProductSKU");
partnumber.Append(reader.ReadElementContentAsString());
reader.ReadToFollowing("Quantity");
quantity.Append(reader.ReadElementContentAsString());
}
using (StreamWriter fileout =
new StreamWriter("W:" + DateTime.Now.ToString("yyyyy-MM-dd_hh-mm-ss-ff") + ".txt", false, Encoding.ASCII))
{
fileout.WriteLine("ISA*00* *00* *ZZ*daisywebstore *12*5016361200 *" + DateTime.Now.ToString("yyMMdd") + "*1559*U*00400*000001649*0*P>~");
fileout.WriteLine("GS*PO*daisywebstore*5016361200*" + DateTime.Now.ToString("yyyyMMdd") + "*" + DateTime.Now.ToString("HHmm") + "*1649*X*004010~");
fileout.WriteLine("ST*850*13~");
fileout.WriteLine("BEG*00*SA*08272226001*" + DateTime.Now.ToString("yyyyMMdd") + "~");
fileout.WriteLine("REF*DP*089~");
fileout.WriteLine("DTM*002*20120104~");
fileout.WriteLine("N1*ST*" + name + "~");
fileout.WriteLine("N3*" + staddress + "~");
fileout.WriteLine("N4*" + city + "*" + state + "*" + zip + "~");
fileout.WriteLine("N1*RE**92*00103653341~");
fileout.WriteLine("PO1*1*6*EA*33.28*TE*IN*985880-542~");
fileout.WriteLine("PID*F*****CO2 BB PISTOL $ 5693~");
fileout.WriteLine("PO4*3*1*EA~");
fileout.WriteLine("CT*1~");
fileout.WriteLine("AMT*1*199.68~");
fileout.WriteLine("SE*16*13~");
}
}
}
}
}
public class Delete
{
private static void Empty()
{
string[] files = Directory.GetFiles(#"C:\onlinesales");
foreach (string filename in files)
File.Delete(filename);
}
}
You are closing the XMLReader through using but the StreamReader is still open which is causing this error
try this
foreach (string filename in Files)
{
StreamReader read = new StreamReader(filename);
using (XmlReader reader = XmlReader.Create(read))
{
}
read.Close();
}
or
foreach (string filename in Files)
{
using (StreamReader read = new StreamReader(filename))
{
using (XmlReader reader = XmlReader.Create(read))
{
}
}
}
Try this overload of the StreamReader constructor instead:
new StreamReader(File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Delete))
wrap the new streameader(filename) in a using statement as well. assuming the files are saved to another directory; just delete the directory
Directory.Delete(#"C:\onlinesales", true);
namespace XMLParse
{
class Class1
{
public static void Main()
{
string[] Files = Directory.GetFiles(#"C:\onlinesales");
foreach (string filename in Files)
{
//...YOUR CODE
}
//....ADD THIS LINE
Array.ForEach(Directory.GetFiles(#"c:\onlinesales\", "*.xml"),
delegate(string path) { File.Delete(path); });
}
}
}

Categories