Doing a search function on a txt file - c#

I am trying to create a search function, so that when I search for White, it should return me "#FFFFFF". Also, it should be case insensitive and support partial name input. The text file that I have contains all the color coding information in the following format:
"#FFFFFF"#White: "#FF0000"#Red:
What I have managed to understand, and done so far is as below; which is basically mapping to the text file and instructing it to write to line till the end of the document. What I do not understand is how to implement the above requirements.
I know it is not a lot, but I don't understand the concept behind the search function.
protected void search_Click(object sender, EventArgs e)
{
StreamReader sr = new StreamReader("colorCode.txt");
string line = null;
while((line =sr.ReadLine()) !=null)
{
}

In this example the colorCode stores the the match for the colorToSearch
protected void search_Click(object sender, EventArgs e)
{
StreamReader sr = new StreamReader("colorCode.txt");
string line = null;
char []colorSeparator = { ':' } ;
string []colors ;
char []colorCodeSeparator = { '#' } ;
string []codeAndColor ;
bool found ;
string colorToSearch ;
string colorCode ;
colorToSearch = "White" ;
found = false ;
while(!found && (line =sr.ReadLine()) !=null)
{
//separate the content of the file "#FFFFFF"#White: "#FF0000"#Red: using ":" as separator
colors = line.Split(colorSeparator) ;
foreach(string color in colors)
{
codeAndColor = colors.Split(colorCodeSeparator) ;
//codeAndColor[0] now contains the colorCode "#FFFFFF"
//codeAndColor[1] contains the name of the color "White"
//check if the name of the color in the file contains the colorToSearch allowing for case insensitive
if(codeAndColor[1].ToUpper().Contains(colorToSearch.ToUpper()))
{
colorCode = codeAndColor[0].Substring(1,7) ; //the 1 is to skip the initial double quote, 7 is the number of caracter to take
found = true ;
//stop the foreach loop
break ;
}
}
}
}
If you are going to do more searches I suggest that you load the colors in a Dictionary<string,string> only once from the file and perform the search on the Dictionary

Instead of opening the file every time, if the file is not huge and it is not updated while your program is running, perhaps you can read it just once and create a lookup table that can be searched, like in the example below. If you need case insensitive comparisons, or a more complicated way to do partial color matching, you will need to add that.
public class ColorLookUpTable
{
private readonly IDictionary<string, string> _colorTable;
private ColorLookUpTable(IDictionary<string, string> colorTable)
{
_colorTable = colorTable;
}
public static ColorLookUpTable LoadFromFile(string fileName)
{
var colorTable = new Dictionary<string, string>();
using (var reader = File.OpenText(fileName))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var colorPairs = line
.Split(new [] { ':' }, StringSplitOptions.RemoveEmptyEntries)
.Where(f => !string.IsNullOrWhiteSpace(f))
.Select(f => f.Trim());
foreach (var colorPair in colorPairs)
{
var fields = colorPair.Split(new [] { '#' }, StringSplitOptions.RemoveEmptyEntries).ToArray();
if (fields.Length == 2)
colorTable[fields[1]] = colorTable[fields[0]];
}
}
}
return new ColorLookUpTable(colorTable);
}
public string FindColorCodeExactMatch(string colorName)
{
string colorCode = null;
if (_colorTable.TryGetValue(colorName, out colorCode))
return colorCode;
return null;
}
public string FindColorCodePartialMatch(string colorName)
{
var colorCode = FindColorCodeExactMatch(colorName);
if (colorCode == null) // No exact match. Need to do work
// very simple partial mathching.
colorCode = _colorTable.Keys.Where(k => k.Contains(colorName)).FirstOrDefault();
return colorCode;
}
}
Usage:
var myColorLookupTable = ColorLookUpTable.LoadFromFile("colorCode.txt");
var colorCode = myColorLookupTable.FindColorCodeExactMatch("White");
var another = myColorLookupTable.FindColorCodePartialMatch("ack");

Related

How do to create string ciphers

