4
\$\begingroup\$

I have written a program that is very simple, with a very specific purpose. However, having written it in approximately 2 hours, (with a bit of cut/paste from some of my other programs and MSDN) it's very ugly.

For example, the main part of the program is held entirely within one big using block, when it really doesn't need to be.

Also, while for the initial purpose of this program is to create placeholder files, the current .pdf files are not in the correct format, which is fine. However, is it possible to create pdf's in the correct format?

Can anyone give me any suggestions on how to neaten this up?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Microsoft.VisualBasic.FileIO;

namespace File_Creation_Program
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            // Clears console in case program has been re-run
            Console.Clear();

            List<string> fileNames = new List<string>();

            Console.WriteLine("Please select 1 or more CSV files to be converted for fle creation.");
            Console.WriteLine();

            // "Multiselect" prperty allows more than 1 file to be selected at a time.
            using (OpenFileDialog openFileDialog1 = new OpenFileDialog())
            {
                openFileDialog1.Title = "Open file";
                openFileDialog1.CheckFileExists = true;
                openFileDialog1.CheckPathExists = true;
                openFileDialog1.DefaultExt = "csv";
                openFileDialog1.Filter = "CSV Files (*.csv)|*.csv|All files (*.*)|*.*";
                openFileDialog1.Multiselect = true;
                openFileDialog1.FilterIndex = 1;
                openFileDialog1.RestoreDirectory = true;
                openFileDialog1.ReadOnlyChecked = true;
                openFileDialog1.ShowReadOnly = true;

                // If the search for the file is OK (i.e. the file exists), stores the filename in a string.
                if (openFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    Console.WriteLine("Working...");
                    Console.WriteLine();

                    // Splits each file by line (as a precaution, as no file should have no more than one line)
                    foreach (string f in openFileDialog1.FileNames)
                    {
                        string[] importFile = File.ReadAllText(f).Split('\n');

                        foreach (string line in importFile)
                        {
                            string[] newFiles = line.Split(',');

                            Console.WriteLine("Please choose where you would like to save the files from " + f);
                            Console.WriteLine();

                            FolderBrowserDialog saveFile = new FolderBrowserDialog();

                            if (saveFile.ShowDialog() == DialogResult.OK)
                            {
                                string folderName = saveFile.SelectedPath;

                                // Creates the placeholder file. Since the files are created from a string, the format is incorrect,
                                // as it is effectively the same as changing the extension from a ".txt" to a ".pdf".
                                // Therefore, the file is useless (appears "corrupt") as anything but a placeholder.
                                foreach (string s in newFiles)
                                {
                                    Console.WriteLine("Working...");
                                    Console.WriteLine();

                                    try
                                    {
                                        StreamWriter sw;
                                        string fileName = folderName + "\\" + s;

                                        sw = File.CreateText(fileName);
                                        sw.WriteLine("Place holder file for Hard Copy entry");
                                        sw.Close();
                                    }
                                    catch (Exception e) { Console.WriteLine("File not created - " + e.Message); }
                                }

                                Console.WriteLine("...Done!");
                                Console.WriteLine();
                            }
                        }
                    }
                }
            }

            // In the case that more files need to be created.
            Console.WriteLine("Would you like to create more files? Y/N");
            string choice = Console.ReadLine();

            Program.Return(choice, args);
        }

        static void Return(string option, string[] args)
        {
            switch (option.ToUpper())
            {
                case "Y":
                case "YES":
                    // Program restarts
                    Main(args);
                    break;
                case "N":
                case "NO":
                    // Program ends
                    break;
                default:
                    Console.WriteLine("Not a valid input... Please enter 'Yes' or 'No'");
                    option = Console.ReadLine();
                    Return(option, args);
                    break;
            }
        }
    }
}
\$\endgroup\$
3
  • \$\begingroup\$ @SirPython thanks :) I have been on SE for a little while now, so I have a hold on what the site (in general) expects from it's askers, so I do try my best to meet that standard. It's good to know I have once again achieved that! \$\endgroup\$
    – Ben
    Commented Mar 1, 2016 at 1:49
  • \$\begingroup\$ You've got a FolderBrowserDialog.Show() inside the loop. Do you really want to ask the user which to save each file or maybe you just want to ask them once and then save all the files in the same folder? \$\endgroup\$
    – jop
    Commented Mar 1, 2016 at 3:13
  • \$\begingroup\$ @jop actually no, because I have allowed for a) multiple csv's to be selected at once and b) they may not want to save them all in the same place \$\endgroup\$
    – Ben
    Commented Mar 1, 2016 at 4:13

1 Answer 1

4
\$\begingroup\$

The first thing that I have noticed is the recursion in your Return method.

It is simpler just have a do while loop inside the Main method. Extract the details into separate methods and it should look like this:

    private static void Main(string[] args)
    {
        bool continueProcessing;
        do
        {
            var fileNames = GetSourceFileNames();
            foreach (var f in fileNames)
            {
                var folderName = GetDestinationFolder(f);
                foreach (var line in File.ReadAllLines(f))
                {
                    foreach (var field in line.Split(','))
                    {
                        CreatePlaceholderPDFs(folderName, field);
                    }
                }
            }
            continueProcessing = AskToContinue();

        } while (continueProcessing);
    }

Your Return method is now named AskToContinue. It returns true if the user wants to continue.

    private static bool AskToContinue()
    {
        while (true)
        {
            Console.WriteLine("Would you like to create more files? Y/N");
            var option = Console.ReadLine() ?? "";
            switch (option.ToUpper())
            {
                case "Y":
                case "YES":
                    return true;
                case "N":
                case "NO":
                    return false;
                default:
                    Console.WriteLine("Not a valid input... Please enter 'Yes' or 'No'");
                    break;
            }    
        }
    }

When handling external resources (files, windows resources, connections, etc) it's a good idea to have them opened and disposed on the same method. That's what the GetSourceFileNames and GetDestinationFolders method do now. (deleted a few lines - just left the important bits)

    private static IEnumerable<string> GetSourceFileNames()
    {
        using (var openFileDialog1 = new OpenFileDialog())
        {
            // set up openFileDialog1.Title = "Open file";
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                return openFileDialog1.FileNames;
            }
        }
        return new string[0];
    }

    private static string GetDestinationFolder(string filename)
    {
        using (var saveFile = new FolderBrowserDialog())
        {
            if (saveFile.ShowDialog() == DialogResult.OK)
            {
                return saveFile.SelectedPath;
            }
        }
        return string.Empty;
    }

These methods open the resource, gets the data, closes the resource and then returns the data to the caller.

The final part is the method for creating the placeholder PDFs

    private static void CreatePlaceholderPDFs(string folderName, string field)
    {
        PrintMessage("Working...");

        try
        {
            var fileName = Path.Combine(folderName, field);
            using (var writer = File.CreateText(fileName))
            {
                writer.WriteLine("Place holder file for Hard Copy entry");
                writer.Close();
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("File not created - " + e.Message);
        }
    }
\$\endgroup\$
3
  • \$\begingroup\$ I should mention I am still using .NET 4.0, if that makes any difference \$\endgroup\$
    – Ben
    Commented Mar 1, 2016 at 4:24
  • \$\begingroup\$ The code I've written is for .net 4. \$\endgroup\$
    – jop
    Commented Mar 1, 2016 at 4:40
  • \$\begingroup\$ Ok, excellent :) I'll have a look into it, thanks for the response! \$\endgroup\$
    – Ben
    Commented Mar 1, 2016 at 4:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.