tags:

views:

800

answers:

6

Any suggestions on how to improve this method? I am currently using it to select a single wallpaper from a directory of wallpapers

I know your not supposed to use arraylist anymore but i couldnt think of a altrnative also im not sure how to filter for more than just one type of file (ie jpg gif png) in the directory info.

any suggestions or tweaks would be fantastic

private string getrandomfile(string path)
        {
            ArrayList al = new ArrayList();
            DirectoryInfo di = new DirectoryInfo(path);
            FileInfo[] rgFiles = di.GetFiles("*.*");
            foreach (FileInfo fi in rgFiles)
            {
                al.Add(fi.FullName);
            }

            Random r = new Random();
            int x = r.Next(0,al.Count);

            return al[x].ToString();

        }

Thanks

Crash

+2  A: 

Do you really need the ArrayList at all, you should be able to eliminate it and just use the array directly once you've generated a random number.

Also, you should check that the path is valid... if specified by a user...

Jon
I agree with this, and I think the LINQ is overkill.
superjoe30
+1  A: 

Changed to use a single instance of the pseudo-random number generator.

// Use a class variable so that the RNG is only created once.
private Random generator;
private Random Generator
{
    get
    {
        if (this.generator == null)
        {
           this.generator = new Random();
        }
        return this.generator;
    }
}
private string getrandomfile(string path)
{
    string file = null;
    if (!string.IsNullOrEmpty(path))
    {
        var extensions = new string[] { ".png", ".jpg", ".gif" };
        try
        {
            var di = new DirectoryInfo(path);
            var rgFiles = di.GetFiles("*.*")
                            .Where( f => extensions.Contains( f.Extension
                                                               .ToLower() );
            int fileCount = rgFiles.Count();
            if (fileCount > 0)
            {
                int x = this.Generator.Next( 0, fileCount );
                file = rgFiles.ElementAt(x).FullName;
            }
        }
        // probably should only catch specific exceptions
        // throwable by the above methods.
        catch {}
    }
    return file;
}
tvanfosson
im not opposed to it but why is everyone so in love with Var. I thought that wasn't good Best practices
Crash893
I think it's more readable. Since C# is strongly typed, you don't lose type safety with it and typically it's obvious from the RHS of the assignment what the type is so you don't lose the semantics.
tvanfosson
also it seems that rgFiles.length is invalid. did you mean count?Normaly i wouldn't ask but im not very familiar with the linq. If i do .count<> do i need to spesify between the <> what the count is of?
Crash893
Oops. I corrected it in once place, but not the other. Yes, it should be .Count() not length, since it's not an array but an IEnumerable<FileInfo>.
tvanfosson
your `return file;` is inside the if(...) and should cause a compile error (not all paths return a value).
Erich Mirabal
+8  A: 

Why not use LINQ:

var files = Directory.GetFiles(path, "*.*").Where(s => Regex.Match(s, @"\.(jpg|gif|png)$").Success);
string randFile = path + files.ToList()[r.Next(0, files.Count())];
sipwiz
+3  A: 

As always - there is more than one way to skin a cat. I've built off of tvanfosson (correct) answer, not because this is 'more' correct; but because I think it's a useful approach.

private static string getRandomFile(string path)
{
    try
    {
        var extensions = new string[] { ".png", ".jpg", ".gif" };

        var di = new DirectoryInfo(path);
        return (di.GetFiles("*.*")
                            .Where(f => extensions.Contains(f.Extension
                                                               .ToLower()))
                            .OrderBy(f => Guid.NewGuid())
                            .First()).FullName ;              
    }
    catch { return ""; }
}
Rob P.
A: 

I made a few changes

here is the code i ended up using, I cut out some of the conditonals becuase they dont really matter ( if there are no files it will return null anyway no need to test twice). I also corrected for a few minor syntax errors and one user pointed out the return should be moved down.

also in regards to the random class, Im not sure why it was bad to keep calling it but i dont see that its necessary since this will only run once every 10 to 15 min. and even then it would only create the class if files were found.

Thanks for everyone's help ( tvanfosson)

private string getrandomfile2(string path)
    {
        string file = null;
        if (!string.IsNullOrEmpty(path))
        {
            var extensions = new string[] { ".png", ".jpg", ".gif" };
            try
            {
                var di = new DirectoryInfo(path);
                var rgFiles = di.GetFiles("*.*").Where( f => extensions.Contains( f.Extension.ToLower()));
                Random R = new Random();
                file = rgFiles.ElementAt(R.Next(0,rgFiles.Count())).FullName;
            }
            // probably should only catch specific exceptions
            // throwable by the above methods.
            catch {}
        }
        return file;
    }
Crash893
A: 

please delete this post

michal