I have an error on this part foreach( string code in text ) the error is saying can not convert char to string. how do i convert this to string
my list
class MyCipher : ICipherDecipher
{
private List<Code> alphabet;
public MyCipher()
{
alphabet = new List<Code>();
alphabet.Add(new Code("Aca", " 1234"));
alphabet.Add(new Code("Bb", " 1234"));
alphabet.Add(new Code("C1", " 1234"));
}
this is where im gtting the error on the foreach part , its saying cant convert to string from char
private string Cipher( string text )
{
StringBuilder result = new StringBuilder();
foreach( string code in text )
{
Code element =
alphabet.Where(x => x.MyCode == code.ToString()).SingleOrDefault();
if ( element != null)
{
result.Append(element.MyDecoded);
}
}
return result.ToString();
}
Edited code
class MyCipher : ICipherDecipher
{
private List<Code> alphabet;
public MyCipher()
{
alphabet = new List<Code>();
alphabet.Add(new Code("4", " take 4"));
alphabet.Add(new Code(" ", " a"));
alphabet.Add(new Code("4d", " for 4 days"));
}
public string Cipher(params string[] codes)
{
StringBuilder result = new StringBuilder();
foreach (string code in codes)
{
Code element =
alphabet.Where(x => x.MyCode == code).SingleOrDefault();
if (element != null)
{
result.Append(element.MyDecoded);
}
}
return result.ToString();
}
class Code
{
public string MyCode;
public string MyDecoded;
public Code(string code, string decode)
{
MyCode = code;
MyDecoded = decode;
}
}
}
Button code
public partial class Form1 : Form
{
private ICipherDecipher myCipher;
public Form1()
{
myCipher = new MyCipher();
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string textToBeCiphered = textBox1.Text;
string textCiphered = myCipher.Cipher(textToBeCiphered);
textBox2.Text = textCiphered;
}
}
Change this part of your code:
foreach( char code in text )
{
Code element =
alphabet.Where(x => x.MyCode == code.ToString()).SingleOrDefault();
if ( element != null)
{
result.Append(element.MyDecoded);
}
}
Then everywhere you use code you convert it to string by using code.ToString()
You're iterating over a string (text), so the code variable should be a char, not a string:
foreach( char code in text )
Alternatively, you can use var:
foreach( var code in text )
to make the compiler automatically assign the type it thinks it should be, but you should still be aware of the type it actually is because it impacts the operations the variable supports.
Going a bit deeper into it, some other languages (especially dynamic languages like JavaScript and Python) don't make this distinction but C# (like most other C-like languages) has a char datatype that holds a single element of the text. In the case of C#, that type holds a UTF-16 code unit. (Which is not always the same as a user-visible character, but that's a whole other story).
Based on the discussion in the comments, it seems you want to match the whole string instead of characters of the string. In that case you have two options, depending on what you want to do:
If you want the Cypher method to receive a single string and get the code that matches that string, just get rid of the loop and match against the parameter directly:
private string Cipher( string code )
{
StringBuilder result = new StringBuilder();
Code element =
alphabet.Where(x => x.MyCode == code).SingleOrDefault();
if ( element != null)
{
result.Append(element.MyDecoded);
}
return result.ToString();
}
Alternatively, if you want to pass multiple strings and process all of them, pass an IEnumerable<string> (from System.Collections.Generic) or a derived type such as string[]:
private string Cipher( IEnumerable<string> codes )
{
StringBuilder result = new StringBuilder();
foreach( string code in codes )
{
Code element =
alphabet.Where(x => x.MyCode == code).SingleOrDefault();
if ( element != null)
{
result.Append(element.MyDecoded);
}
}
return result.ToString();
}
// Usage examples:
private string CallSite() {
// (These are just some of the options, other enumerable types
// will work as well as long as they enumerate over strings)
return Cypher( new[] { "Aca", "Bb" });
return Cypher( new List<string> { "Aca", "Bb" });
}
Alternatively, if you replace IEnumerable<string> with params string[] you can call the function as if it had any number of string parameters:
private string Cipher( params string[] codes )
{
// ... (as above)
}
// Usage example:
private string CallSite() {
return Cypher( "Aca", "Bb" );
}
In any of these cases, you can get replace code.ToString() with simply code because it already is a string (and "string".ToString() just returns itself).

