I'm not sure what exactly i'm doing wrong here...but i noticed that my File.Move() isn't renaming any files.
Also, does anybody know how in my 2nd loop, i'd be able to populate my .txt file with a list of the path AND sanitized file name?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
//recurse through files. Let user press 'ok' to move onto next step
string[] files = Directory.GetFiles(#"C:\Documents and Settings\jane.doe\Desktop\~Test Folder for [SharePoint] %testing", "*.*", SearchOption.AllDirectories);
foreach (string file in files)
{
Console.Write(file + "\r\n");
}
Console.WriteLine("Press any key to continue...");
Console.ReadKey(true);
//End section
//Regex -- find invalid chars
string pattern = " *[\\~#%&*{}/<>?|\"-]+ *";
string replacement = " ";
Regex regEx = new Regex(pattern);
string[] fileDrive = Directory.GetFiles(#"C:\Documents and Settings\jane.doe\Desktop\~Test Folder for [SharePoint] %testing", "*.*", SearchOption.AllDirectories);
List<string> filePath = new List<string>();
//clean out file -- remove the path name so file name only shows
string result;
foreach(string fileNames in fileDrive)
{
result = Path.GetFileName(fileNames);
filePath.Add(result);
}
StreamWriter sw = new StreamWriter(#"C:\Documents and Settings\jane.doe\Desktop\~Test Folder for [SharePoint] %testing\File_Renames.txt");
//Sanitize and remove invalid chars
foreach(string Files2 in filePath)
{
try
{
string sanitized = regEx.Replace(Files2, replacement);
sw.Write(sanitized + "\r\n");
System.IO.File.Move(Files2, sanitized);
System.IO.File.Delete(Files2);
}
catch (Exception ex)
{
Console.Write(ex);
}
}
sw.Close();
}
}
}
I'm VERY new to C# and trying to write an app that recurses through a specific drive, finds invalid characters (as specified in the RegEx pattern), removes them from the filename and then write a .txt file that has the path name and the corrected filename.
Any ideas?
Your filepath list contains only the file names. You have removed the directory info from them in the call to Path.GetFileName(), so your File.Move is looking for the target file in the application's default directory, rather than its original location.
I think your code for saving the sanitized file names is correct though. You should use the using() construct around your StreamWriter though, as below, to ensure that the file is closed once you're done with it.
//clean out file -- remove the path name so file name only shows
string result;
foreach(string fileNames in fileDrive)
{
// result = Path.GetFileName(fileNames); // don't do this.
filePath.Add(fileNames);
}
using (StreamWriter sw = new StreamWriter(#"C:\Documents and Settings\jane.doe\Desktop\~Test Folder for [SharePoint] %testing\File_Renames.txt"))
{
//Sanitize and remove invalid chars
foreach(string Files2 in filePath)
{
try
{
string filenameOnly = Path.GetFileName(Files2);
string pathOnly = Path.GetDirectoryName(Files2);
string sanitizedFilename = regEx.Replace(filenameOnly, replacement);
string sanitized = Path.Combine(pathOnly, sanitizedFilename);
sw.Write(sanitized + "\r\n");
System.IO.File.Move(Files2, sanitized);
}
catch
{
}
}
}
Are any exceptions being thrown in the call to File.Move()? You have an empty catch block beneath it which will be stopping you from seeing them. Try removing the catch{} or putting some code in there to log any exceptions.
Try using File.AppendAllLines() (with a collection) or File.AppendAllText() (for each individually) instead of a stream. That will make things a little easier.
Also, I understand not wanting your application to bomb, but at the very least, while you're currently writing/debugging comment your try block out so that you can see the exceptions.
Probably not an answer, but perhaps a suggestion to help.
Related
I'm trying to read a folder and do a look at the file names. Using this code:
try
{
var folderPath = #"C:\Users\Gamer\source\repos\carValLocal\carValLocal\files\";
foreach (string file in Directory.EnumerateFiles(Path.GetFileName(folderPath)))
{
var ha = file;
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
Console.ReadLine();
}
Unfortunately, I'm getting the following error:
The path is not of a legal form
My original filepath:
var folderPath = #"C:\Users\Gamer\source\repos\carValLocal\carValLocal\files\";
To find the bad chars I wrote this bit of code:
string illegal = #"C:\Users\Gamer\source\repos\carValLocal\carValLocal\files\";
string invalid = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());
foreach (char c in invalid)
{
illegal = illegal.Replace(c.ToString(), "");
}
which came back with:
"CUsersGamersourcereposcarValLocalcarValLocalfiles"
Which clearly isn't a file name.
If I don't use the Path class, it still finds files. How can I make this work because everything I've tried (like removing illegal chars) just doesn't work.
Well, for given folder path
var folderPath = #"C:\Users\Gamer\source\repos\carValLocal\carValLocal\files\";
The existing call
Path.GetFileName(folderPath);
returns empty string: "" since
C:\Users\Gamer\source\repos\carValLocal\carValLocal\files\
\ /|
--------------------- directory ------------------------ file
if you want to look for files in C:\Users\Gamer\source\repos\carValLocal\carValLocal\files you can
use Path.GetDirectoryName:
foreach (string file in Directory.EnumerateFiles(Path.GetDirectoryName(folderPath)))
{
...
}
If you want some kind of path manipulation, try DirectoryInfo, e.g. let's have a look for files in
C:\Users\Gamer\source\repos\carValLocal\carValLocal
Code:
var folderPath = #"C:\Users\Gamer\source\repos\carValLocal\carValLocal\files\";
DirectoryInfo di = new DirectoryInfo(folderPath);
foreach (string file in Directory.EnumerateFiles(di.Parent.FullName)) {
...
}
I was wondering if someone could assist or point me in the right direction to move files where part of the filename needs to be matched to part of the foldername for example:
Moving filename Cust-10598.txt to a folder named John-Doe-10598 Is this possible?
I was able to create all the folders inside the root directory where all the files are contained, now I would like to sort them and put each of them inside the matching folder.
Any help or ideas are highly appreciated
Assuming you already have a list of probably folders using Directory.GetDirectores(),
var listOfFolders = Directory.GetDirectories(basePath);
You can find the associated Folder for given filename using following method.
string GetAssociatedDirectory(string fileName,IEnumerable<string> folderNames)
{
Regex regEx = new Regex(#"Cust-(?<Id>[\d]*)",RegexOptions.Compiled);
Match match = regEx.Match(fileName);
if (match.Success)
{
var customerId = match.Groups["Id"].Value;
if(folderNames.Any(folder=>folder.EndsWith($"-{customerId}")))
{
return folderNames.First(folder=>folder.EndsWith(customerId));
}
else
{
throw new Exception("Folder not found");
}
}
throw new Exception("Invalid File Name");
}
You can then use File.Move to copy the file to destination directory
You could simply Split() on '-' if it's that simple of naming convention.
class Program
{
static void Main(string[] args)
{
var file = "Cust-10598.txt";
var fileSplit = file.Split('-');
var sourceDir = #"C:\";
var destFolder = "{name of destination folder}-" + Path.GetFileNameWithoutExtension(fileSplit[1]);
var destPath = #"C:\newpath";
File.Move(Path.Combine(source, file), Path.Combine(destPath, destFolder, file));
}
}
While learning with books sometimes i copy some code from pdf, to test it.
This tiny exe was suppose to change ‘ ’ “ ” to ' or "
and it work fine, but only if tested *.cs file is opened manually before I debug my methods.
Otherwise it's not working. When code paste into concerned file directly, and closed, without opening once again The Replace method return "Unexpected character ?"
I dont understand the probleme, since File.ReadAllText already open and close the file.
using System;
using System.Collections.Generic;
using System.IO;
class Test
{
public static void Main()
{
string path = Directory.GetCurrentDirectory();
string[] csfiles = Directory.GetFiles(path, "*.cs");
foreach (var item in csfiles)
{
string text = File.ReadAllText(item);
text = text.Replace("‘", "\'")
.Replace("’", "\'")
.Replace("“", "\"")
.Replace("”", "\"");
File.WriteAllText(item, text);
}
}
}
Apparently File.ReadAllText(); does change encoding when opening.
My caracters (being in ASCII+ANSI) was ruined just when opened.
string text = File.ReadAllText(path, Encoding.Default); keeps original encoding when opening. Replace work fine on this, and so my exe.
:) Thank you for your help!
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
class Test
{
public static void Main()
{
string path = Directory.GetCurrentDirectory();
string[] csfiles = Directory.GetFiles(path, "*.cs");
foreach (var item in csfiles)
{
string text = File.ReadAllText(item, Encoding.Default);
string newtext = text.Replace("‘", "\'")
.Replace("’", "\'")
.Replace("“", "\"")
.Replace("”", "\"");
File.WriteAllText(item, newtext);
}
}
}
How to read an ANSI encoded file containing special characters
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);
}
}
}
I am having a problem writing the files in folders and subfolders .
For Example:- test is the main folder
1) C:\test\
and i want to read and write the subfolder files
2)C:\test\12-05-2011\12-05-2011.txt
3)C:\test\13-05-2011\13-05-2011.txt
4)C:\test\14-05-2011\14-05-2011.txt
My code is:
private void button1_Click(object sender, EventArgs e)
{
const string Path1 = #"C:\test";
DoOnSubfolders(Path1);
try
{
StreamReader reader1 = File.OpenText(Path1);
string str = reader1.ReadToEnd();
reader1.Close();
reader1.Dispose();
File.Delete(Path1);
string[] Strarray = str.Split(new char[] { Strings.ChrW(10) });
int abc = Strarray.Length - 2;
int xyz = 0;
while (xyz <= abc)
}
I am getting an error. The error is
Access to the path 'C:\test' is denied.
Can anyone say me what i need to change in this code?
At first you could flatten your recursive calls by calling DirectoryInfo.GetFiles(string, SearchOption) and setting the SearchOption to AllDirectories.
What's also a common mistake (but not clear from your question) is that a directory needs to be created, before you can create a file. Simply call Directory.CreateDirectory(). And put in the complete path (without filename) into it. It will automatically do nothing if the directory already exists and is also able to create the whole needed structure. So no checks or recursive calls are needed (maybe a try-catch if you don't have write access).
Update
So here is an example that reads in a file, does some conversion on each line and writes the result into a new file. If this works properly the original file will be replaced by the converted one.
private static void ConvertFiles(string pathToSearchRecursive, string searchPattern)
{
var dir = new DirectoryInfo(pathToSearchRecursive);
if (!dir.Exists)
{
throw new ArgumentException("Directory doesn't exists: " + dir.ToString());
}
if (String.IsNullOrEmpty(searchPattern))
{
throw new ArgumentNullException("searchPattern");
}
foreach (var file in dir.GetFiles(searchPattern, SearchOption.AllDirectories))
{
var tempFile = Path.GetTempFileName();
// Use the using statement to make sure file is closed at the end or on error.
using (var reader = file.OpenText())
using (var writer = new StreamWriter(tempFile))
{
string line;
while (null != (line = reader.ReadLine()))
{
var split = line.Split((char)10);
foreach (var item in split)
{
writer.WriteLine(item);
}
}
}
// Replace the original file be the converted one (if needed)
////File.Copy(tempFile, file.FullName, true);
}
}
In your case you could call this function
ConvertFiles(#"D:\test", "*.*")
To recursively walk the sub-folders, you need a recursive function ie. One that calls itself. here is an example that should be enough for you to work with:
static void Main(string[] args)
{
const string path = #"C:\temp\";
DoOnSubfolders(path);
}
private static void DoOnSubfolders(string rootPath)
{
DirectoryInfo d = new DirectoryInfo(rootPath);
FileInfo[] fis = d.GetFiles();
foreach (var fi in fis)
{
string str = File.ReadAllText(fi.FullName);
//do your stuff
}
DirectoryInfo[] ds = d.GetDirectories();
foreach (var info in ds)
{
DoOnSubfolders(info.FullName);
}
}
You need use class Directory info and FileInfo.
DirectoryInfo d = new DirectoryInfo("c:\\test");
FileInfo [] fis = d.GetFiles();
DirectoryInfo [] ds = d.GetDirectories();
Here's a quick one liner to write the contents of all text files in a given directory (and all subdirectories) to the console:
Directory.GetFiles(myDirectory,"*.txt*",SearchOption.AllDirectories)
.ToList()
.ForEach(a => Console.WriteLine(File.ReadAllText(a)));
This code:
const string Path1 = #"C:\test";
StreamReader reader1 = File.OpenText(Path1);
Says open "c:\test" as a text file... The error you're getting is:
Access to the path 'C:\test' is denied
You're getting the error because as you stated above, 'c:\test' is a folder. You can't open folders like they are text files, hence the error...
A basic (full depth search) for files with a .txt extension looks like this:
static void Main(string[] args) {
ProcessDir(#"c:\test");
}
static void ProcessDir(string currentPath) {
foreach (var file in Directory.GetFiles(currentPath, "*.txt")) {
// Process each file (replace this with your code / function call /
// change signature to allow a delegate to be passed in... etc
// StreamReader reader1 = File.OpenText(file); // etc
Console.WriteLine("File: {0}", file);
}
// recurse (may not be necessary), call each subfolder to see
// if there's more hiding below
foreach (var subFolder in Directory.GetDirectories(currentPath)) {
ProcessDir(subFolder);
}
}
Have a look at http://support.microsoft.com/kb/303974 for a start. The secret is Directory.GetDirectories in System.IO.
You have to configure (NTFS) security on the c:\Test folder.
Normally you would have the application run under non-admininstrator account so the account that is running the program should have access.
If you are running on Vista or Windows 7 with UAC, you might be an administrator but you will not be using the administrative (elevated) permissions by default.
EDIT
Look at these lines:
const string Path1 = #"C:\test";
DoOnSubfolders(Path1);
try
{
StreamReader reader1 = File.OpenText(Path1);
That last line is trying to read the FOLDER 'c:\test' as if it was a text file.
You can't do that. What are you trying to accomplish there?