Is it possible to read files from a directory one file after another?
I look for something like:
while (File file = Directory.GetFile(path)) {
//
// Do something with file
//
}
[UPDATE]
I already knew about GetFiles() but I'm looking for a function that return one file at a time.
EnumerateFiles() is .Net4.x, would be nice to have, but I'm using .Net2.0. Sorry, that I didn't mention.
(Tag updated)
You can enumerate over the file names:
foreach(string fileName in Directory.EnumerateFiles(path)) {
// Do something with fileName - using `FileInfo` or `File`
}
string[] arFiles = Directory.GetFiles(#"C:\");
foreach (var sFilename in arfiles)
{
// Open file named sFilename for reading, do whatever
using (StreamReader sr = File.OpenText(sFilename ))
{
string s = "";
while ((s = sr.ReadLine()) != null)
{
Console.WriteLine(s);
}
}
}
foreach (var file in Directory.EnumerateFiles(path))
{
var currFileText = File.ReadAllText(file);
}
What about Directory.GetFiles(path) method?
foreach(String fileName in Directory.GetFiles(path))
{
FileInfo file = new FileInfo(fileName);
}
Try with this...
foreach (var filePath in Directory.GetFiles(path))
{
var text = File.ReadAllText(filePath);
// Further processing
}
Related
How can I read line by line for a list of files?
I have a directory with a number of files, I need to save all the files in a list and process them one by one, line by line.
So far I have done the following :
//fetching all files from directory
DirectoryInfo d = new DirectoryInfo("path");
Dictionary<int, FileInfo> DatFiles = new Dictionary<int, FileInfo>();
int filecounter = 1;
foreach (var dat in d.EnumerateFiles())
{
DatFiles.Add(filecounter, dat);
filecounter++;
}
Console.WriteLine(filecounter);
foreach (var fileName in DatFiles)
{
foreach (var line in File.ReadLines(fileName.Value.OpenText().ToString()))
{
//run some methods
}
}
When executing, I'm getting an exception, file not found. Even though the list is full of file names.
EnumerateFiles() returns a list of FileInfo objects, and File.ReadLines() takes a string path argument; you probably want to use File.ReadLines(fileName.Value.FullName) in your foreach as that gives the path to the actual file; OpenText() returns a StreamReader object.
This smaller code should do the task
var files = Directory.GetFiles("path");
foreach(var f in files)
{
using(StreamReader reader = new StreamReader(f))
{
var lines = reader.ReadToEnd().Split(new string[]{Environment.NewLine});
// Do here
}
}
When all else fails refer to the documentation
// Open the stream and read it back.
using (StreamReader sr = fi.OpenText())
{
string s = "";
while ((s = sr.ReadLine()) != null)
{
Console.WriteLine(s);
}
}
I have a folder "c:\test" which contains multiple archives. How do I search through all the archives in this folder for a specific file.
This only search a particular archive using ZipPath:
private void button1_Click(object sender, EventArgs e)
{
string zipPath = #"C:\Test\archive1.zip";
string filetosearch = "testfile";
using (ZipArchive archive = ZipFile.OpenRead(zipPath))
{
foreach (ZipArchiveEntry entry in archive.Entries)
{
var position = entry.Name.IndexOf(filetosearch , StringComparison.InvariantCultureIgnoreCase);
if (position > -1)
{
listView1.Items.Add(entry.Name);
}
}
}
}
Is it possible to search all the archives in this folder i.e archive1 to archive70
You can use the following code:
foreach(var zipPath in Directory.GetFiles("C:\\Test"))
{
using (ZipArchive archive = ZipFile.OpenRead(zipPath))
{
foreach (ZipArchiveEntry entry in archive.Entries)
{
var position = entry.Name.IndexOf(filetosearch , StringComparison.InvariantCultureIgnoreCase);
if (position > -1)
{
listView1.Items.Add(entry.Name);
}
}
}
}
The code gets all the files in the directory and iterates through them. If you need to filter the files by extension you can check it inside the foreach loop.
You probably want something along the lines of
string[] filePaths = Directory.GetFiles(#"c:\Test\", "*.zip")
Then change you click code to
foreach(var filePath in filePaths){
//your code here for each path
}
You may use following code
string[] filePaths = Directory.GetFiles(#"c:\test", "*.zip");
string filetosearch = "testfile";
foreach (var item in filePaths)
{
string name = Path.GetFileName(item);
if (name.IndexOf(filetosearch, StringComparison.InvariantCultureIgnoreCase) != -1)
{
//item is path of that file
}
}
I am trying to create new files with the names created by data from lines in several files.
I want to read all lines of just the .txt files in a folder and then create files from that list.
The files are have various amounts of lines and there could be a various amount of .txt files.
Here is the code that I have tried;
static void WriteToFile(string directory, string name)
{
string filename = String.Format(name);
string path = Path.Combine(directory, filename);
using (StreamWriter sw = File.CreateText(path))
{
sw.WriteLine("Inserted Text");
}
}
......
string[] allFiles = Directory.GetFiles(folder, "*.txt");
foreach (string file in allFiles)
{
string[] lines = File.ReadAllLines(file);
foreach (string newfile in lines)
{
WriteToFile(folder, newfile);
}
}
This is now creating the files but I need to specify the extension as they are just created as 'file1' instead of 'file1.ext'
File.Create Method (String) returns FileStream. The FileStream must be disposed to flush file. Try using this code to create an empty file:
File.Create(fileName).Dispose();
Also, take a look at the similar question: Creating an empty file in C#.
Without any details of error/exception, to me it seems either permission issue, or character issue.
You can use Path.GetInvalidPathChars with Enumerable.Intersect to check if file path contains invalid characters before creating new file
char[] invalidPathChars = Path.GetInvalidPathChars();
foreach (string newfile in lines)
{
if (invalidPathChars.Intersect(newfile).Any())
{
Console.WriteLine(newfile + " contains invalid characters for file name");
continue;
}
File.Create(newfile);
}
File.Create returns a filestream that you can use to write to the new file. But you are not providing the path that is the argument in Create but the line. The line might be an invalid path.
You can use this query instead:
string invalidCharacters = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());
var allPaths = Directory.EnumerateFiles(folder, "*.txt")
.SelectMany(path => File.ReadLines(path))
.Select(line => {
string fileName = line;
foreach (Char c in invalidCharacters)
fileName = fileName.Replace(c.ToString(), "_");
return new{ line, path = Path.Combine(targetFolder, fileName) };
} );
foreach(var p in allPaths)
{
File.WriteAllText(p.path, p.line);
}
Edit: however, that will very likely result in this error:
The specified path, file name, or both are too long. The fully
qualified file name must be less than 260 characters, and the
directory name must be less than 248 characters.
So you need to use a method that shortens the path (f.e. using a logic that appends a number to avoid duplicate names).
static void WriteToFile(string directory, string name)
{
string filename = String.Format(name + ".ini");
string path = Path.Combine(directory, filename);
using (StreamWriter sw = File.CreateText(path))
{
sw.WriteLine("Inserted Text");
}
}
......
var allFiles = Directory.GetFiles(folder, "*.txt");
foreach (string file in allFiles)
{
var lines = File.ReadAllLines(file);
foreach (string newfile in lines)
{
WriteToFile(folder, newfile);
}
}
I am trying to read a list in text file and move the files source to target directory. But as I am trying to read this file using for statement it's giving me following error :
foreach statement cannot operate on variables of type
System.IO.StreamReader because System.IO.StreamReader does not
contain a public definition for GetEnumerator
Not sure if this is issue with file creation or some alternate approach is needed here to read and then move files.
Please advise.
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);
string diff_list = string.Join(Environment.NewLine, file_list_diff);
df.WriteLine(string.Join(Environment.NewLine, file_list_diff));
df.Close();
System.IO.StreamReader file_read = new System.IO.StreamReader(target_dir + "\\Diff.txt");
if (!Directory.Exists(targetinfo.FullName))
{
Directory.CreateDirectory(targetinfo.FullName);
}
/*foreach (FileInfo fi in sourceinfo.GetFiles())
{
fi.CopyTo(Path.Combine(targetinfo.ToString(), fi.Name), true);
}*/
foreach (string file in file_read) // Error With For Loop
{
}
create_target_fileList();
}
Yes, you can't use foreach directly with StreamReader. It doesn't have the required members for foreach to work.
Options:
Use File.ReadLines instead:
string path = Path.Combine(targetDir, "Diff.txt");
foreach (string file in File.ReadLines(path))
{
// ...
}
Repeatedly call ReadLine on your StreamReader, which should be in a using statement and is simply obtained using File.OpenText:
string path = Path.Combine(targetDir, "Diff.txt");
using (TextReader reader = File.OpenText(path))
{
string file;
while ((file = reader.ReadLine()) != null)
{
// ...
}
}
Note that I've made the variable names a bit cleaner too - idiomatic variable names in C# are things like sourceFileList rather than source_f_list.
Additionally, I'd encourage you to use File.WriteAllText earlier on, rather than the way you're using df (without a using statement, and opening it much earlier than you need to).
Everything is working fine.. I can Unzip files, from an Zip/Rar .. Archive.
The Problem is, how to Unzip a file, thats in a Directory?
To Unzip a File directly I use (SharpZipLib):
FastZip fastZip = new FastZip();
fastZip.ExtractZip(source, targetDirectory, null);
using (var fs = new FileStream(source, FileMode.Open, FileAccess.Read))
using (var zf = new ZipFile(fs))
{
var ze = zf.GetEntry("toc.out");
if (ze == null)
{
throw new ArgumentException("toc.out", "not found in Zip");
}
using (var s = zf.GetInputStream(ze))
{
// do something with ZipInputStream
}
}
}
Or with DotNetZip/ZipDotNet:
using (ZipFile zip = ZipFile.Read(source))
{
ZipEntry e = zip["toc.out"];
e.Extract();
}
Thats not working, cause hes searching the file in the root..
And I also wont do something like: DirectoryName/toc.out
How can I achieve this`? Isn't there a parameter, where I can include all subfolders - for searching or something similar? :(
You can write a LINQ expression to find the file in sub folders as shown below
DirectoryInfo dirInfo = new DirectoryInfo(#"C:\");
foreach (var file in dirs.Select(dir => dir.EnumerateFiles().Where(i => i.Name.ToLower() == "wsdl.zip").FirstOrDefault()).Where(file => file != null))
{
Console.WriteLine(file.ToString());
Console.WriteLine(file.Length);
}
The above code searches all subfolder under C drive for the file wsdl.zip and prints its name and length to the console.
Hope that helps.
You can check the last part of the Name of the entry. Even if the file is in a subfolder, the Name entry would be something like "Folder/file.ext".
An extension method to accomplish this would be like:
public static ZipEntry GetEntryExt(this ZipFile file, string fileName)
{
foreach (ZipEntry entry in file)
{
if (entry.IsFile && entry.Name.EndsWith(Path.DirectorySeparatorChar + fileName))
return entry;
}
return null;
}