Combine multiple lines into 1 string with stream reader

I have a decently sized file (95K lines) that i need to parse through. For the following sample data...
<FIPS>10440<STATE>AL<WFO>BMX
8 32.319 32.316 -86.484 -86.487 32.316 -86.484
32.316 -86.484
102 32.501 31.965 -85.919 -86.497 32.496 -86.248
32.448 -86.181 32.432 -86.189 32.433 -86.125 32.417 -86.116
32.406 -86.049 32.419 -86.023 32.337 -85.991 32.333 -85.969
32.276 -85.919 32.271 -85.986 32.250 -85.999 31.968 -85.995
31.965 -86.302 32.052 -86.307 32.051 -86.406 32.245 -86.410
32.276 -86.484 32.302 -86.491 32.332 -86.475 32.344 -86.497
32.364 -86.492 32.378 -86.463 32.405 -86.460 32.414 -86.396
32.427 -86.398 32.433 -86.350 32.412 -86.310 32.441 -86.325
32.487 -86.314 32.473 -86.288 32.488 -86.260 32.501 -86.263
32.496 -86.248
What I need to do is read from one FIPS to the next FIPS and combine the lines within each group into one giant line like the following...
<FIPS>10440<STATE>AL<WFO>BMX 8 32.319 32.316 -86.484 -86.487 32.316 -86.484 32.316 -86.484...
<FIPS>10440<STATE>AL<WFO>BMX 102 32.501 31.965 -85.919 -86.497 32.496 -86.248 32.448 -86.181...
I currently have the following code (about my 6th variation for the day). What am I missing?
using (var reader = new StreamReader(winterBoundsPath))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine().Trim();
if (!Char.IsLetter(line[0]))
{
if (line.Contains("<FIPS>"))
{
var lineReplace = line.Replace('<', ' ').Replace('>', ' ');
string[] rawData = lineReplace.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
temp = new WinterJsonModel
{
FIPS = rawData[1],
State = rawData[3],
Center = rawData[5],
polyCoords = new List<polyCoordsJsonData>()
};
}
else
{
string[] rawData2 = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (rawData2.Count() > 1)
{
allValues.Add(listPointValue);
listPointValue = new List<string>();
}
// Add values to line
foreach (string value in rawData2)
{
listPointValue.Add(value);
}
}
}
}
reader.Close();
}
Judging from the sample you've given, the line breaks are CRLF characters. This means you really only need to know two things.
1. If the line contains "FIPS" as a string literal enclosed as a tag
2. if you've reached the end of a line that has a carriage return.
I'm going to ignore the JSON bit for now, because it's not part of your question. I'm assuming this means you have the JSON well-handled and if we get these strings how you want them, you've got it from there.
var x = new List<string>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine().Trim();
if (line.Contains("<FIPS>"))
{
x.Add(line.Replace(Environment.NewLine, " "));
}
else
{
var s = String.Concat(x.Last(), line.Replace(Environment.NewLine, string.Empty), " ");
x[x.Count - 1] = s;
}
}
Much of the point here is to separate the organization of the data away from actually putting it into your object. From here, you can iterate through the list in a foreach, creating new objects based on the results of string.Split() on each string in your List<string>.
I've been parsing text files for over 40 years. Code below is sample of what I've done
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Oppgave3Lesson1
{
class Program
{
const string FILENAME = #"c:\temp\test.txt";
static void Main(string[] args)
{
WinterJsonModel data = new WinterJsonModel();
data.ParseFile(FILENAME);
}
}
public class WinterJsonModel
{
public static List<WinterJsonModel> samplData = new List<WinterJsonModel>();
public string fips { get; set; }
public string state { get; set; }
public string wfo { get; set; }
public List<Group> groups = new List<Group>();
public void ParseFile(string winterBoundsPath)
{
WinterJsonModel winterJsonModel = null;
Group group = null;
List<KeyValuePair<decimal, decimal>> values = null;
using (var reader = new StreamReader(winterBoundsPath))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine().Trim();
if (line.Length > 0)
{
if (line.StartsWith("<FIPS>"))
{
winterJsonModel = new WinterJsonModel();
WinterJsonModel.samplData.Add(winterJsonModel);
string[] rawData = line.Split(new char[] { '<', '>' }, StringSplitOptions.RemoveEmptyEntries);
winterJsonModel.fips = rawData[1];
winterJsonModel.state = rawData[3];
winterJsonModel.wfo = rawData[5];
group = null; // very inportant line
}
else
{
decimal[] rawData = line.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries).Select(x => decimal.Parse(x)).ToArray();
//if odd number of numbers in a line
if (rawData.Count() % 2 == 1)
{
group = new Group();
winterJsonModel.groups.Add(group);
group.id = (int)rawData[0];
//remove group number from raw data
rawData = rawData.Skip(1).ToArray();
}
for (int i = 0; i < rawData.Count(); i += 2)
{
group.values.Add(new KeyValuePair<decimal, decimal>(rawData[i], rawData[i + 1]));
}
}
}
}
}
}
}
public class Group
{
public int id { get; set; }
public List<KeyValuePair<decimal, decimal>> values = new List<KeyValuePair<decimal, decimal>>();
}
}

