I have a text file each item is in <> and they are separated by , there is no spaces.
I need to be able to read total number of records and assign this to a variable.
Also I need to assign each item in a row to a variable and the number of that row to a variable. This is so they can be processed later.
I have search the internet but i just seem to be going in circles, any help or source ideas would be appreciated.
Instructions are not really clear, but i give it a try.
using System;
using System.Data;
using System.IO;
using System.Collections.Generic;
class test
{
public Dictionary<int, String> readAndSortFile()
{
StreamReader sr = new StreamReader("file.txt");
Dictionary<int, String> dic = new Dictionary<int, string>();
int loop = 0;
while (!sr.EndOfStream)
{
dic.Add(loop, sr.ReadLine());
loop++;
}
sr.Close();
return dic;
}
}
your result should look like this:
[0] {[0, <a>]}
[1] {[1, <b>]}
[2] {[2, <c>]}
you can get file like this
string file = System.IO.Directory.GetFiles(HttpContext.Current.Server.MapPath(folderName), "*.txt");
FileInfo fi = new FileInfo(file);
// to read all content of this file you can use -
File.ReadAllLines(fi.FullName)
and after this you can use Dictionary to save your data and then you can use it later.
You can read here - http://csharp.net-informations.com/collection/dictionary.htm
Related
before you blame me, yes I did search for this topic/problem before I posted this question.
My Task is to Convert a CSV into a JSON with C# & Newtonsoft.
However im having huge trouble with this Newtonsoft Documentation and dont understand sh*t..
My Idea was to:
Give the Program the Path to the CSV.
Read the CSV with a foreach loop.
Add all the lines to a JSON Object.
Save the JSON File in the same Folder.
This is the Code I got so far:
using System;
using System.IO;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace CSVtoJson
{
class Program
{
static void Main(string[] args)
{
ConvertCsvFileToJsonObject();
string ConvertCsvFileToJsonObject()
{
string path = "C:\\Dev\\CSVtoJSON\\csvtojson.csv";
var csv = new List<string[]>();
var lines = File.ReadAllLines(path);
foreach (string line in lines)
csv.Add(line.Split(','));
var properties = lines[0].Split(',');
var listObjResult = new List<Dictionary<string, string>>();
for (int i = 1; i < lines.Length; i++)
{
var objResult = new Dictionary<string, string>();
for (int j = 0; j < properties.Length; j++)
objResult.Add(properties[j], csv[i][j]);
listObjResult.Add(objResult);
}
return JsonConvert.SerializeObject(listObjResult);
}
}
}
}
However my Function does not seem to do anything, neither do I know how to create a JSON File and save it.. Im very thankful for every comment I'll get since im stuck on this for hours!! :)
Your code for reading csv looks like it could work.
Just use the information from Pavel Anikhouski's comments
Try to change the line below and add a line after it.
from:
ConvertCsvFileToJsonObject();
into:
var jsonString = ConvertCsvFileToJsonObject();
File.WriteAllText(""C:\\Dev\\CSVtoJSON\\output.json"", jsonString);
I am currently working on a project that involves taking a text file with information in it and storing the values into an array for use in determining if a certain book should be "split" based on its ID.
I have declared a string array in the class that is executing the method for this task, and assigning the values from the text file using a StreamReader.
Here is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.Odbc;
using System.Data.OleDb;
using System.IO;
namespace ElectionsPollBooks
{
class dbElections
{
//arrays, ints, for pollbook splits
string[] as_splitNumbers;
int i_splitCount;
public void Process()
{
//opens conenction
OpenConn();
//Gets the precinct info for later parsing
GetDistrictInfo();
//populate splits array
PopulateSplits();
//the hard work
SeperateDataSet();
CloseConn();
}
//...other methods in here, not related
private void PopulateSplits()
{
//sets the count
i_splitCount = 0;
//reads the split file
StreamReader sr_splits = new StreamReader(#"a\file\path\here\.txt");
//begin populating the array
while (sr_splits.ReadLine() != null)
{
//split ID
as_splitNumbers[i_splitCount] = sr_splits.ReadLine();
i_splitCount = i_splitCount + 1;
}
sr_splits.Close();
sr_splits.Dispose();
}
}
}
Visual Studio is telling me at this line:
string[] as_splitNumbers;
That:
"as_splitNumbers is never assigned to and will always return a null value."
When I also run the program, it throws a NullReferenceException during the while loop.
My question is then, what am I doing wrong when it comes to assigning the StreamReader values to the as_splitNumbers array? What am I missing in my logic?
Thank you.
You're not initializing your array with a size.
What you could do if you don't know the size is use List<int>.
Change
string[] as_splitNumbers
to
List<string> as_SplitNumbers = new List<string>();
and your method to:
private void PopulateSplits()
{
//sets the count
i_splitCount = 0;
//reads the split file
using(StreamReader sr_splits = new StreamReader(#"a\file\path\here\.txt"))
{
//begin populating the array
while (sr_splits.ReadLine() != null)
{
//split ID
string split = sr_splits.ReadLine();
as_splitNumbers.Add(split);
i_splitCount = i_splitCount + 1;
}
}
}
If what you're sending it to (SeperateDataSet();?) requires an array, you can cast it by using _asSplitNumbers.ToArray() later on. List<T> just allows you to add without knowing the size.
Try to use a List (System.Enumerable).
Because you donn't know the size of the array before reading.
At the declaration of the variable it will means:
List<string> as_splitNumbers = new List<string>();
in the loop you can simply write
as_splitNumbers.Add(sr_splits.ReadLine())
and it will work!
Your as_splitNumbers array is never allocated. You need to initialize the array with a size first.
string[] as_splitNumbers = new string[SIZE];
However, it seems you should just use a List in your case.
List<string> as_splitNumbers = new List<string>();
Then
//split ID
as_splitNumbers.Add(sr_splits.ReadLine());
So I've been reading that I shouldn't write my own CSV reader/writer, so I've been trying to use the CsvHelper library installed via nuget. The CSV file is a grey scale image, with the number of rows being the image height and the number columns the width. I would like to read the values row-wise into a single List<string> or List<byte>.
The code I have so far is:
using CsvHelper;
public static List<string> ReadInCSV(string absolutePath)
{
IEnumerable<string> allValues;
using (TextReader fileReader = File.OpenText(absolutePath))
{
var csv = new CsvReader(fileReader);
csv.Configuration.HasHeaderRecord = false;
allValues = csv.GetRecords<string>
}
return allValues.ToList<string>();
}
But allValues.ToList<string>() is throwing a:
CsvConfigurationException was unhandled by user code
An exception of type 'CsvHelper.Configuration.CsvConfigurationException' occurred in CsvHelper.dll but was not handled in user code
Additional information: Types that inherit IEnumerable cannot be auto mapped. Did you accidentally call GetRecord or WriteRecord which acts on a single record instead of calling GetRecords or WriteRecords which acts on a list of records?
GetRecords is probably expecting my own custom class, but I'm just wanting the values as some primitive type or string. Also, I suspect the entire row is being converted to a single string, instead of each value being a separate string.
According to #Marc L's post you can try this:
public static List<string> ReadInCSV(string absolutePath) {
List<string> result = new List<string>();
string value;
using (TextReader fileReader = File.OpenText(absolutePath)) {
var csv = new CsvReader(fileReader);
csv.Configuration.HasHeaderRecord = false;
while (csv.Read()) {
for(int i=0; csv.TryGetField<string>(i, out value); i++) {
result.Add(value);
}
}
}
return result;
}
If all you need is the string values for each row in an array, you could use the parser directly.
var parser = new CsvParser( textReader );
while( true )
{
string[] row = parser.Read();
if( row == null )
{
break;
}
}
http://joshclose.github.io/CsvHelper/#reading-parsing
Update
Version 3 has support for reading and writing IEnumerable properties.
The whole point here is to read all lines of CSV and deserialize it to a collection of objects. I'm not sure why do you want to read it as a collection of strings. Generic ReadAll() would probably work the best for you in that case as stated before. This library shines when you use it for that purpose:
using System.Linq;
...
using (var reader = new StreamReader(path))
using (var csv = new CsvReader(reader))
{
var yourList = csv.GetRecords<YourClass>().ToList();
}
If you don't use ToList() - it will return a single record at a time (for better performance), please read https://joshclose.github.io/CsvHelper/examples/reading/enumerate-class-records
Please try this. This had worked for me.
TextReader reader = File.OpenText(filePath);
CsvReader csvFile = new CsvReader(reader);
csvFile.Configuration.HasHeaderRecord = true;
csvFile.Read();
var records = csvFile.GetRecords<Server>().ToList();
Server is an entity class. This is how I created.
public class Server
{
private string details_Table0_ProductName;
public string Details_Table0_ProductName
{
get
{
return details_Table0_ProductName;
}
set
{
this.details_Table0_ProductName = value;
}
}
private string details_Table0_Version;
public string Details_Table0_Version
{
get
{
return details_Table0_Version;
}
set
{
this.details_Table0_Version = value;
}
}
}
You are close. It isn't that it's trying to convert the row to a string. CsvHelper tries to map each field in the row to the properties on the type you give it, using names given in a header row. Further, it doesn't understand how to do this with IEnumerable types (which string implements) so it just throws when it's auto-mapping gets to that point in testing the type.
That is a whole lot of complication for what you're doing. If your file format is sufficiently simple, which yours appear to be--well known field format, neither escaped nor quoted delimiters--I see no reason why you need to take on the overhead of importing a library. You should be able to enumerate the values as needed with System.IO.File.ReadLines() and String.Split().
//pseudo-code...you don't need CsvHelper for this
IEnumerable<string> GetFields(string filepath)
{
foreach(string row in File.ReadLines(filepath))
{
foreach(string field in row.Split(',')) yield return field;
}
}
static void WriteCsvFile(string filename, IEnumerable<Person> people)
{
StreamWriter textWriter = File.CreateText(filename);
var csvWriter = new CsvWriter(textWriter, System.Globalization.CultureInfo.CurrentCulture);
csvWriter.WriteRecords(people);
textWriter.Close();
}
So I am trying to sort a file out in a descending order.
The text file looks something like this:
%[TIMESTAMP=1441737006376][EVENT=agentStateEvent][queue=79651][agentID=61871][extension=22801][state=2][reason=0]%
%[TIMESTAMP=1441737006102][EVENT=agentStateEvent][queue=79654][agentID=62278][extension=22828][state=2][reason=0]%
%[TIMESTAMP=1441737006105][EVENT=CallControlTerminalConnectionTalking][callID=2619][ucid=10000026191441907765][deviceType=1][deviceName=21775][Queue=][Trunk=384:82][TrunkType=1][TrunkState=1][Cause=100][CalledDeviceID=07956679058][CallingDeviceID=21775][extension=21775]%
and basically I want the end result to only output unique values of the timestamp. I have used substring to get rid of the excess text, and it outputs fine as shown below:
[TIMESTAMP=1441737006376]
[TIMESTAMP=1441737006102]
[TIMESTAMP=1441737006105]
however i want it to order in the following order (basically numeric descending to ascending):
[TIMESTAMP=1441737006102]
[TIMESTAMP=1441737006105]
[TIMESTAMP=1441737006376]
I have tried the .sort and .orderBy but not having any joy. I wouldve using this prior to doing any substring formatting wouldve sufficed but clearly not.
Code is as follows:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FedSorter
{
class Program
{
static void Main(string[] args)
{
int counter = 0;
string line;
string readIn = "C:\\Users\\xxx\\Desktop\\Files\\ex1.txt";
System.IO.TextWriter writeOut = new StreamWriter("C:\\Users\\xxx\\Desktop\\Files\\ex1_new.txt");
List<String> list = new List<String>();
// Read the file and display it line by line.
System.IO.StreamReader file = new System.IO.StreamReader(readIn);
string contents = "";
string checkValues = "";
while ((line = file.ReadLine()) != null)
{
string text = line;
text = text.Substring(1, 25);
if (!checkValues.Contains(text))
{
list.Add(text);
Console.WriteLine(text);
writeOut.WriteLine(text);
counter++;
}
contents = text;
checkValues += contents + ",";
}
list = list.OrderBy(x => x).ToList();
writeOut.Close();
file.Close();
orderingFile();
}
public static void orderingFile()
{
string line = "";
string readIn = "C:\\Users\\xxx\\Desktop\\Files\\ex1_new.txt";
System.IO.TextWriter writeOut = new StreamWriter("C:\\Users\\xxx\\Desktop\\Files\\ex1_new2.txt");
List<String> ordering = new List<String>();
// Read the file and display it line by line.
System.IO.StreamReader file = new System.IO.StreamReader(readIn);
while ((line = file.ReadLine()) != null)
{
ordering.OrderBy(x => x).ToList();
ordering.Add(line);
writeOut.WriteLine(line);
}
writeOut.Close();
file.Close();
}
}
}
You are creating a new list and you need to assign it to the variable
list = list.OrderBy(x => x).ToList();
However it doesn't look like you even use list after you create and sort it. Additionally you have the same issue in the orderingFile method with
ordering.OrderBy(x => x).ToList();
However instead of sorting and creating a new list on each line it would be better to use a SortedList<TKey, TValue> that will keep the contents sorted as you add to it.
But again you are not actually using the ordering list after you finish adding to it in the foreach. If you are looking to read the values in a file, sort them and then output them to another file, then you need to do it in that order.
Aside from #juharr's correct answer, you would do well to take advantage of LINQ to simplify your code greatly.
string readIn = "C:\\Users\\xxx\\Desktop\\Files\\ex1.txt";
var timestamps = File.ReadAllLines(readIn)
.Select(l => l.Substring(1, 25))
.Distinct()
.OrderBy(t => t)
.ToArray();
To write out the values, you can either use a foreach on timestamps and write out each line to your TextWriter, or you can use the File class again:
string readOut = "C:\\Users\\xxx\\Desktop\\Files\\ex1_new.txt";
File.WriteAllLines(readOut, timestamps);
//notice I've changed it to ToArray in the first part instead of ToList.
I am using csvhelper to write data to a csv file. I am using C# and VS2010. The object I wish to write is a complex data type object of type Dictionary< long,List<HistoricalProfile>>
Below is the code I am using to write the data to the csv file:
Dictionary<long, List<HistoricalProfile>> profiles
= historicalDataGateway.GetAllProfiles();
var fileName = CSVFileName + ".csv";
CsvWriter writer = new CsvWriter(new StreamWriter(fileName));
foreach (var items in profiles.Values)
{
writer.WriteRecords(items);
}
writer.Dispose();
When it loops the second time I get an error
The header record has already been written. You can't write it more than once.
Can you tell me what I am doing wrong here. My final goal is to have a single csv file with a huge list of records.
Thanks in advance!
Have you seen this library http://www.filehelpers.net/ this makes it very easy to read and write CSV files
Then your code would just be
var profiles = historicalDataGateway.GetAllProfiles(); // should return a list of HistoricalProfile
var engine = new FileHelperEngine<HistoricalProfile>();
// To Write Use:
engine.WriteFile("FileOut.txt", res);
I would go more low-level and iterate through the collections myself:
var fileName = CSVFileName + ".csv";
var writer = new StreamWriter(fileName);
foreach (var items in profiles.Values)
{
writer.WriteLine(/*header goes here, if needed*/);
foreach(var item in items)
{
writer.WriteLine(item.property1 +"," +item.propery2...);
}
}
writer.Close();
If you want to make the routine more useful, you could use reflection to get the list of properties you wish to write out and construct your record from there.