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.
Related
I know this has been asked a few times, but I'm need a fast way to do this in files with different size (small and large files).
I need to edit scale factor in sat(txt) file. This is a first number in third line:
700 104 1 0 16 Autodesk AutoCAD 19 ASM 221.0.0.1871 NT 24 Tue
Aug 16 09:02:14 2016
1000 9.9999999999999995e-007 1e-010
I suggest extracting a method and Linq:
private static String MyEditLine(string value) {
var items = value.Split(new char[] { ' ' }, 2);
items[0] = "2000"; // let's change 1000 into 2000
return string.Join(" ", items);
}
...
var target = File
.ReadLines(#"C:\MyFile.txt")
.Select((line, index) => index != 2
? line
: MyEditLine(line))
.ToList();
File.WriteAllLines(#"C:\MyFile.txt", target);
assume you read your file and get a String[] called file and the number, you want to modify, is represented as float.
Than you can use the following code to first extract the line, you want. After this you get the number through float.TryParse(..)
int lineWithParam = 3;
String[] splittedLine = (file[lineWithParam-1]).Split(new char[] { ' ' }, 2);
if(splittedLine.Length == 2)
{
float fact = 0.0f;
String newFact = splittedLine[0];
// or how ever you want to modify your factor
if(float.TryParse(splittedLine[0], out fact))
{
newFact = "" + (fact * 12.3f);
}
file[lineWithParam-1] = newFact + " " + splittedLine[1];
}
Here an executable example: https://dotnetfiddle.net/NVgETo
after this you can write the String[] file back to the real file.
Note: this will not modify the file, if in the given line the first parameter isn't a valid float!
I have a program that reads texts files and I'm wanting it to collect data after a certain title in the text file, in this case [HRData]. Once the streamreader reaches [HRData] I want it to read every line after that and store each line in a list, but allowing me to get access to the seperate numbers.
The text file is like so:
[HRZones]
190
175
162
152
143
133
0
0
0
0
0
[SwapTimes]
[Trip]
250
0
3978
309
313
229
504
651
//n header
[HRData]
91 154 70 309 83 6451
91 154 70 309 83 6451
92 160 75 309 87 5687
94 173 80 309 87 5687
96 187 87 309 95 4662
100 190 93 309 123 4407
101 192 97 309 141 4915
103 191 98 309 145 5429
So referring to the text file, I want it to store the first line after [HRData] and allow me access each variable, for example 91 being [0].
I have code that already stores to a list if the word matches the regex, but I do not know how to code it to read after a specific string like [HRData].
if (squareBrackets.Match(line).Success) {
titles.Add(line);
if (textAfterTitles.Match(line).Success) {
textaftertitles.Add(line);
}
}
This is my attempt so far:
if (line.Contains("[HRData]")) {
inttimes = true;
MessageBox.Show("HRDATA Found");
if (inttimes == true) {
while (null != (line = streamReader.ReadLine())) {
//ADD LINE AND BREAK UP INTO PARTS S
}
}
}
You can call a LINQ-friendly method File.ReadLines , then you can use LINQ to get the part you want:
List<string> numbers = File.ReadLines("data.txt")
.SkipWhile(line => line != "[HRData]")
.Skip(1)
.SelectMany(line => line.Split())
.ToList();
Console.WriteLine(numbers[0]); // 91
Edit - this will give you all the numbers in one List<string>, if you want to keep the line order, use Select instead of SelectMany:
List<List<string>> listsOfNums = File.ReadLines("data.txt")
.SkipWhile(line => line != "[HRData]")
.Skip(1)
.Select(line => line.Split().ToList())
.ToList();
Note that this requires additional index to get a single number:
Console.WriteLine(listsOfNums[0][0]); // 91
You could use a variable to track the current section:
var list = new List<int[]>();
using (StreamReader streamReader = ...)
{
string line;
string sectionName = null;
while (null != (line = streamReader.ReadLine()))
{
var sectionMatch = Regex.Match(line, #"\s*\[\s*(?<NAME>[^\]]+)\s*\]\s*");
if (sectionMatch.Success)
{
sectionName = sectionMatch.Groups["NAME"].Value;
}
else if (sectionName == "HRData")
{
// You can process lines inside the `HRData` section here.
// Getting the numbers in the line, and adding to the list, one array for each line.
var nums = Regex.Matches(line, #"\d+")
.Cast<Match>()
.Select(m => m.Value)
.Select(int.Parse)
.ToArray();
list.Add(nums);
}
}
}
Presuming your current code attempt works, which I have not gone through to verify...
You could simply do the following:
List<int> elements = new List<int>();
while (null != (line = streamReader.ReadLine()))
{
if(line.Contains("["))
{
//Prevent reading in the next section
break;
}
string[] split = line.Split(Convert.ToChar(" "));
//Each element in split will be each number on each line.
for(int i=0;i<split.Length;i++)
{
elements.Add(Convert.ToInt32(split[i]));
}
}
Alternatively, if you want a 2 dimensional list, such that you can reference the numbers by line, you could use a nested list. For each run of the outer loop, create a new list and add it to elements (elements would be List<List<int>>).
Edit
Just a note, be careful with the Convert.ToInt32() function. It should really be in a try catch statement just in case some text is read in that isn't numeric.
Edit
Ok.. to make the routine more robust (per my comment below):
First make sure the routine doesn't go beyond your block of numbers. I'm not sure what is beyond the block you listed, so that will be up to you, but it should take the following form:
If(line.Contains("[") || line.Contains("]") || etc etc etc)
{
break;
}
Next thing is pre-format your split values. Inside the for statement:
for(int i=0;i<split.Length;i++)
{
string val = split[i].Trim(); //Get rid of white space
val = val.Replace("\r\n",""); //Use one of these to trim every character.
val = val.Replace("\n","");
try
{
elements.Add(Convert.ToInt32());
}
catch (Exception ex)
{
string err = ex.Message;
//You might try formatting the split value even more here and retry convert
}
}
To access the individual numbers (presuming you are using a single dimension list) there are a couple ways to do this. If you want to access by index value:
elements.ElementAt(index)
if you want to iterate through the list of values:
foreach(int val in elements)
{
}
If you need to know exactly what line the value came from, I suggest a 2d list. It would be implemented as follows (I'm copying my code from the original code snippet, so assume all of the error checking is added!)
List<List<int>> elements = new List<List<int>>();
while (null != (line = streamReader.ReadLine()))
{
if(line.Contains("["))
{
//Prevent reading in the next section
break;
}
List<int> newLine = new List<int>();
string[] split = line.Split(Convert.ToChar(" "));
//Each element in split will be each number on each line.
for(int i=0;i<split.Length;i++)
{
newLine.Add(Convert.ToInt32(split[i]));
}
elements.Add(newLine);
}
Now to access each element by line:
foreach(var line in elements)
{
//line is a List<int>
int value = line.ElementAt(index); //grab element at index for the given line.
}
Alternatively, if you need to reference directly by line index, and column index
int value = elements.ElementAt(lineIndex).ElementAt(columnIndex);
Be careful with all of these direct index references. You could pretty easily get an index out of bounds issue.
One other thing.. you should probably put a breakpoint on your Convert.ToInt statement and find what string it is breaking on. If you can assume that the data input will be consistent, then finding exactly what string is breaking the conversion will help you create a routine that handles the particular characters that are filtering in. I am going to guess that the method broke when it attempted to Convert the last split value to an integer, and we had not removed line endings.
Here is a big problem for me, because I can't get out of the loop. I got in listDataReport.Count only 1. But in the foreach from beginDate (example: 10/01/2010) to endDate (today), my file writes as times as date are going through from the beginning to the end.
What I want is only one write for the specific date in listDataReport
listDataReport = blReports.GetDataClientes(beginDate, endDate);
string dateSelected = string.Empty;
while (beginDate < endDate)
{
foreach (var item in listDataReport)
{
FileCreated.WriteLog(item.NmbrCliLeg + "|" + item.NmbCliProf + "|" + item.Namsur + "|" + item.Mail, false);
dateSelected= item.DateUp;
}
beginDate = beginDate.AddDays(1);
}
log.WriteLog("Clients up date: " + dateSelected + ":" + listDataReport.Count);
It repeats as many days are between beginDate- endDate. And if i only get one Client on listDataReportthat happens.
As you can see there's FileCreated.WriteLogcreates a .txt which writes the data client here's the problem. In log.WriteLog which creates a .log file there's no problem in that. I'll show what I got from both files.
In log:
---***--- Execution Initiated: 27/03/2015 09:44:40 a.m.
27/03/2015 09:44:50 a.m. - Clients up date 03/19/2015: 1
===***=== Execution Ended: 03/27/2015 09:44:50 a.m.
But now in .txt file (Datefile03272015.txt) :
0123456789|7976967|NAME SURNAME|somemail#mail.com
0123456789|7976967|NAME SURNAME|somemail#mail.com
0123456789|7976967|NAME SURNAME|somemail#mail.com
0123456789|7976967|NAME SURNAME|somemail#mail.com
All the job runs each day and creates a .txt file each day. It doesn't matter the .log file here.
Use the keyword break to break out of a loop:
https://msdn.microsoft.com/en-us/library/ttw7t8t6.aspx
int[] list = [1, 2, 3, 4, 5, 6, 7, 8];
foreach(int item in list)
{
Console.WriteLine(item);
if (item == 5)
break;
}
Output:
1
2
3
4
5
Let's say I have text file like this
<pre>----------------
hPa m C
---------------------
1004.0 28 13.6
1000.0 62 16.2
998.0 79 17.2
992.0 131 18.0
<pre>----------------
Sometext here
1000.0 10 10.6
1000.0 10 11.2
900.0 10 12.2
900.0 100 13.0
<aaa>----------------
How Can I Create Array in C# that reads text file from line number 5 (1004.0) to just before line that starts with string <pre>-
I used string[] lines = System.IO.File.ReadAllLines(Filepath);
To make each line in the array
The problem is I want only numbers of first section in the array in order to separate them later to another 3 arrays (hPa, m, C) .
Here's a possible solution. It's probably way more complicated than it should be, but that should give you an idea of possible mechanisms to further refine your data.
string[] lines = System.IO.File.ReadAllLines("test.txt");
List<double> results = new List<double>();
foreach (var line in lines.Skip(4))
{
if (line.StartsWith("<pre>"))
break;
Regex numberReg = new Regex(#"\d+(\.\d){0,1}"); //will find any number ending in ".X" - it's primitive, and won't work for something like 0.01, but no such data showed up in your example
var result = numberReg.Matches(line).Cast<Match>().FirstOrDefault(); //use only the first number from each line. You could use Cast<Match>().Skip(1).FirstOrDefault to get the second, and so on...
if (result != null)
results.Add(Convert.ToDouble(result.Value, System.Globalization.CultureInfo.InvariantCulture)); //Note the use of InvariantCulture, otherwise you may need to worry about , or . in your numbers
}
Do you mean this?
System.IO.StreamReader file = new System.IO.StreamReader(FILE_PATH);
int skipLines = 5;
for (int i = 0; i < skipLines; i++)
{
file.ReadLine();
}
// Do what you want here.
hi i'm trying to extract values from this tagged file
here is the file
0
LINE
5
1C1CBD
330
1C1ADB
100
AcDbEntity
8
0-FD
62
9
370
-2
100
AcDbLine
10
53740.73468153231
20
-190253.3098529756
30
0.0
11
53690.49919802765
21
-190166.2994431953
31
0.0
0
you can see that there is a hexadecimal number below "LINE", is there anyway i can extract it into some list?
like
VALUE = 1C1CBD
NOTE: the file consist more than one of this kind of pattern
and then how can i get the maximum value?
EDIT 1
i see that "5" can be found by using regex "\s\s5" can i use this?
Thank you for your feedback i have been able to complete what i want
here is the code
string[] handle = originalString.Split(new string[] { "\r\n" }, StringSplitOptions.None);
List<string> hexa = new List<string>();
for (var a = 1; a <= handle.Count() - 1; a++)
{
if (Regex.IsMatch(handle[a], #"^\s\s5"))
{
hexa.Add(handle[a + 1]);
}
}
List<int> HexaToInt = new List<int>();
foreach (string valueHexa in hexa)
{
int intHexaValue = int.Parse(valueHexa, System.Globalization.NumberStyles.HexNumber);
HexaToInt.Add(intHexaValue);
}
int maximumHexa = HexaToInt.Max();
string hexValue = maximumHexa.ToString("X");
it is possible afterall to extract the hexadecimal value from the handle group codes
It is totally impossible.
No way to catch characters and extract what you need.
You have to organize the structure of this file better.