Picking specific numbers out of text file and assign to variable

Someone here at works needs some calculations done from some numbers within a text file. I know how to do the calculation but I haven't worked with text file before. So I spent the night reading and wrote a little something for the first number I needed but it doesn't work.
So here is an example of the file.
So that first number that comes after FSD: 0.264 I need to read that number and save to a variable. The number will always be different per file. Then I need the first 3.4572 number read to a variable. and the last number of that column as well which you don't see here but for the example it can be the last one shown in the image of 3.3852 read and saved to a variable.
Maybe I'm making this much harder than it needs to be but this is what I was playing around with
public partial class FrmTravelTime : Form
{
string file = "";
public FrmTravelTime()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
DialogResult result = openFileDialog1.ShowDialog();
if (result == DialogResult.OK)
{
file = openFileDialog1.FileName;
}
}
private void button2_Click(object sender, EventArgs e)
{
var sLines = File.ReadAllLines(file)
.Where(s => !s.StartsWith("FSD:"))
.Where(s => !string.IsNullOrWhiteSpace(s))
.Select(s => new
{
SValue = Regex.Match(s, "(?<=S)[\\d.]*").Value,
})
.ToArray();
string Value = "";
for (int i = 0; i < sLines.Length; i++)
{
if (sLines[i].SValue == "")
{
Value = (sLines[i].SValue);
}
}
}
}
EDIT FOR #Ramankingdom
So if you see here all lines have an ending column of 0.00 until we get to
3.0164 7793 1 0 0.159 0.02
So what I'd like to do, is edit what we did to skip everything that has a column with 0.00 in that last column and make the first non 0.00 the info.firstvalue so in this case 3.0164
Now I tried this on my own and used
var data = lines.Where(line => (!line.Contains(Data_Start_Point_Identifier) && !line.Contains(FSD__Line_Identifier) && !line.EndsWith("0.00"))).ToList();
But that breaks info.startvalue and data = dataWithAvgVolts[dataWithAvgVolts.Count - 1].Split(splitter);
So I'd figured I'd check with you.
So I tried this but I keep getting invalid data error on info.startvalue
FileInfo info = new FileInfo();
var lines = File.ReadAllLines(row.Cells["colfilelocation"].Value.ToString());
var fsdLine = lines.FirstOrDefault(line =>
line.Contains(FSD__Line_Identifier));
info.FSD = fsdLine.Substring(fsdLine.IndexOf(FSD_Identifier) + FSD_Identifier.Length, 7);
var dataWithAvgVolts = lines.SkipWhile(line => !line.Contains(Data_Start_Point_Identifier)).ToList();
int index =1;
while(index < dataWithAvgVolts.Count())
{
var data = dataWithAvgVolts[index].Split(splitter);
if(data.Count() >1)
{
if(!Convert.ToDouble(data[data.Count()-1]) == 0)
{
//set start info
break;
}
}
index++;
}
the reverse loop you can run to set the end value
Here is the code
class Program
{
const string FSD_Identifier = "FSD:";
const string FSD__Line_Identifier = "Drilling Data";
const string Data_Start_Point_Identifier = "AVG_VOLTS";
static readonly char[] splitter = {' ','\t'};
static void Main(string[] args)
{
var result = GetFileInfo("c:\\sample.txt");
}
private static MyFileInfo GetFileInfo(string path)
{
MyFileInfo info = new MyFileInfo();
try
{
var lines = File.ReadAllLines(path);
var fsdLine = lines.FirstOrDefault(line => line.Contains(FSD__Line_Identifier));
info.FSD = fsdLine.Substring(fsdLine.IndexOf(FSD_Identifier) + FSD_Identifier.Length, 10); // take lenght you can specify or your own logic
var dataWithAvgVolts = lines.SkipWhile(line => !line.Contains(Data_Start_Point_Identifier)).ToList<string>();
if (dataWithAvgVolts.Count() > 1)
{
var data = dataWithAvgVolts[1].Split(splitter);
info.startvalue = Convert.ToDouble(data[0]);
data = dataWithAvgVolts[dataWithAvgVolts.Count-1].Split(splitter);
info.endvalue = Convert.ToDouble(data[0]);
}
}
catch (Exception ex)
{
//logging here
}
return info;
}
}
public class MyFileInfo
{
public string FSD;
public double startvalue;
public double endvalue;
}

