my project is about recording screen as sequence of images then instead of make it as video i planed to load all image directories to list and use timer to view them image by image, but i get files in wrong order like this:
this code is to load files from directory:
string[] array1 = Directory.GetFiles("C:\\Secret\\" + label1.Text, "*.Jpeg");
Array.Sort(array1);
foreach (string name in array1)
{
listBox1.Items.Add(name);
}
timer2.Start();
this code to view them
int x = 0;
private void timer2_Tick(object sender, EventArgs e)
{
if (x >= listBox1.Items.Count)
{
timer2.Stop();
}
else
{
ssWithMouseViewer.Image = Image.FromFile(listBox1.Items[x].ToString());
x++;
}
}
i need to view them in order like 0.jpeg, 1.jpeg, 2.jpeg.....10.jpeg, 11..jpeg...
The strings are sorted: in lexicographic order...
you have two options: rename the files so they be ordered in lexicographic order (eg: 001, 002, 003...), or, using linq, and file name manipulations:
IEnumerable<string> sorted = from filename in array1
orderby int.Parse(Path.GetFileNameWithoutExtension(filename))
select filename;
Presumably your array should already be sorted as you enter label1.text in numerical order? If not it might be easier for you to sort the label1.text values into numerical order before calling your method.
You need to use a "natural sort order" comparer when sorting the array of strings.
The easiest way to do this is to use P/Invoke to call the Windows built-in one, StrCmpLogicalW(), like so (this is a compilable Console application):
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Security;
namespace ConsoleApp1
{
[SuppressUnmanagedCodeSecurity]
internal static class NativeMethods
{
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
public static extern int StrCmpLogicalW(string psz1, string psz2);
}
public sealed class NaturalStringComparer: IComparer<string>
{
public int Compare(string a, string b)
{
return NativeMethods.StrCmpLogicalW(a, b);
}
}
sealed class Program
{
void run()
{
string[] filenames =
{
"0.jpeg",
"1.jpeg",
"10.jpeg",
"11.jpeg",
"2.jpeg",
"20.jpeg",
"21.jpeg"
};
Array.Sort(filenames); // Sorts in the wrong order.
foreach (var filename in filenames)
Console.WriteLine(filename);
Console.WriteLine("\n");
Array.Sort(filenames, new NaturalStringComparer()); // Sorts correctly.
foreach (var filename in filenames)
Console.WriteLine(filename);
}
static void Main(string[] args)
{
new Program().run();
}
}
}
NOTE: This example is based on code from this original answer.
The most simple way is to use the OrderBy function in LINQ in combination with Path.GetFileNameWithoutExtension like so:
string[] array1 = Directory.GetFiles("C:\\Secret\\" + label1.Text, "*.Jpeg");
array1 = array1.OrderBy(x => int.Parse(System.IO.Path.GetFileNameWithoutExtension(x))).ToArray();
To use the OrderBy function, you need to add a using statement for the namespace System.Linq;
Related
i am starting to learn C#, my first language i learned is Python and i switched to Visual Studio Code for it from Pycharm.
I am trying to code a simple TicTacToe as exercise, when i loop trough my TicTacToe grid to see if one of the empty fields marked with numbers is still avaliable, i get an unexpected output.
The expected output would be 1-9, but its not, i am not allowed to post images so not sure how to say/show it.
When i use char as data type the correct value seems to be there in '' as second value, but how do access it?
in both cases comparision operator do not yield the expected results!
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
namespace CSharp_Shell
{
public static class Programm
{
static int meow = 1;
static string board_roof = "-------";
static string board_mid1 = "|1|2|3|";
static string board_mid2 = "|4|5|6|";
static string board_mid3 = "|7|8|9|";
static string board_all_default = board_roof + Environment.NewLine + board_mid1 + Environment.NewLine +board_mid2 + Environment.NewLine +board_mid3 + Environment.NewLine + board_roof;
public static void Main(string[] args) {
Acces_board2(meow);
}
public static void Acces_board2(int lfm) {
for(int gas=0; gas<board_all_default.Length; gas++) {
bool result = char.IsNumber(board_all_default[gas]);
if (result) {
Console.WriteLine($"{board_all_default[gas]} , {lfm}");
if(lfm < board_all_default[gas]) {
Console.WriteLine($"True");
}
}
}
}
}
}
doesnt matter if i use
if (lfm < board_all_default[gas])
or
int checkme = board_all_default[gas];
if (lfm < checkme)
it never works, that would be no issue in python, i have no clue whats happening
Here is my code:
private static bool checkifDirectoryContainsFilesWithSpecifiedExtention(string path, string fileExestention) //Like C:\\smth, *.html
{
foreach (string f in Directory.GetFiles(path,fileExestention))
{
return true;
}
foreach (string d in Directory.GetDirectories(path))
{
return checkifDirectoryContainsFilesWithSpecifiedExtention(d,fileExestention);
}
return false;
}
In this function the program returns every file with specified extention BUT If I contain only one file with the specified extention in the last folder, the function returns false, which makes no sence because it exists
My question is why it does that...
Try it out. I can't really find the bug.
The problem is the "return" inside the foreach (string d in Directory.GetDirectories(path)) loop. It will only check the first directory per level. You need something like this (not nice, but keeping your style/format)
bool ok = false;
foreach (string d in Directory.GetDirectories(path))
{
ok = ok || checkifDirectoryContainsFilesWithSpecifiedExtention(d,
fileExestention);
}
return ok;
Better yet, use the linq that Marc provided.
Turned this into a LINQ query
private static bool CheckifDirectoryContainsFilesWithSpecifiedExtention(string path, string fileExestention)
//Like C:\\smth, *.html
{
return Directory.GetFiles(path, fileExestention).Any() ||
Directory.GetDirectories(path)
.Select(d => CheckifDirectoryContainsFilesWithSpecifiedExtention(d, fileExestention))
.FirstOrDefault();
}
Tried it on the a few debug folders using *.exe as the mask and it returns true. It traverses sub folders as well. Not sure what you meant by one file in the last folder.
See if it works for you.
this works for me
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StackOverflowSnippets
{
class Program
{
static void Main(string[] args)
{
String path = #"C:\smth"; String pattern = "*.html";
Console.WriteLine("__" + checkifDirectoryContainsFilesWithSpecifiedExtention(path, pattern));
Console.ReadLine();
}
private static bool checkifDirectoryContainsFilesWithSpecifiedExtention(string path, string fileExestention) //Like C:\\smth, *.html
{
foreach (string f in Directory.GetFiles(path, fileExestention))
{
return true;
}
foreach (string d in Directory.GetDirectories(path))
{
if (checkifDirectoryContainsFilesWithSpecifiedExtention(Path.Combine(path, d), fileExestention))
{
return true;
}
}
return false;
}
}
}
I have a large directory of folders and files that contain a space at the end of the name, I'm trying to rename the directories with that space to one without, so that another application would be able to access it.
I'm using C# (but if there's a better option that would fix that issue please suggest) and here's my entire code:
using System;
using System.IO;
using System.Text.RegularExpressions;
namespace removing_spaces_in_directories_names
{
class Program
{
public static string path = "../../../old_directory";
static void Main(string[] args)
{
DirectoryInfo di = new DirectoryInfo(path);
WalkDirectoryTree(di);
Console.ReadLine();
}
static void WalkDirectoryTree(System.IO.DirectoryInfo root)
{
if (root.Name != "old_directory")
{ renameDirectory(root); }
DirectoryInfo[] diArr = root.GetDirectories();
foreach(DirectoryInfo di in diArr)
{
WalkDirectoryTree(di);
}
}
static void renameDirectory(System.IO.DirectoryInfo dir)
{
Console.WriteLine("renaming: " + dir.FullName);
string newName = ReplaceLastOccurrence(dir.FullName, " ", "");
if (Directory.Exists(dir.FullName) == false)
{
//dir.MoveTo(newName);
String oldName = #"\\?\"+dir.FullName;
Directory.Move(oldName,newName);
}
}
public static string ReplaceLastOccurrence(string Source, string Find, string Replace)
{
int place = Source.LastIndexOf(Find);
if (place == -1)
return Source;
string result = Source.Remove(place, Find.Length).Insert(place, Replace);
return result;
}
}
}
I have tried adding "\?\" to the beginning of the folder name as suggested here but that's not working, the error I'd get if I add it is: Illeagal characters in path.
On the other hand if I use dir.MoveTo(newName); without the "\?\" characters I'd get the error: Could not find a part of the path 'Volunteer Information '
How can I go through this if at all? would perhaps running this application on linux rather than windows help?
For each directory that you want to rename (remove the trailing space at the end in this case), let's say your DirectoryInfo variable is called di
You want to do this:
string oldName = di.FullName;
string newName = oldName.TrimEnd();
Directory.Move(oldName, newName);
I rewrote this in a PHP application that's sitting on linux and it worked.
Just learning RX and wanted to make a program that iterated the file system. Here is what I came up with that works:
using System;
using System.IO;
using System.Reactive.Disposables;
using System.Reactive.Linq;
namespace ConsoleApplication8
{
internal class Program
{
private static IObservable<string> GetFiles(string folder, string filePattern)
{
return Observable.Create<string>(
o =>
{
var files = Directory.GetFiles(folder, filePattern);
foreach (var file in files)
{
o.OnNext(file);
}
var folders = Directory.GetDirectories(folder);
foreach (var f in folders)
{
var x = GetFiles(f, filePattern);
x.Subscribe(p => { o.OnNext(p); });
}
o.OnCompleted();
return Disposable.Empty;
});
}
private static void Main(string[] args)
{
var o = GetFiles(#"d:\temp", "*.*");
o.Subscribe(p => { Console.WriteLine(p); });
Console.Read();
}
}
}
(Note the use of recursion by calling GetFiles again and subscribing)
While it works it seems very clumsy, I can't help thinking that I should be using something like Concat to combine the sequences instead of just bubbling them back up.
Also I would like to change that Foreach to a Parallel.ForEach but I'm unsure the ramifications this would have using RX. I can't seem to find much for documentation.
Any tips on how to write this better using RX?
To solve a problem like this, it can help to write a LINQ version of the function first. eg:
static IEnumerable<string> GetFiles(string folder, string filePattern)
{
return Directory.GetFiles(folder, filePattern)
.Concat(Directory.GetDirectories(folder).SelectMany(f => GetFilesEnumerable(f, filePattern)));
}
Then just change the IEnumerables to IObservables:
static IObservable<string> GetFiles(string folder, string filePattern)
{
return Directory.GetFiles(folder, filePattern).ToObservable()
.Concat(Directory.GetDirectories(folder).ToObservable().SelectMany(f => GetFilesEnumerable(f, filePattern)));
}
Turns out, based on my discovery of SearchOption.AllDirectories (why in all my years have I never noticed this) it can be boiled down into two real lines of code:
using System;
using System.IO;
using System.Reactive.Linq;
namespace ConsoleApplication8
{
internal class Program
{
private static void Main(string[] args)
{
var o = Directory.GetFiles(#"e:\code", "*.*", SearchOption.AllDirectories).ToObservable();
o.Subscribe(f => Console.WriteLine(f));
Console.Read();
}
}
}
Crazy how simple it really is now. Need a new RX problem to play with.
So I'm trying to run through every file on my harddrive, but it stops once it gets to the 2115th (I think) loop. I believe it is a stack overflow due to my use of recursion, but I'm new to C# and really have no idea. Here's my code, thank you very much.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Data;
namespace test_data
{
class Program
{
static string drive = Path.GetPathRoot(Environment.CurrentDirectory);
static void CrawlDir(string dir)
{
string[] dir_package = {};
List<string> dir_list = new List<string>();
foreach (string scan_dir in Directory.GetDirectories(dir))
{
try
{
dir_list.Add(scan_dir);
}
catch (System.Exception error)
{
Console.WriteLine(error.Message);
}
}
dir_package = dir_list.ToArray();
Process_Package(dir_package);
}
static void Main(string[] args)
{
CrawlDir(drive);
Console.ReadLine();
}
static void Process_Package(string[] package)
{
foreach (string dir in package)
{
Console.WriteLine(dir);
try
{
CrawlDir(dir);
}
catch (Exception)
{
Console.WriteLine("Error!");
}
}
}
}
}
Just use what's built in - Directory.GetDirectories supports an optional parameter to specify if you want to get all directories recursively:
var dirs = Directory.GetDirectories(drive, "*.*", SearchOption.AllDirectories);
Note that this is a blocking call - instead you could use Directory.EnumerateDirectories to receive the directory names one by one as they are being found:
var dirs = Directory.EnumerateDirectories(drive, "*.*", SearchOption.AllDirectories);
foreach(string dir in dirs)
{
Console.WriteLine(dir);
}
Use this overload with SearchOption.AllDirectories so you don't have to do any recursion:
public static string[] GetDirectories(
string path,
string searchPattern,
SearchOption searchOption
)
Recursion looks more or less ok, although you do not really need a list in CrawlDir. If you had a stack overflow you'd get a nasty message.
My guess is - the program completes and stops at ReadLine() waiting for you to press Enter.
You're adding a lot of overhead to each level of recursion by using a List (dir_list), an array (dir_package) and two try/catch loops. I don't know what you're really trying to do, but for this example it's way overkill.
Still, it would take a lot to cause a stack overflow on a modern OS. What error message are you getting?
This code should be equivalent.
using System;
using System.IO;
namespace test_data
{
class Program
{
static string drive = Path.GetPathRoot(Environment.CurrentDirectory);
static void CrawlDir(string dir)
{
foreach (string subDir in Directory.GetDirectories(dir))
{
try
{
Console.WriteLine(subDir);
CrawlDir(subDir);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
static void Main(string[] args)
{
CrawlDir(drive);
Console.ReadLine();
}
}
}