Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Author: Mark Grealish (s00123474@itsligo.ie)
- Description: A simple CSV parser and viewer.
- Date: Eh, today.
- Attribution:
- The player data is that of my World of Warcraft guild because I never grabbed the sample file.
- It was scraped from the World of Warcraft Armory website:
- http://us.battle.net/wow/en/guild/arthas/Def%C3%ADant/
- */
- using System;
- using System.IO;
- using System.Collections.Generic;
- public class CsvReader
- {
- //
- // ++++GLOBAL VARIABLES++++
- //
- // I go in the door with a null value because I use this as a check elsewhere.
- public static string path = "players.csv";
- public static bool debug = false;
- static void Main()
- {
- //
- // ++++MAIN MENU++++
- //
- int n = 42;
- do
- {
- Console.Clear();
- // Output in option one is limmited! There is a note, below, about this.
- Console.WriteLine("1. View the contents of {0}.", path);
- Console.WriteLine("2. Search for a specific record in {0}.", path);
- Console.WriteLine();
- Console.WriteLine("4. Exit.");
- Console.WriteLine();
- n = IntParse("Selection: ");
- switch ( n )
- {
- case 1:
- // Putting Console.Clear(); here makes my life easier. Messy, but fuck it.
- Console.Clear();
- CsvView( path, -1 );
- break;
- case 2:
- Console.Clear();
- CsvSearch( path );
- break;
- case 4:
- break;
- default:
- break;
- }
- } while ( n != 4 );
- }
- //
- // ++++LOAD CSV FILE++++
- //
- private static string[] CsvLoad( string path )
- {
- /*
- In this method I loop through and read the file twice. This isn't a perfect solution, but eh, it works.
- Update: I looked around, and this actually is a recommended method to return to the top in a simple parser.
- There's an alternate method that involves a list which seems fairly simple to implement, but it's too much
- work right now. /lazy
- I counted rows above so the one-dimensional array is the exact size of the file. AKA: MOAR EFFICENCY.
- Back to the topic of efficiency: I want to emulate the Unix/Linux style of file management,
- which is to not lock the file except during read/write. Correspondingly, the only time I open the file
- is when I call this method. This array is then piped to wherever it is needed.
- */
- // Count rows. Start with row 1.
- int row = 0;
- StreamReader count = new StreamReader( path );
- string line = "";
- while ( line != null )
- {
- row++;
- line = count.ReadLine();
- }
- count.Close();
- // The array for the data.
- string[] csvData = new string[row];
- // Fill up the array.
- StreamReader data = new StreamReader( path );
- int n = 0;
- while ( n < row )
- {
- csvData[n] = line;
- line = data.ReadLine();
- n++;
- }
- return csvData;
- }
- //
- // ++++VIEW CSV FILE+++
- //
- static void CsvView( string path, int rec )
- {
- /*
- This method takes the record and actually handles the output. The default value is "-1". If it is -1, the
- entire array will be output. If it is any other number <= csv.Length, then only that given record will
- be displayed.
- */
- Console.Clear();
- // 1. Grab the array containing the CSV data.
- string[] csv = CsvLoad( path );
- // 2. Put the first line into a string.
- string line = csv[1];
- // 3. Split that line into an array.
- string[] field = line.Split( ',' );
- // 4. Use the above arrays to output the respective rows and fields of the array.
- // int rows = 20;
- int rows = csv.Length;
- // There was a note above about this: In the above line I demonstrate my ability to output the entire array.
- // However, I limit the display to ten records for ease of life when debugging this program.
- int cols = field.Length;
- // Table format.
- string tFormat = "{0,-15}";
- string hFormat = "{0,-15}{1,-15}{2,-15}{3,-15}";
- // A spot of sanity checking during debugging.
- // Console.WriteLine( csv.Length );
- // Console.WriteLine( field.Length );
- // Console.WriteLine();
- // Probably worth a few points to untangle this mess:
- // 1. Output the line header ("Player, ...") in one go.
- // 2. Output the line break once per column.
- // 3. Double loop: Once per line, output each field from that line, as Split().
- // 4. Following on from 3., output the user's citation once per line, per their score.
- Console.WriteLine( String.Format (hFormat, "Player #:", "Name:", "Score:", "Citation:" ));
- // Remove the equals for three columns instead of four.
- for ( int i = 0; i <= cols; i++ )
- Console.Write(String.Format( tFormat, "----------" ));
- Console.WriteLine();
- // The quote unquote main event:
- // Seriously, this segment made more sense when I was rancidly drunk.
- if ( rec < 0 )
- {
- for ( int i = 1; i < rows; i++ )
- {
- line = csv[i];
- field = line.Split( ',' );
- for ( int j = 0; j < cols; j++ )
- {
- Console.Write( String.Format( tFormat, field[j] ));
- }
- // Totally, totally, *totally* hacked this line in to fit the exercise. Sorry, Vivion.
- Console.Write( String.Format( tFormat, PlayerCitation(field[2]) )); // <<--Parentheses, oh my!
- Console.WriteLine();
- }
- }
- else if ( rec > 0 )
- {
- // Blatant copy/paste to avoid a better fix.
- line = csv[rec];
- field = line.Split( ',' );
- for ( int j = 0; j < cols; j++ )
- {
- Console.Write( String.Format( tFormat, field[j] ));
- }
- // Totally, totally, *totally* hacked this line in to fit the exercise. Sorry, Vivion.
- Console.Write( String.Format( tFormat, PlayerCitation(field[2]) )); // <<--Parentheses, oh my!
- Console.WriteLine();
- }
- // And then home.
- Back();
- }
- //
- // ++++SEARCH++++
- //
- static void CsvSearch( string path )
- {
- Console.Clear();
- // The example array.
- string[] csv = CsvLoad( path );
- // Array elements, spread out for debugging.
- // Example string.
- Console.Write( "Enter search string (case sensitive): " );
- string query = Convert.ToString( Console.ReadLine() );
- // n serves two purposes:
- // 1. Loop counter in the loop.
- // 2. The loop will break at the element containing our string.
- // 2a. After the loops breaks, n will be used to output that element
- int element = 1;
- int sentinel = 0;
- try
- {
- do
- {
- // teh loopage.
- sentinel = csv[element].IndexOf( query );
- element++;
- // IndexOf() changes the value of sentinel to -1 if the item isn't found in the string.
- // When the string is matched, sentinel becomes 7, and the loop breaks.
- if ( sentinel >= 0 )
- break;
- } while ( (element < csv.Length) );
- }
- catch ( IndexOutOfRangeException )
- {
- // The search throws up an error if nothing is matched. I dump the error in here and handle it separately, below.
- // I liken this to a little box filled with screaming monsters. Monsters.
- }
- // This is to correct for...unexpected behaviour elsewhere.
- // I had to give element a value of 1 or it crashed out. Therefore the line /after/ the matched string was output.
- // I therefore subtract 1 from element to correct for this.
- // A workaround, not a fix.
- element -= 1;
- if ( debug )
- {
- // Debugging.
- Console.WriteLine();
- Console.WriteLine("Sentinel value: {0}", sentinel);
- Console.WriteLine("Element value: {0}", element);
- if ( sentinel > 0 )
- Console.WriteLine("Matched string: {0}", csv[element]);
- else if ( sentinel <= 0 )
- Console.WriteLine("Not found, sorry. :(");
- Console.WriteLine();
- Console.ReadLine();
- }
- if ( sentinel > 0 )
- {
- Console.Clear();
- // The pretty output goes here.
- Console.WriteLine("Record matched!");
- CsvView( path, element );
- }
- else if ( sentinel < 0 )
- {
- Console.Clear();
- Console.WriteLine("String not matched, sorry. :(");
- Back();
- }
- /*
- I ran into some problems with the output. I could write a method to output either the entire array, or one line as needed.
- But eh, whatever.
- This was the final part of the project I approached. My own overall assessment of my performance is moments of brilliance
- interspersed with hours of raw, bumbling mediocrity. I spoke to other classmates, and apparently my approach to handling
- the file with an array was unique. The code in this project is stripped down from a fully-featured CSV parser that I wrote.
- Balancing this was my often lazy implementation of X or Y feature.
- However! The end-user should see a flawless experience in line with the expectations of the project. Small victories.
- */
- }
- //
- // ++++CITATIONS++++
- //
- private static string PlayerCitation( string sScore )
- {
- /*
- The achievement scores in my players.csv file are higher than those in the sample file.
- (This is the same sample file that, in hindsight, I should have probably downloaded.)
- To accomodate this, I have modified the score criteria to fit my .csv file. Behold:
- Exercise: Mine:
- < 400 < 4000
- >= 400 && <= 599 >= 4000 && <= 5999
- >= 600 && <= 699 >= 6000 && <= 6999
- >= 700 && <= 999 >= 7000 && <= 9999
- > 999 > 9999
- In short, I added a zero. /toot
- */
- string citOne = "Sluggish Snail";
- string citTwo = "Ambling Armadillo";
- string citThree = "Bobbing Bobcat";
- string citFour = "Rocketing Rabbit";
- string citFive = "Turbocharged Cheetah";
- // Take in the player score (their achievement points), and convert it to an int value.
- int score = Convert.ToInt32( sScore );
- string citation = "";
- if ( score < 4000 )
- citation = citOne;
- if ( (score >= 4000) && (score <= 5999) )
- citation = citTwo;
- if ( (score >= 6000) && (score <= 6999) )
- citation = citThree;
- if ( (score >= 7000) && (score <= 9999) )
- citation = citFour;
- if ( (score > 9999) )
- citation = citFive;
- return citation;
- }
- //
- // ++++GO BACK++++
- //
- static void Back()
- {
- // Pause before returning.
- Console.WriteLine();
- Console.Write("Press [RETURN] to return to the main menu.");
- Console.ReadLine();
- }
- //
- // ++++PARSE INT++++
- //
- private static int IntParse( string userPrompt )
- {
- // A boolean variable to test the int (or double, as the case may be).
- bool evalInt = false;
- int parsedInt = 0;
- do
- {
- // Send the relevant string to the console.
- Console.Write(userPrompt);
- // Read/test the user's input.
- evalInt = Int32.TryParse( Console.ReadLine(), out parsedInt );
- // If it doesn't parse, loop. If it does, move on.
- if ( !evalInt )
- InputFail();
- // Keep asking the luser for input until they give us something valid.
- } while ( !evalInt );
- // Return the parsed input.
- return parsedInt;
- }
- //
- // ++++PARSE DOUBLE++++
- //
- private static double DoubleParse( string userPrompt )
- {
- bool evalDouble = false;
- double parsedDouble = 0;
- do
- {
- Console.Write( userPrompt );
- evalDouble = Double.TryParse( Console.ReadLine(), out parsedDouble );
- if ( !evalDouble )
- InputFail();
- } while ( !evalDouble );
- return parsedDouble;
- }
- //
- // ++++BAD USER! BAD!++++
- //
- static void InputFail()
- {
- // Part of the Int/Double parse methods.
- Console.WriteLine("Invalid input. Please enter a numerical value.");
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement