Reading CSV file having Field name in each line? - c#

I am working in an ERP integration software. I need to parse CSV file from HRM application to make an entry.
I am getting the input CSV file like this:
$Emp.No$=123456,$CardNo$=254658,$InTime$="12/11/2013 09:03:05",$OutTime$="12/11/2013 17:25:20"
$Emp.No$=565556,$CardNo$=254689,$InTime$="12/11/2013 09:03:50",$OutTime$="12/11/2013 18:01:11"
The CSV file doesn't have a column name header, instead each field has a field name associated with it inside $FieldName$.
I tried to parse it with CSVHelper. It just works fine, when using ReadFieldsByIndex() method.
Problem:
Some of the columns do not have $InTime$ or $OutTime$. So, reading by index fails. How can I read only available data and how to map according to the field name available in each line.

You haven't got a CSV file there. You have a data file, each line of which contains one or more key/value pairs, separated by commas. The key and value are separated by an = and the key is enclosed by $'s.
Having expressed what you have, that should help you identify a solution:
Don't use a CSV framework.
Read each line at a time from the file.
Split the line on , to give you the key value pairs.
Split the key value pairs on = to give the two parts.
(Optionally) remove the $ from the key name.
You then should have a suitable level of data to transfer these values into whatever destination objects you have.

This will write to the separate file with headers and followed by values.
string file =#"D:\STACKOVERFLOW\csvproblem.txt";
string newfile =#"D:\STACKOVERFLOW\output.txt";
StreamReader sr = new StreamReader(file);
StreamWriter sw = new StreamWriter(newfile);
try{
string header = "";
StringBuilder sb = new StringBuilder();
StringBuilder sb_header = new StringBuilder();
bool recordHeader = true;
while(sr.EndOfStream==false){
string readLine = sr.ReadLine();
string[] split = readLine.Split(',');
sb = new StringBuilder();
foreach (string str in split)
{
if (recordHeader)
{
if (str.IndexOf('$') < str.LastIndexOf('$'))
{
sb_header.AppendFormat("{0},",
str.Substring(str.IndexOf('$'),str.IndexOf('$')+str.LastIndexOf('$')+1));
}
}
sb.AppendFormat("{0},", str.Substring(str.IndexOf('=')+1));
}
if (recordHeader)
{
sw.WriteLine(sb_header.ToString().Trim(','));
}
sw.WriteLine(sb.ToString().Trim(','));
recordHeader = false;
}
}
finally{
sr.Close();
sw.Close();
}

Related

Read and Write INI file without sections

There is an ini file format
########## Order section ##########
KeyOne=Value1
....
....
....
...
KeyMore=999
Key = 88888*
......
......
......
how can I edit what is behind the = ?
I tried in many ways, but since there are no sections in the ini file, I can’t figure out how to change the values Value1 and 999 and 88888*?
Tried splitting strings with split "=" , but failed to change values. and also add new lines to the file? after Key = 88888*
1.If there are spaces or text in the textbox, then it does not work.
const string filepath = #"C:\Users\123\Desktop\Config.ini";
string text = File.ReadAllText(filepath);
const string PATTERN = #"KeyOne=(?<Number>[\d\.]+)";
Match match = Regex.Match(text, PATTERN, RegexOptions.IgnoreCase);
if (match.Success)
{
int index = match.Groups["Number"].Index;
int length = match.Groups["Number"].Length;
text = text.Remove(index, length);
text = text.Insert(index, Program.form1.textBox11.Text);
File.WriteAllText(filepath, text);
}
An INI file has a well defined structure composed by one or many [Sections] and zero or many pairs of [Key]=[Value] under each section. A file without at least a section is not a proper INI file and the standard windows API GetPrivateProfileString and WritePrivateProfileString are not able to read a file with that format.
However, your file is a lot simpler than a standard INI file. It is just composed by pairs of [Key]=[Value] so it is a naturally perfect fit for a Dictionary<string, string>
Reading it coud be simple as
Dictionary<string, string> GetConfigData(string fileName)
{
Dictionary<string, string> data = new Dictionary<string, string>();
foreach (string line in File.ReadLines(fileName))
{
var lineData = line.Split('=');
data.Add(lineData[0], lineData[1]);
}
return data;
}
and writing back that dictionary is even simpler
void WriteConfigData(string fileName, Dictionary<string, string> data)
{
File.WriteAllLines(fileName, data.Select(z => $"{z.Key}={z.Value}{Environment.NewLine}"));
}
Now if you want to change some value you could have
var data = GetConfigData("yourbadinifile.ini");
data["KeyValue"] = "a new value";
WriteConfigData("yourbadinifile.ini", data);
Warning: In the examples above there is no error checking. A robust solution should check if the file passed to the read method exists and if the split operation produces an array of two elements. Consider also that checking for binary files is also an unhandled problem and with complex solutions. So we could also consider to let exceptions bubble up to the client caller.

How can I use C# to search an XML file for specific words?

I'm very new to C# and XML files in general, but currently I have an XML file that still has some html markup in it (&amp, ;quot;, etc.) and I want to read through the XML file and remove all of those so it becomes easily readable. I can open and print the file to the console with no issue, but I'm stumped trying to search for those specific strings and remove them.
One way to do this would be to put all the words you want to remove into an array, and then use the Replace method to replace them with empty strings:
var xmlFilePath = #"c:\temp\original.xml";
var newFilePath = #"c:\temp\modified.xml";
var wordsToRemove = new[] {"&amp", ";quot;"};
// Read existing xml file
var fileContents = File.ReadAllText(xmlFilePath);
// Remove words
foreach (var word in wordsToRemove)
{
fileContents = fileContents.Replace(word, "");
}
// Create new file with words removed
File.WriteAllText(newFilePath, fileContents);
I suppose you are looking for this: https://learn.microsoft.com/en-us/dotnet/api/system.web.httputility.htmldecode?view=netcore-3.1
Converts a string that has been HTML-encoded for HTTP transmission into a decoded string.
// Encode the string.
string myEncodedString = HttpUtility.HtmlEncode(myString);
Console.WriteLine($"HTML Encoded string is: {myEncodedString}");
StringWriter myWriter = new StringWriter();
// Decode the encoded string.
HttpUtility.HtmlDecode(myEncodedString, myWriter);
string myDecodedString = myWriter.ToString();
Console.Write($"Decoded string of the above encoded string is: {myDecodedString}");
Your string is html encoded, probably for transmission over network. So there is a built in method to decode it.

Reading from a string List<>

my application basically reads a CSV file which will always have the same format and I need to application to create a CSV file with different formatting. Reading and writing CSV file is not the issue, however the problem I am having is reading from the string array containing all the data from the CSV file.
For example: From the below, how can I get the system to get me the 4th value only: Value Date
[0] = "\"Book Date\",\"Reference\",\"Descript\",\"Value Date\",\"Debit\",\"Credit\",\"Closing Balance\""
This is how I am reading from CSV file.
openFileDialog1.ShowDialog();
var reader = new StreamReader(File.OpenRead(openFileDialog1.FileName));
List<string> searchList = new List<string>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
searchList.Add(line);
}
Use String.Split. It returns a string array that contains the substrings in this instance that are delimited by elements of a specified string or Unicode character array.
var splitStrings = line.Split(",");
if (splitStrings.Length > 4)
{
searchList.Add(splitStrings[3]);
}
split the line and get the 4th value like this:
searchList.Add(line.Split(',')[3]);

C# CSV file to array/list

I want to read 4-5 CSV files in some array in C#
I know that this question is been asked and I have gone through them...
But my use of CSVs is too much simpler for that...
I have csv fiels with columns of following data types....
string , string
These strings are without ',' so no tension...
That's it. And they aren't much big. Only about 20 records in each.
I just want to read them into array of C#....
Is there any very very simple and direct way to do that?
To read the file, use
TextReader reader = File.OpenText(filename);
To read a line:
string line = reader.ReadLine()
then
string[] tokens = line.Split(',');
to separate them.
By using a loop around the two last example lines, you could add each array of tokens into a list, if that's what you need.
This one includes the quotes & commas in fields. (assumes you're doing a line at a time)
using Microsoft.VisualBasic.FileIO; //For TextFieldParser
// blah blah blah
StringReader csv_reader = new StringReader(csv_line);
TextFieldParser csv_parser = new TextFieldParser(csv_reader);
csv_parser.SetDelimiters(",");
csv_parser.HasFieldsEnclosedInQuotes = true;
string[] csv_array = csv_parser.ReadFields();
Here is a simple way to get a CSV content to an array of strings. The CSV file can have double quotes, carriage return line feeds and the delimiter is a comma.
Here are the libraries that you need:
System.IO;
System.Collection.Generic;
System.IO is for FileStream and StreamReader class to access your file. Both classes implement the IDisposable interface, so you can use the using statements to close your streams. (example below)
System.Collection.Generic namespace is for collections, such as IList,List, and ArrayList, etc... In this example, we'll use the List class, because Lists are better than Arrays in my honest opinion. However, before I return our outbound variable, i'll call the .ToArray() member method to return the array.
There are many ways to get content from your file, I personally prefer to use a while(condition) loop to iterate over the contents. In the condition clause, use !lReader.EndOfStream. While not end of stream, continue iterating over the file.
public string[] GetCsvContent(string iFileName)
{
List<string> oCsvContent = new List<string>();
using (FileStream lFileStream =
new FileStream(iFilename, FileMode.Open, FileAccess.Read))
{
StringBuilder lFileContent = new StringBuilder();
using (StreamReader lReader = new StreamReader(lFileStream))
{
// flag if a double quote is found
bool lContainsDoubleQuotes = false;
// a string for the csv value
string lCsvValue = "";
// loop through the file until you read the end
while (!lReader.EndOfStream)
{
// stores each line in a variable
string lCsvLine = lReader.ReadLine();
// for each character in the line...
foreach (char lLetter in lCsvLine)
{
// check if the character is a double quote
if (lLetter == '"')
{
if (!lContainsDoubleQuotes)
{
lContainsDoubleQuotes = true;
}
else
{
lContainsDoubleQuotes = false;
}
}
// if we come across a comma
// AND it's not within a double quote..
if (lLetter == ',' && !lContainsDoubleQuotes)
{
// add our string to the array
oCsvContent.Add(lCsvValue);
// null out our string
lCsvValue = "";
}
else
{
// add the character to our string
lCsvValue += lLetter;
}
}
}
}
}
return oCsvContent.ToArray();
}
Hope this helps! Very easy and very quick.
Cheers!

Searching strings in txt file

I have a .txt file with a list of 174 different strings. Each string has an unique identifier.
For example:
123|this data is variable|
456|this data is variable|
789|so is this|
etc..
I wish to write a programe in C# that will read the .txt file and display only one of the 174 strings if I specify the ID of the string I want. This is because in the file I have all the data is variable so only the ID can be used to pull the string. So instead of ending up with the example about I get just one line.
eg just
123|this data is variable|
I seem to be able to write a programe that will pull just the ID from the .txt file and not the entire string or a program that mearly reads the whole file and displays it. But am yet to wirte on that does exactly what I need. HELP!
Well the actual string i get out from the txt file has no '|' they were just in the example. An example of the real string would be: 0111111(0010101) where the data in the brackets is variable. The brackets dont exsist in the real string either.
namespace String_reader
{
class Program
{
static void Main(string[] args)
{
String filepath = #"C:\my file name here";
string line;
if(File.Exists(filepath))
{
StreamReader file = null;
try
{
file = new StreamReader(filepath);
while ((line = file.ReadLine()) !=null)
{
string regMatch = "ID number here"; //this is where it all falls apart.
Regex.IsMatch (line, regMatch);
Console.WriteLine (line);// When program is run it just displays the whole .txt file
}
}
}
finally{
if (file !=null)
file.Close();
}
}
Console.ReadLine();
}
}
}
Use a Regex. Something along the lines of Regex.Match("|"+inputString+"|",#"\|[ ]*\d+\|(.+?)\|").Groups[1].Value
Oh, I almost forgot; you'll need to substitute the d+ for the actual index you want. Right now, that'll just get you the first one.
The "|" before and after the input string makes sure both the index and the value are enclosed in a | for all elements, including the first and last. There's ways of doing a Regex without it, but IMHO they just make your regex more complicated, and less readable.
Assuming you have path and id.
Console.WriteLine(File.ReadAllLines(path).Where(l => l.StartsWith(id + "|")).FirstOrDefault());
Use ReadLines to get a string array of lines then string split on the |
You could use Regex.Split method
FileInfo info = new FileInfo("filename.txt");
String[] lines = info.OpenText().ReadToEnd().Split(' ');
foreach(String line in lines)
{
int id = Convert.ToInt32(line.Split('|')[0]);
string text = Convert.ToInt32(line.Split('|')[1]);
}
Read the data into a string
Split the string on "|"
Read the items 2 by 2: key:value,key:value,...
Add them to a dictionary
Now you can easily find your string with dictionary[key].
first load the hole file to a string.
then try this:
string s = "123|this data is variable| 456|this data is also variable| 789|so is this|";
int index = s.IndexOf("123", 0);
string temp = s.Substring(index,s.Length-index);
string[] splitStr = temp.Split('|');
Console.WriteLine(splitStr[1]);
hope this is what you are looking for.
private static IEnumerable<string> ReadLines(string fspec)
{
using (var reader = new StreamReader(new FileStream(fspec, FileMode.Open, FileAccess.Read, FileShare.Read)))
{
while (!reader.EndOfStream)
yield return reader.ReadLine();
}
}
var dict = ReadLines("input.txt")
.Select(s =>
{
var split = s.Split("|".ToArray(), 2);
return new {Id = Int32.Parse(split[0]), Text = split[1]};
})
.ToDictionary(kv => kv.Id, kv => kv.Text);
Please note that with .NET 4.0 you don't need the ReadLines function, because there is ReadLines
You can now work with that as any dictionary:
Console.WriteLine(dict[12]);
Console.WriteLine(dict[999]);
No error handling here, please add your own
You can use Split method to divide the entire text into parts sepparated by '|'. Then all even elements will correspond to numbers odd elements - to strings.
StreamReader sr = new StreamReader(filename);
string text = sr.ReadToEnd();
string[] data = text.Split('|');
Then convert certain data elements to numbers and strings, i.e. int[] IDs and string[] Strs. Find the index of the given ID with idx = Array.FindIndex(IDs, ID.Equals) and the corresponding string will be Strs[idx]
List <int> IDs;
List <string> Strs;
for (int i = 0; i < data.Length - 1; i += 2)
{
IDs.Add(int.Parse(data[i]));
Strs.Add(data[i + 1]);
}
idx = Array.FindIndex(IDs, ID.Equals); // we get ID from input
answer = Strs[idx];

Categories

Resources