I'm fairly new to C# and what I'm trying to do is
Search for a file
List all matching files into a listbox
Copy the whole folder where the file is located to another place
I found bits and pieces on the web that I'm using. Right now it's only the btn_search_Click part that is working.
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btn_search_Click(object sender, EventArgs e)
{
try
{
listBox1.Items.Clear();
//Directory to search in
DirectoryInfo Di = new DirectoryInfo(#"D:\xxxx\Versionen");
FileInfo[] nPfad = Di.GetFiles(textBox1.Text, SearchOption.AllDirectories);
Int32 nLengePfad = nPfad.GetLength(0);
listBox1.Items.AddRange(nPfad);
}
catch (Exception)
{
MessageBox.Show("File not found");
}
}
private void btn_save_Click(object sender, EventArgs e)
{
{
string sourceFile = #"D:\Users\Public\public\test.txt";
string destinationFile = #"D:\Users\Public\private\test.txt";
// To move a file or folder to a new location:
System.IO.File.Move(sourceFile, destinationFile);
// To move an entire directory. To programmatically modify or combine
// path strings, use the System.IO.Path class.
System.IO.Directory.Move(#"C:\Users\Public\public\test\", #"C:\Users\Public\private");
}
}
}
}
My question now is, what would the code look like, if I want to select a file from the listbox and copy NOT the file but the folder it's located in to another place. I already have set a btn_save and a basic code to move files, but I need someone to show me a way to copy any selected file from the listbox or rather copy the folder of the selected file.
I'm fairly new to C# and am open for new approaches. If I'm completely wrong with the code, scratch it, show me a correct or easier way to achieve the same
You can move directly the directory with Directory.Move.
Using the FileInfo.DirectoryName you can get the Directory path from the FileInfo[] SelectedItems.
var itemsToMove = myListBox.SelectedItems.Cast<FileInfo>();
var directoriesTheyAreIn = itemsToMove.Select(x => x.DirectoryName);
var cleanDirectoriesList = directoriesTheyAreIn.Distinct();
//As many file can be in the same Dir we only need to move the dire once to move those file.
But what if Dir contains both selected and unselected files? Here I will move them all.
foreach (var path in cleanDirectoriesList)
{
// here you have to craft your destination directory
string destinationDirectory = "";
Directory.Move(path, destinationDirectory);
}
From your question it's unclear what part of the old path should be keep in the new path. but if it's based on your "D:\xxxx\Versionen" string you can simply replace this part with the new root path "NewRoot\foo\bar":
string destinationDirectory = path.Replace(#"D:\xxxx\Versionen", #"G:\FooBAR\NEWPATH\");
If you need to move only the selected file you can blindly call Directory.CreateDirectory before copying each file, as it won't throw error if the directory already exist. Grouping on directory to avoid useless instruction could have been possible but I feel like it won't be that easy to modify. Here the code will simply be: create the directory then move the file.
foreach (var item in itemsToMove) {
string destinationDirectory = #"BasedPath\" + " Craft it ";
Directory.CreateDirectory(destinationDirectory);
File.Move(item.FullName, destinationDirectory + item.Name);
}
Store the list of files into a List<FileInfo> and iterate through with foreach. This worked for me:
string destination = #"C:\Some\Destination\";
string actualFile = string.Empty;
foreach (var file in fileList)
{
actualFile = file.FullName;
File.Copy(actualFile, destination + Path.GetFileName(actualFile));
}
Related
I'm attempting to zip up a handful of files but these files could exist in different directories. The zipping portion is working correctly but I cannot figure out how to get it to preserve the directory structure within the zip file.
Here's what I have so far:
public static void CreateZipFile(IEnumerable<FileInfo> files, string archiveName)
{
using (var stream = File.OpenWrite(archiveName))
using (var archive = new ZipArchive(stream, ZipArchiveMode.Create))
{
foreach (var item in files)
{
archive.CreateEntryFromFile(item.FullName, item.Name, CompressionLevel.Optimal);
}
}
}
Is this possible?
#ErocM the link provided by #Flydog57 gives you exactly what you want. You are not exploiting the entryName argument correctly (the second argument in your case when calling CreateEntryFromFile).
Independently of which file you are adding to the archive (from same of different folders), you have to structure your archive using the entryName argument the C# api gives to you.
If your file's fullname is /tmp/myfile.txt, and you do archive.CreateEntryFromFile(item.FullName, item.Name), then the archive entry name will be myfile.txt. No folder created as the entry name doesn't contain folder structure in it's name.
However, if you call archive.CreateEntryFromFile(item.FullName, item.FullName), you will then have you file folder structure into the archive.
You can try with your function just changing item.Name into item.FullName.
Just be careful, on windows; if you path is C:\tmp\myfile.txt for instance, the archive will not be extractable correctly. You can then add some little code to remove C: from the full name of your files.
Some examples taking your implementation:
using System;
using System.IO;
using System.Collections.Generic;
using System.IO.Compression;
namespace ConsoleApp
{
internal class Program
{
static void Main(string[] args)
{
FileInfo f1 = new FileInfo(#"/tmp/test1.txt");
FileInfo f2 = new FileInfo(#"/tmp/testdir/test2.txt");
List<FileInfo> files = new();
files.Add(f1);
files.Add(f2);
CreateZipFile(files, #"/tmp/archive.zip");
}
public static void CreateZipFile(IEnumerable<FileInfo> files, string archiveName)
{
using (var stream = File.OpenWrite(archiveName))
using (var archive = new ZipArchive(stream, ZipArchiveMode.Create))
{
foreach (var item in files)
{
// Here for instance, I put all files in the input list in the same directory, without checking from where they are in the host file system.
archive.CreateEntryFromFile(item.FullName, $"mydir/{item.Name}", CompressionLevel.Optimal);
// Here, I am just using the actual full path of the file. Be careful on windows with the disk name prefix (C:, D:, etc...).
// archive.CreateEntryFromFile(item.FullName, item.FullName, CompressionLevel.Optimal);
}
}
}
}
I am new in WinForms technology. I am using .NET Framework 4.8 , Microsoft Visual Studio 2019. I put file in Resources folder.
I tried something like this
using DevExpress.XtraBars;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace accwf
{
public partial class NhapSoDu : DevExpress.XtraBars.Ribbon.RibbonForm
{
public NhapSoDu()
{
InitializeComponent();
}
private void simpleButton1_Click(object sender, EventArgs e)
{
Console.WriteLine(System.AppDomain.CurrentDomain.BaseDirectory);
Process.Start(".../B01-DN_01_Summary.xlsx");
}
}
}
please guide me finish it.
I do this in one of my applications to open a XLSX file that is an embedded resource in my application
private void buttonOpenTemplate_Click(object sender, EventArgs e)
{
byte[] templateFile = Properties.Resources._01__So_du_tai_khoan; // This is your Excel document in the application Resources
string tempPath = $"{Path.GetTempFileName()}.xlsx";
using (MemoryStream ms = new MemoryStream(templateFile))
{
using(FileStream fs = new FileStream(tempPath, FileMode.OpenOrCreate))
{
ms.WriteTo(fs);
fs.Close();
}
ms.Close();
}
Process.Start(tempPath);
}
This requires a reference to System.IO for access to the MemoryStream and FileStream classes.
You are currently only outputting the base directory. Along with that, you're only looking for files within that base directory. Execution happens from the base directory, so your program is looking for ..\Path\to\exe\B01-DN_01_Summary.xlsx when it should be looking for ..\Path\to\exe\Resources\FilesHere\ImportExcel\B01-DN_01_Summary.xlsx
To note: embedding resources files into your application is not recommend. It's preferable to instead store their locations and allow the application to traverse your directories to find the specified file locations.
Here's an adapted version you can try:
You will need to make sure that the Copy to Output Directory property for you desire file is set to "Copy Always" or "Copy if Newer". This will ensure the directory path is created in your output directory.
namespace accwf
{
public partial class NhapSoDu : DevExpress.XtraBars.Ribbon.RibbonForm
{
public NhapSoDu()
{
InitializeComponent();
}
private void simpleButton1_Click(object sender, EventArgs e)
{
string resourcePath = System.IO.File.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Resources\\FilesHere\\ImportExcel\\B01-DN_01_Summary.xlsx")
if (File.Exists(resourcePath))
{
MessageBox.Show("Exists");
}
else
{
MessageBox.Show("Doesn't Exist");
}
Process.Start(resourcePath);
}
}
}
This is an example of how I get PDF file documentation for a help menu I have:
public void MyMethod()
{
// helpMenuPath is a global var set to something like: Area/MyApp/Resources/
string filePath = helpMenuPath;
string[] fileNames = new string[0]; // Initialize the variable with length of 0. Directory.GetFiles() will allow for this length to be overwritten
// Try/Catch in case bad dir
try
{
fileNames = Directory.GetFiles(filePath);
}
catch (IOException ioe)
{
// error catch for if bad dir
MessageBox.Show($"Error in getting files: {ioe.Message}");
}
// Do something with files ...
}
The product I'm using is a Beijer HMI, currently i can generate a report and save it to a known location (my desktop - C:\Users\mrdav\Desktop).
I need to be able to search on my desktop for a file extension .xls and change its name.
When the report is generated by the HMI, it uses the date and time which means when the file is generated the name will be different every time.
On the press of a button i need to search my desktop for the .xls file and change its name to a variable.
// This is my variable with my program
string NewName = Globals.Tags.Tag1.Value;
The code that is generated needs to sit within the below example.
public partial class Screen1
{
void Button1_Click(System.Object sender, System.EventArgs e)
{
// Code to be added here...
}
}
Hopefully someone can help, I’m using windows compact framework so limited on functionality.
Any questions please let me know.
Thanks in advance,
Dave
Here is an example how you can do that:
DirectoryInfo dir = new DirectoryInfo(sExportPath);
FileInfo[] Files = dir.GetFiles("*.csv");
foreach(FileInfo file in Files )
{
// rename file
System.IO.File.Move(file.FullName, GenerateNewFileName());
}
//elsewhere in the class
private string GenerateNewFileName()
{
//here is where you implement creating or getting the filename that you want your file to be renamed to. An example might look like the below
string serialNumber = GetSerialNumber(); //Get the serial number that you talked about in the question. I've made it a string, but it could be an int (it should be a string)
return Path.ChangeExtension(serialNumber,".xls"); //to use path you will need a using statement at the top of your class file 'using System.IO'
}
This seems to work...but i know its not as tidy as it could be.
Any suggestions?
Thanks to all that helped, got there in the end!
void Button_Click(System.Object sender, System.EventArgs e)
{
try
{
// Location for new file
string NewFileName = #"c:\users\mrdav\desktop\testfolder\";
// Add varibale name to new file
NewFileName += Globals.Tags.Tag1.Value;
// add .xls extention to new file
NewFileName += ".xls";
//show new file name to check all ok
MessageBox.Show (NewFileName);
//search for .xls in known directory
DirectoryInfo di = new DirectoryInfo(#"c:\users\mrdav\desktop");
FileInfo[] Files = di.GetFiles("*.xls");
// if files exist with .xls extention
foreach(FileInfo file in Files )
{
// show full file name
MessageBox.Show (file.FullName);
//rename old file to new file name and move to new folder
File.Move(file.FullName, NewFileName);
}
}
catch (Exception ex)
{
MessageBox.Show (ex.ToString());
}
}
Finally got my code working fine, but I need to extract the most recent zipped file within the directory.
Really not sure how to go about this, can someone please point me in the correct direction, was thinking of using modified date and time, please see my code below...
using System;
using System.IO;
using System.IO.Compression;
namespace unZipMe
{
class Program
{
static void Main(string[] args)
{
DirectoryInfo file = new DirectoryInfo(#"c:\Temp\ZipSampleExtract");
if(file.Exists)
{
file.Delete(true);
}
string myDir = (#"c:\Temp\ZipSampleExtract");
bool exists = System.IO.Directory.Exists(myDir);
if (!exists)
{
System.IO.Directory.CreateDirectory(myDir);
}
//provide the folder to be zipped
//string folderToZip = #"c:\Temp\ZipSample";
//provide the path and name for the zip file to create
string zipFile = #"c:\Temp\ZipSampleOutput\MyZippedDocuments.zip";
//call the ZipFile.CreateFromDirectory() method
//ZipFile.CreateFromDirectory(folderToZip, zipFile, CompressionLevel.Optimal, false);
//specif the directory to which to extract the zip file
string extractFolder = #"c:\Temp\ZipSampleExtract\";
//call the ZipFile.ExtractToDirectory() method
ZipFile.ExtractToDirectory(zipFile, extractFolder);
}
}
}
In my application there is a situation like this.Before creating a file, my application search for files in a directory under a particular filename. If any file/files found, then it should read each files contents and write these contents(of each file) to a new file. I have googled many and tried some like this:
string temp_file_format = "ScriptLog_" + DateTime.Now.ToString("dd_MM_yyyy_HH");
string[] files = Directory.GetFiles(path,temp_file_format);
foreach (FileAccess finfo in files)
{
string text = File.ReadAllText(finfo);
}
and
System.IO.DirectoryInfo dir = new DirectoryInfo(path);
System.IO.FileInfo[] files = dir.GetFiles(temp_file_format);
foreach (FileInfo finfo in files)
{
finfo.OpenRead();
}
But all these failed..Can anyone show me an alternative for this?
Is there anything wrong in my temp_file_format string?
It will be nice if I could prepend these contents to the new file. Else also, no worries..
any help would be really appreciated..
This is a compete working implementation that does all of that
without reading everything in memory at one time (which doesn't work for large files)
without keeping any files open for more than the required time
using System.IO;
using System.Linq;
public static class Program {
public static void Main()
{
var all = Directory.GetFiles("/tmp", "*.cpp")
.SelectMany(File.ReadAllLines);
using (var w = new StreamWriter("/tmp/output.txt"))
foreach(var line in all)
w.WriteLine(line);
}
}
I tested it on mono 2.10, and it should work on any .NET 4.0+ (for File.ReadAllLines which is a lazy linewise enumerable)
Here's a short snippet that reads all the files and out puts them to the path outputPath
var lines = from file in Directory.GetFiles(path,temp_file_format)
from line in File.ReadAllLines(file)
select line;
File.WriteAllLines(outputPath, content);
The problem you are having with your code is not really related to reading files but simply trying to use an object as a type it's not. Directory.GetFiles returns an array of string and File.ReadXXX and File.OpenRead expects the path as a string. So you simply need to pass each of the strings returned as the path argument to the appropriate method. The above is one such example. Hope it helps both solve your problem and explain the actually issue with your code
try this:
foreach (FileInfo finfo in files)
{
try
{
using (StreamReader sr = new StreamReader("finfo "))
{
String line = sr.ReadToEnd();
Console.WriteLine(line);
}
}
catch (Exception e)
{
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
}
using (var output = File.Create(outputPath))
{
foreach (var file in Directory.GetFiles(InputPath,temp_file_format))
{
using (var input = File.OpenRead(file))
{
input.CopyTo(output);
}
}
}