Insert a running number in textfile in c# - c#

I would like to add a running number inside a textfile but it must be in specific column. etc: line 1, column 15.
original file : it has data name,profession,birthdate,status
john teacher 1988 married
marcel engineer1976 single
emi professo1975 married
convert file:insert running number between birthdate and status
john teacher 1988 D001married
marcel engineer1976 D002single
emi professo1975 D003married
note : every data start at their own specific column. name start at column 1, profession start at column 7,birthday start at column 15 and status start at column 20.
how do I do this using c#.

Loop through each row of the text and run something like this on each line:
const int STATUS_START_COLUMN_NUM = 19;
line = line.Substring(0,STATUS_START_COLUMN_NUM - 1) + "D" + String.Format("{0:000}",i) + line.Substring(STATUS_START_COLUMN_NUM);
i++;

This is exactly what String.Insert() is for.
List<string> data = new List<string>
{
"john teacher 1988 married",
"marcel engineer1976 single",
"emi professo1975 married"
};
Console.WriteLine("Before: ");
data.ForEach(Console.WriteLine);
Console.WriteLine();
int runningNumber = 1;
for (int i = 0; i < data.Count; i++)
{
data[i] = data[i].Insert(20, String.Format("D{0:000}", runningNumber));
runningNumber++;
}
Console.WriteLine("After: ");
data.ForEach(Console.WriteLine);
Results:
Before:
john teacher 1988 married
marcel engineer1976 single
emi professo1975 married
After:
john teacher 1988 D001married
marcel engineer1976 D002single
emi professo1975 D003married

Here's a sample solution that makes use of StringBuilder and TextWriter with the use of string.Format() and additional functionality Truncate to get the proper length of string.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace ConsoleApplicationStringBuilder
{
class Program
{
static void Main(string[] args)
{
/*
john teacher 1988 married
marcel engineer1976 single
emi professo1975 married
*/
StringBuilder sb = new StringBuilder();
sb.AppendLine(string.Format("{0, -7}{1, -8}{2, -5}{3}", Truncate("john", 6), Truncate("teacher", 8), 1988, Truncate("married", 7)));
sb.AppendLine(string.Format("{0, -7}{1, -8}{2, -5}{3}", Truncate("marcel", 6), Truncate("engineer", 8), 1976, Truncate("single", 7)));
sb.AppendLine(string.Format("{0, -7}{1, -8}{2, -5}{3}", Truncate("emi", 6), Truncate("professor", 8), 1975, Truncate("married", 7)));
string s = sb.ToString();
Console.WriteLine(s);
//Write to file
using (TextWriter tw = File.CreateText("C:\\test.txt"))
{
tw.Write(s);
tw.Flush();
tw.Close();
}
Console.WriteLine("File written to C:\\test.txt"); ;
Console.ReadLine();
}
static public string Truncate(string value, int max)
{
return value.Substring(0, Math.Min(value.Length, max));
}
}
}
What happens here are the following:
Truncate each string you passed on Truncate function to get only the string within the given maximum value
Pass each value to string.Format() padding each item with the blank spaces needed
Build all the string via StringBuilder and convert it to a string
Create a text file and assign it TextWriter filling it with the string that was built previously

Related

Accessing the elements of an array

I have a task to create a program to read from a file and check which employees have worked together for longer. I have already created the code to read from a file and store the data in an array. You can check it below:
string path;
do
{
Console.Write("Please enter the path of the file: ");
path = Console.ReadLine();
if (!File.Exists(path))
{
Console.WriteLine("The path is not correct.");
}
} while (!File.Exists(path));
string[] lines = File.ReadAllLines(path);
foreach (string line in lines) //just to check if the program can read from a file
{
Console.WriteLine(line);
}
Console.WriteLine();
for (int i = 0; i < lines.Length; i++)
{
string[] values = lines[i].ToString().Split(',');
foreach (string el in values) //just to check if the value are stored inside the array
{
Console.Write(el + " ");
}
}
Console.ReadLine();
This code gives this result:
Please enter the path of the file: C:\Users\...
143, 12, 2013-11-01, 2014-01-05
145, 10, 2009/01/01, 2011/04/27
140, 10, 2009.03.01, 2011.04.27
111, 10, 2009.03.01, NULL
143 12 2013-11-01 2014-01-05
145 10 2009/01/01 2011/04/27
140 10 2009.03.01 2011.04.27
111 10 2009.03.01 NULL
(the columns represent: employerID, projectID, DateFrom and DateTo respectively). Now I need to create a code that calculates the time that 2 employees have worked on the same project (using project id and the dates to calculate the period of work together). I need some help to understand how I can do that. Thank you!
This could be a good start:
Create a class EmployeeWorkPeriod with the 4 fields
Parse values into data types like int and DateTime (and DateTime?).
Once you have these object you can start writing you program logic.