Text file to two string arrays in wpf using streamreader

I'm trying to read a text file to two string arrays. Array1 is to be all the odd lines, array2 all the even lines. I then add all the items of array1 to a combobox and when that is selected, or as it gets typed, outputs array2 to a textbox.
So far, I have tried a few methods from here, but the big issue seems to be creating the arrays. I tried to get help here before, but the answers didn't actually answer my question. They must be arrays, not lists (which I tried and worked well). I am really confused by this whole thing and my attempted code is now rubbish:
private void ReadFile(string filePath, string customerPhone, string customerName)
{
string line = string.Empty;
var fileSR = new StreamReader(filePath);
bool number = true;
while((line = fileSR.ReadLine()) != null)
{
if (number)
{
customerPhone(line);
number = false;
}
else
{
customerName(line);
number = true;
}
}
fileSR.Close();
}
I'm losing confidence in this whole process, but I need to find a way to make it work, then I can learn why it does.
You are almost there, just use the List<string>.
private void ReadFile(string filePath, string customerPhone, string customerName)
{
string line = string.Empty;
using (var fileSR = new StreamReader(filePath))
{
bool number = true;
List<string> customerPhone = new List<string>();
List<string> customerName = new List<string>();
while((line = fileSR.ReadLine()) != null)
{
if (number)
{
customerPhone.Add(line);
number = false;
}
else
{
customerName.Add(line);
number = true;
}
}
fileSR.Close();
}
}
If you are interested only in Arrays, you could simply call customerName.ToArray() to convert it to an array.
Linq Solution
Alternatively you could use Linq and do this.
var bothArrays = File.ReadLines("filepath") // Read All lines
.Select((line,index) => new {line, index+1}) // index each line
.GroupBy(x=> x/2) // Convert into two groups
.SelectMany(x=> x.Select(s=>s.line).ToArray()) // Convert it to array
.ToArray();
You should use collections to return data, say IList<String>:
private static void ReadFile(String filePath,
IList<String> oddLines,
IList<String> evenLines) {
oddLines.Clear();
evenLines.Clear();
int index = 1; //TODO: start with 0 or with 1
foreach (String line in File.ReadLines(filePath)) {
if (index % 2 == 0)
evenLines.Add(line);
else
oddLines.Add(line);
index += 1;
}
}
using
List<String> names = new List<String>();
List<String> phones = new List<String>();
ReadFile(#"C:\MyDate.txt", names, phones);
// If you want array representation
String[] myNames = names.ToArray();
String[] myPhones = phones.ToArray();
// Let's print out names
Console.Write(String.Join(Envrironment.NewLine, names));
Please, notice, that using File.ReadLines usually more convenient than StreamReader which should be wrapped in using:
// foreach (String line in File.ReadLines(filePath)) equals to
using (var fileSR = new StreamReader(filePath)) {
while ((line = fileSR.ReadLine()) != null) {
...
}
}
This worked! I have these class level strings:
string cFileName = "customer.txt";
string[] cName = new string[0];
string[] cPhone = new string[0];
And then this in the Window Loaded event, but could be used in it's own method:
private void Window_Loaded_1(object sender, RoutedEventArgs e)
{
//read file on start
int counter = 0;
string line;
StreamReader custSR = new StreamReader(cFileName);
line = custSR.ReadLine();
while (custSR.Peek() != -1)
{
Array.Resize(ref cPhone, cPhone.Length + 1);
cPhone[cPhone.Length - 1] = line;
counter++;
line = custSR.ReadLine();
Array.Resize(ref cName, cName.Length + 1);
cName[cName.Length - 1] = line;
counter++;
line = custSR.ReadLine();
phoneComboBox.Items.Add(cPhone[cPhone.Length - 1]);
}
custSR.Close();
//focus when program starts
phoneComboBox.Focus();
}

Removing quotes in file helpers

I have a .csv file(I have no control over the data) and for some reason it has everything in quotes.
"Date","Description","Original Description","Amount","Type","Category","Name","Labels","Notes"
"2/02/2012","ac","ac","515.00","a","b","","javascript://"
"2/02/2012","test","test","40.00","a","d","c",""," "
I am using filehelpers and I am wondering what the best way to remove all these quotes would be? Is there something that says "if I see quotes remove. If no quotes found do nothing"?
This messes with the data as I will have "\"515.00\"" with unneeded extra quotes(especially since I want in this case it to be a decimal not a string".
I am also not sure what the "javascript" is all about and why it was generated but this is from a service I have no control over.
edit
this is how I consume the csv file.
using (TextReader textReader = new StreamReader(stream))
{
engine.ErrorManager.ErrorMode = ErrorMode.SaveAndContinue;
object[] transactions = engine.ReadStream(textReader);
}
You can use the FieldQuoted attribute described best on the attributes page here. Note that the attribute can be applied to any FileHelpers field (even if it type Decimal). (Remember that the FileHelpers class describes the spec for your import file.. So when you mark a Decimal field as FieldQuoted, you are saying in the file, this field will be quoted.)
You can even specify whether or not the quotes are optional with
[FieldQuoted('"', QuoteMode.OptionalForBoth)]
Here is a console application which works with your data:
class Program
{
[DelimitedRecord(",")]
[IgnoreFirst(1)]
public class Format1
{
[FieldQuoted]
[FieldConverter(ConverterKind.Date, "d/M/yyyy")]
public DateTime Date;
[FieldQuoted]
public string Description;
[FieldQuoted]
public string OriginalDescription;
[FieldQuoted]
public Decimal Amount;
[FieldQuoted]
public string Type;
[FieldQuoted]
public string Category;
[FieldQuoted]
public string Name;
[FieldQuoted]
public string Labels;
[FieldQuoted]
[FieldOptional]
public string Notes;
}
static void Main(string[] args)
{
var engine = new FileHelperEngine(typeof(Format1));
// read in the data
object[] importedObjects = engine.ReadString(#"""Date"",""Description"",""Original Description"",""Amount"",""Type"",""Category"",""Name"",""Labels"",""Notes""
""2/02/2012"",""ac"",""ac"",""515.00"",""a"",""b"","""",""javascript://""
""2/02/2012"",""test"",""test"",""40.00"",""a"",""d"",""c"","""","" """);
// check that 2 records were imported
Assert.AreEqual(2, importedObjects.Length);
// check the values for the first record
Format1 customer1 = (Format1)importedObjects[0];
Assert.AreEqual(DateTime.Parse("2/02/2012"), customer1.Date);
Assert.AreEqual("ac", customer1.Description);
Assert.AreEqual("ac", customer1.OriginalDescription);
Assert.AreEqual(515.00, customer1.Amount);
Assert.AreEqual("a", customer1.Type);
Assert.AreEqual("b", customer1.Category);
Assert.AreEqual("", customer1.Name);
Assert.AreEqual("javascript://", customer1.Labels);
Assert.AreEqual("", customer1.Notes);
// check the values for the second record
Format1 customer2 = (Format1)importedObjects[1];
Assert.AreEqual(DateTime.Parse("2/02/2012"), customer2.Date);
Assert.AreEqual("test", customer2.Description);
Assert.AreEqual("test", customer2.OriginalDescription);
Assert.AreEqual(40.00, customer2.Amount);
Assert.AreEqual("a", customer2.Type);
Assert.AreEqual("d", customer2.Category);
Assert.AreEqual("c", customer2.Name);
Assert.AreEqual("", customer2.Labels);
Assert.AreEqual(" ", customer2.Notes);
}
}
(Note, your first line of data seems to have 8 fields instead of 9, so I marked the Notes field with FieldOptional).
Here’s one way of doing it:
string[] lines = new string[]
{
"\"Date\",\"Description\",\"Original Description\",\"Amount\",\"Type\",\"Category\",\"Name\",\"Labels\",\"Notes\"",
"\"2/02/2012\",\"ac\",\"ac\",\"515.00\",\"a\",\"b\",\"\",\"javascript://\"",
"\"2/02/2012\",\"test\",\"test\",\"40.00\",\"a\",\"d\",\"c\",\"\",\" \"",
};
string[][] values =
lines.Select(line =>
line.Trim('"')
.Split(new string[] { "\",\"" }, StringSplitOptions.None)
.ToArray()
).ToArray();
The lines array represents the lines in your sample. Each " character must be escaped as \" in C# string literals.
For each line, we start off by removing the first and last " characters, then proceed to split it into a collection of substrings, using the "," character sequence as the delimiter.
Note that the above code will not work if you have " characters occurring naturally within your values (even if escaped).
Edit: If your CSV is to be read from a stream, all your need to do is:
var lines = new List<string>();
using (var streamReader = new StreamReader(stream))
while (!streamReader.EndOfStream)
lines.Add(streamReader.ReadLine());
The rest of the above code would work intact.
Edit: Given your new code, check whether you’re looking for something like this:
for (int i = 0; i < transactions.Length; ++i)
{
object oTrans = transactions[i];
string sTrans = oTrans as string;
if (sTrans != null &&
sTrans.StartsWith("\"") &&
sTrans.EndsWith("\""))
{
transactions[i] = sTrans.Substring(1, sTrans.Length - 2);
}
}
I have the same predicament and I replace the quotes when I load the value into my list object:
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
namespace WindowsFormsApplication6
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
LoadCSV();
}
private void LoadCSV()
{
List<string> Rows = new List<string>();
string m_CSVFilePath = "<Path to CSV File>";
using (StreamReader r = new StreamReader(m_CSVFilePath))
{
string row;
while ((row = r.ReadLine()) != null)
{
Rows.Add(row.Replace("\"", ""));
}
foreach (var Row in Rows)
{
if (Row.Length > 0)
{
string[] RowValue = Row.Split(',');
//Do something with values here
}
}
}
}
}
}
This code might help which I developed:
using (StreamReader r = new StreamReader("C:\\Projects\\Mactive\\Audience\\DrawBalancing\\CSVFiles\\Analytix_ABC_HD.csv"))
{
string row;
int outCount;
StringBuilder line=new StringBuilder() ;
string token="";
char chr;
string Eachline;
while ((row = r.ReadLine()) != null)
{
outCount = row.Length;
line = new StringBuilder();
for (int innerCount = 0; innerCount <= outCount - 1; innerCount++)
{
chr=row[innerCount];
if (chr != '"')
{
line.Append(row[innerCount].ToString());
}
else if(chr=='"')
{
token = "";
innerCount = innerCount + 1;
for (; innerCount < outCount - 1; innerCount++)
{
chr=row[innerCount];
if(chr=='"')
{
break;
}
token = token + chr.ToString();
}
if(token.Contains(",")){token=token.Replace(",","");}
line.Append(token);
}
}
Eachline = line.ToString();
Console.WriteLine(Eachline);
}
}

Categories