Splitting article by sentences using delimiters

I have a small assignment where I have an article in a format that is like this
<REUTERS TOPICS="NO" LEWISSPLIT="TRAIN" CGISPLIT="TRAINING-SET" OLDID="5545" NEWID="2">
<TITLE>STANDARD OIL <SRD> TO FORM FINANCIAL UNIT</TITLE>
<DATELINE> CLEVELAND, Feb 26 - </DATELINE><BODY>Standard Oil Co and BP North America
Inc said they plan to form a venture to manage the money market
borrowing and investment activities of both companies.
BP North America is a subsidiary of British Petroleum Co
Plc <BP>, which also owns a 55 pct interest in Standard Oil.
The venture will be called BP/Standard Financial Trading
and will be operated by Standard Oil under the oversight of a
joint management committee.
Reuter
</BODY></TEXT>
</REUTERS>
and I am writing it to a new xml file with this format
<article id= some id >
<subject>articles subject </subject>
<sentence> sentence #1 </sentence>
.
.
.
<sentence> sentence #n </sentence>
</article>
I have written a code that does all of this and works fine.
The problem is that I am splitting sentences by using the delimiter ., but if the there is a number like 2.00, the code thinks that 2 is a sentence and 00 is a different sentence.
Does anyone have any idea on how to identify sentences better so it will keep the numbers and such in same sentence?
Without having to go over all of the array?
Is there a way I can have the string.Split() method ignore the split if there is a number before and after the delimiter?
My code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Data;
using System.Xml;
namespace project
{
class Program
{
static void Main(string[] args)
{
string[] lines = System.IO.File.ReadAllLines(#"path");
string body = "";
REUTERS article = new REUTERS();
string sentences = "";
for (int i = 0; i<lines.Length;i++){
string line = lines[i];
// finding the first tag of the article
if (line.Contains("<REUTERS"))
{
//extracting the id from the tag
int Id = line.IndexOf("NEWID=\"") + "NEWID=\"".Length;
article.NEWID = line.Substring(Id, line.Length-2 - Id);
}
if (line.Contains("TITLE"))
{
string subject = line;
subject = subject.Replace("<TITLE>", "").Replace("</TITLE>", "");
article.TITLE = subject;
}
if( line.Contains("<BODY"))
{
int startLoc = line.IndexOf("<BODY>") + "<BODY>".Length;
sentences = line.Substring(startLoc, line.Length - startLoc);
while (!line.Contains("</BODY>"))
{
i++;
line = lines[i];
sentences = sentences +" " + line;
}
int endLoc = sentences.IndexOf("</BODY>");
sentences = sentences.Substring(0, endLoc);
char[] delim = {'.'};
string[] sentencesSplit = sentences.Split(delim);
using (System.IO.StreamWriter file =
new System.IO.StreamWriter(#"path",true))
{
file.WriteLine("<articles>");
file.WriteLine("\t <article id = " + article.NEWID + ">");
file.WriteLine("\t \t <subject>" + article.TITLE + "</subject>");
foreach (string sentence in sentencesSplit)
{
file.WriteLine("\t \t <sentence>" + sentence + "</sentence>");
}
file.WriteLine("\t </article>");
file.WriteLine("</articles>");
}
}
}
}
public class REUTERS
{
public string NEWID;
public string TITLE;
public string Body;
}
}
}
ok so i found a solution using the ideas i recieved here
i used the overload method of split like this
.Split(new string[] { ". " }, StringSplitOptions.None);
and it looks much better now
You can also use a regular expression that looks for the sentence terminators with white space:
var pattern = #"(?<=[\.!\?])\s+";
var sentences = Regex.Split(input, pattern);
foreach (var sentence in sentences) {
//do something with the sentence
var node = string.Format("\t \t <sentence>{0}</sentence>", sentence);
file.WriteLine(node);
}
Note that this applies to the English language as there may be other rules for sentences in other languages.
The Following example
using System;
using System.Text.RegularExpressions;
public class Program
{
public static void Main()
{
var input = #"Standard Oil Co and BP North America
Inc said they plan to form a venture to manage the money market
borrowing and investment activities of both companies.
BP North America is a subsidiary of British Petroleum Co
Plc <BP>, which also owns a 55 pct interest in Standard Oil.
The venture will be called BP/Standard Financial Trading
and will be operated by Standard Oil under the oversight of a
joint management committee.";
var pattern = #"(?<=[\.!\?])\s+";
var sentences = Regex.Split(input, pattern);
foreach (var sentence in sentences)
{
var innerText = sentence.Replace("\n", " ").Replace('\t', ' ');
//do something with the sentence
var node = string.Format("\t \t <sentence>{0}</sentence>", innerText);
Console.WriteLine(node);
}
}
}
Produces this output
<sentence>Standard Oil Co and BP North America Inc said they plan to form a venture to manage the money market borrowing and investment activities of both companies.</sentence>
<sentence>BP North America is a subsidiary of British Petroleum Co Plc <BP>, which also owns a 55 pct interest in Standard Oil.</sentence>
<sentence>The venture will be called BP/Standard Financial Trading and will be operated by Standard Oil under the oversight of a joint management committee.</sentence>
I would make a list of all index points of the '.' characters.
foreach index point, check each side for numbers, if numbers are on both sides, remove the index point from the list.
Then when you are outputting simply use the substring functions with the remaining index points to get each sentence as an individual.
Bad quality code follows (it's late):
List<int> indexesToRemove = new List<int>();
int count=0;
foreach(int indexPoint in IndexPoints)
{
if((sentence.elementAt(indexPoint-1)>='0' && elementAt(indexPoint-1<='9')) && (sentence.elementAt(indexPoint+1)>='0' && elementAt(indexPoint+1<='9')))
indexesToRemove.Add(count);
count++;
}
The next line is so that we do not have to alter the removal number as we traverse the list in the last step.
indexesToRemove = indexesToRemove.OrderByDescending();
Now we simply remove all the locations of the '.'s that have numbers on either side.
foreach(int indexPoint in indexesToRemove)
{
IndexPoints.RemoveAt(indexPoint);
}
Now when you read out the sentences into the new file format you just loop sentences.substring(lastIndexPoint+1, currentIndexPoint)
Spent much time on this - thought you might like to see it as it really doesn't use any awkward code whatsoever - it is producing output 99% similar to yours.
<articles>
<article id="2">
<subject>STANDARD OIL <SRD> TO FORM FINANCIAL UNIT</subject>
<sentence>Standard Oil Co and BP North America</sentence>
<sentence>Inc said they plan to form a venture to manage the money market</sentence>
<sentence>borrowing and investment activities of both companies.</sentence>
<sentence>BP North America is a subsidiary of British Petroleum Co</sentence>
<sentence>Plc <BP>, which also owns a 55.0 pct interest in Standard Oil.</sentence>
<sentence>The venture will be called BP/Standard Financial Trading</sentence>
<sentence>and will be operated by Standard Oil under the oversight of a</sentence>
<sentence>joint management committee.</sentence>
</article>
</articles>
The console app is as follows:
using System.Xml;
using System.IO;
namespace ReutersXML
{
class Program
{
static void Main()
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("reuters.xml");
var reuters = xmlDoc.GetElementsByTagName("REUTERS");
var article = reuters[0].Attributes.GetNamedItem("NEWID").Value;
var subject = xmlDoc.GetElementsByTagName("TITLE")[0].InnerText;
var body = xmlDoc.GetElementsByTagName("BODY")[0].InnerText;
string[] sentences = body.Split(new string[] { System.Environment.NewLine },
System.StringSplitOptions.RemoveEmptyEntries);
using (FileStream fileStream = new FileStream("reuters_new.xml", FileMode.Create))
using (StreamWriter sw = new StreamWriter(fileStream))
using (XmlTextWriter xmlWriter = new XmlTextWriter(sw))
{
xmlWriter.Formatting = Formatting.Indented;
xmlWriter.Indentation = 4;
xmlWriter.WriteStartElement("articles");
xmlWriter.WriteStartElement("article");
xmlWriter.WriteAttributeString("id", article);
xmlWriter.WriteElementString("subject", subject);
foreach (var s in sentences)
if (s.Length > 10)
xmlWriter.WriteElementString("sentence", s);
xmlWriter.WriteEndElement();
}
}
}
}
I hope you like it :)

How to get the last characters of a string

I would like to ask question about formatting strings in C#. Basically I only want to view the last n characters in the string.
For example: string = ("1201 OFFICE PARK RD WDM, APT 708, FLR 2, BLDG 7")
now what i want is just to show:
"APT 708, FLR 2, BLDG 7"
I can actually use a remove method but what if the string.length is not always the same as mentioned in the example? like if I only have "1201 OFFICE PARK" or "FLR 2,BLDG 7" Appreciate any help on this. Thanks!
Following your comments, you can work out n.
string s = "1201 OFFICE PARK RD WDM, APT 708, FLR 2, BLDG 7";
string subS = s.SubString(s.IndexOf(",") + 1).TrimStart();
or if this string is fixed format:
string subS = s.SubString(s.IndexOf(",") + 2);
public string GetEnd (string input, int n)
{
return input.SubString (input.Length - n, n);
}
this should give you the desired result, as long as you know n

c# split integers and strings from text file and add them to two different listbox

I'm trying to parse sales information from text file and put them to two listboxes
The text file contains this information:
Sam West $10,000.00
Mae West $125,900.00
North West $2,000.00
Michelle Smith $25,000.00
John Smith $12,500.00
Martin Smith $19,900.00
David Sampson $32,500.00
Joan Sampson $5,990.00
Sam Sampson $10,000.00
Mae Sampson $125,500.00
North Sampson $2,000.00
Michelle West $25,000.00
John Johnson $12,500.00
Martin Johnson $19,900.00
David Johnson $32,500.00
Joan Johnson $5,990.00
Sam Hartmann $10,000.00
Mae Hartmann $125,100.00
North Hartmann $2,000.00
Michelle Hartmann $25,000.00
John Johnson $12,500.00
Martin Hartmann $19,900.00
David Hartmann $32,500.00
Joan Hartmann $5,990.00
and my code is here
private void btnReadInSalesData_Click(object sender, EventArgs e)
{
StreamReader reader = new StreamReader("SalesNumbers.txt");
List<int> numbers = new List<int>();
int intTotal = 0;
while (!reader.EndOfStream)
{
string line = reader.ReadLine();
string[] tokens = line.Split(new char[] { '$' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string s in tokens)
{
if (int.TryParse(s, out intTotal))
numbers.Add(intTotal);
lstTotalSales.Items.Add(s);
}
}
And here is a picture of the output
http://s24.postimg.org/ylm8vl9at/output.jpg
Simply I want to read the text file and add the total sales to lstTotalSales listbox and add The Full name to lstNames list box.
Thank you
You missed to split each line into name and value.
Try this:
string[] lines = File.ReadAllLines("SalesNumbers.txt");
foreach (string line in lines) {
string[] s = line.Split("$".ToCharArray());
if (s.Length<2) { /* */ }
double d;
if (!double.TryParse(s[1], NumberStyles.Float, CultureInfo.CurrentCulture, out d)) {
// Handle if not a number
}
lstNames.Items.Add(s[0]);
lstTotalSales.Items.Add(d);
}
EDIT
While we convert the value to a double, you have to add the currency symbol when displaying the value:
string text = "$" + value.ToString();
Please note that we imply always splitting with the $ symbol.
Assuming multiple currency symbols, you have to keep track of the split symbol:
string currencySymbols = "$€Y";
//...
int index = line.IndexOfAny(currencySymbols.ToCharArray());
if (index<0) {} //Nothing found
char usedSymbol = line[index]; // <- found symbol
string name = line.Substring(0, index);
string value = line.Substring(index+1);
//...
You should use decimal instead of int, because your numbers are not integers.
You should also change your logic within the loop. I think it should be more like that:
foreach (string s in tokens)
{
if (decimal.TryParse(s, out decTotal))
{
numbers.Add(decTotal);
lstTotalSales.Items.Add(s);
}
else
{
lstNames.Items.Add(s);
}
}

Array help Index out of range exception was unhandled

I am trying to populate combo boxes from a text file using comma as a delimiter everything was working fine, but now when I debug I get the "Index out of range exception was unhandled" warning. I guess I need a fresh pair of eyes to see where I went wrong, I commented on the line that gets the error //Fname = fields[1];
private void xViewFacultyMenuItem_Click(object sender, EventArgs e)
{
const string fileStaff = "source\\Staff.txt";
const char DELIM = ',';
string Lname, Fname, Depart, Stat, Sex, Salary, cDept, cStat, cSex;
double Gtotal;
string recordIn;
string[] fields;
cDept = this.xDeptComboBox.SelectedItem.ToString();
cStat = this.xStatusComboBox.SelectedItem.ToString();
cSex = this.xSexComboBox.SelectedItem.ToString();
FileStream inFile = new FileStream(fileStaff, FileMode.Open, FileAccess.Read);
StreamReader reader = new StreamReader(inFile);
recordIn = reader.ReadLine();
while (recordIn != null)
{
fields = recordIn.Split(DELIM);
Lname = fields[0];
Fname = fields[1]; // this is where the error appears
Depart = fields[2];
Stat = fields[3];
Sex = fields[4];
Salary = fields[5];
Fname = fields[1].TrimStart(null);
Depart = fields[2].TrimStart(null);
Stat = fields[3].TrimStart(null);
Sex = fields[4].TrimStart(null);
Salary = fields[5].TrimStart(null);
Gtotal = double.Parse(Salary);
if (Depart == cDept && cStat == Stat && cSex == Sex)
{
this.xEmployeeListBox.Items.Add(recordIn);
}
recordIn = reader.ReadLine();
}
Source file --
Anderson, Kristen, Accounting, Assistant, Female, 43155
Ball, Robin, Accounting, Instructor, Female, 42723
Chin, Roger, Accounting, Full, Male,59281
Coats, William, Accounting, Assistant, Male, 45371
Doepke, Cheryl, Accounting, Full, Female, 52105
Downs, Clifton, Accounting, Associate, Male, 46887
Garafano, Karen, Finance, Associate, Female, 49000
Hill, Trevor, Management, Instructor, Male, 38590
Jackson, Carole, Accounting, Instructor, Female, 38781
Jacobson, Andrew, Management, Full, Male, 56281
Lewis, Karl, Management, Associate, Male, 48387
Mack, Kevin, Management, Assistant, Male, 45000
McKaye, Susan, Management, Instructor, Female, 43979
Nelsen, Beth, Finance, Full, Female, 52339
Nelson, Dale, Accounting, Full, Male, 54578
Palermo, Sheryl, Accounting, Associate, Female, 45617
Rais, Mary, Finance, Instructor, Female, 27000
Scheib, Earl, Management, Instructor, Male, 37389
Smith, Tom, Finance, Full, Male, 57167
Smythe, Janice, Management, Associate, Female, 46887
True, David, Accounting, Full, Male, 53181
Young, Jeff, Management, Assistant, Male, 43513
For the sake of anyone who doesn't want to look at the mammoth code you've posted, here's the relevant bit:
while (recordIn != null)
{
fields = recordIn.Split(DELIM);
Lname = fields[0];
Fname = fields[1]; // this is where the error appears
Given the exception you've seen, that basically means that recordIn doesn't contain the delimiter DELIM (a comma). I suggest you explicitly check for the expected size and throw an exception giving more details if you get an inappropriate line. Or if it's a blank line, as others have suggested (and which does indeed seem likely) you may want to just skip it.
Alternatively, here's a short but complete console application which should help you find the problem:
using System;
using System.IO;
class Test
{
static void Main()
{
string[] lines = File.ReadAllLines("source\\Staff.txt");
for (int i = 0; i < lines.Length; i++)
{
string line = lines[i];
string[] fields = line.Split(',');
if (fields.Length != 6)
{
Console.WriteLine("Invalid line ({0}): '{1}'",
i + 1, line);
}
}
}
}
That could be because of blank line that appear at the top in the text file.
Have you checked for an empty row at the end of your text file?
After this:
fields = recordIn.Split(DELIM);
you need this:
if (fields.length < 6)
{
// the current recordIn is the problem!
}
else
{
Lname = fields[0];
// etc.
}
recordIn = reader.ReadLine(); // make sure to put this after the else block!
You should do this routinely when reading from files, because there are often leading or trailing blank lines.
You've most likely got an extra blank line at the end of your input file, which therefore only has one (empty) field, giving you index out of range at index 1.

Categories

Resources