This is a similar question I asked earlier, except different in the fact that I am taking multiple files and calculating the total sums off of those files. I have it to the point where I am reading all the files from a specific directory, but for some reason its not grouping correctly.
Here is the code that I have:
public void CalculateMonthlyStatistics(string monthlyFiles)
{
string monthlyFileName = monthlyFiles + ".log";
var statistics = File.ReadLines(monthlyFileName)
.GroupBy(items => items[0])
.Select(g =>
new
{
Division = g.Key,
ZipFiles = g.Sum(i => Convert.ToInt32(i[1])),
Conversions = g.Sum(i => Convert.ToInt32(i[2])),
ReturnedFiles = g.Sum(i => Convert.ToInt32(i[3])),
TotalEmails = g.Sum(i => Convert.ToInt32(i[4]))
});
statistics
.ToList()
.ForEach(d => Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}",
d.Division,
d.ZipFiles,
d.Conversions,
d.ReturnedFiles,
d.TotalEmails));
Console.Read();
//.ForEach(d => Log.Open(tempFileName.TrimEnd(charsToTrim), d.Division, d.ZipFiles, d.Conversions, d.ReturnedFiles, d.TotalEmails));
}
}
}
The log files that I am putting into it look like the following:
Division Zip Files Conversions Returned Files Total E-Mails
Corporate 0 5 0 5
Energy 0 1 0 5
Global Operations 0 3 0 3
Oil & Gas 1 5 0 5
Capital 5 18 0 12
So what I am trying to do, is group by "Corporate", "Energy", etc. Then calculate the totals for ALL of the files being read, to create a Monthly Statistics file. I am getting totals currently, however I think its got something to do with the header that I am passing in, and I am not sure how to tell it to skip that line.
Thanks in advance
EDIT
Here is my processor, which originally reads the directory, etc.
public void ProcessMonthlyLogFiles()
{
DateTime currentTime = DateTime.Now;
int month = currentTime.Month - 1;
int year = currentTime.Year;
string path = Path.GetDirectoryName(Settings.DailyPath + year + #"\" + month + #"\");
foreach (string monthlyFileNames in Directory.GetFiles(path))
{
string monthlyFiles = path + #"\" + Path.GetFileNameWithoutExtension(monthlyFileNames);
new MonthlyReader().CalculateMonthlyStatistics(monthlyFiles);
}
}
The processor finds the proper directory to search through in order to get the files from. It uses the current date, and finds last month.
Skipping the header is straightforward:
File.ReadLines(monthlyFileName).Skip(1).<rest of your chain>
However, it seems as though you're reading one file at a time, when you want to be reading all files then calculating the statistics?
How about first:
public IEnumerable<String> ReadLinesInDirectory(string path)
{
return Directory.EnumerateFiles(path)
.SelectMany(f =>
File.ReadLines(f)
.AsEnumerable()
.Skip(1));
}
And replace ReadLines with that (ensuring you're pointing to the right path etc).
OK here's the full explanation, but I think you may need to study C# some more. First, define the ReadLinesInDirectory function I wrote above.
Then replace ProcessMonthlyLogFiles with this instead:
public void ProcessMonthlyLogFiles()
{
DateTime currentTime = DateTime.Now;
int month = currentTime.Month - 1;
int year = currentTime.Year;
string path = Path.GetDirectoryName(Settings.DailyPath + year + #"\" + month + #"\");
CalculateMonthlyStatistics(path);
}
And in CalculateMonthlyStatistics have the first three lines (before the GroupBy) as follows:
public void CalculateMonthlyStatistics(string path)
{
var statistics = ReadLinesInDirectory(path)
// .GroupBy etc...
Related
There are about 15 particular public folders out of several public folders from which I am deleting mailitems which are greater than 15 days old. Each public folder has around 1000+ mailitems. Every week it's the same quantity of items. Currently I am getting the default public folder and looping each of the sub-folders and deleting the mails.
Microsoft.Office.Interop.Outlook.Folder tempInbox = tempApp.Session.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olPublicFoldersAllPublicFolders) as Microsoft.Office.Interop.Outlook.Folder;
**SOME Code***
foreach (Microsoft.Office.Interop.Outlook.Folder subfolder1 in subfolder.Folders)
{
if ((check those 14 subfolder names )& (subfolder1.Folders.Count > 0))
{
CheckCountries(subfolder1, sw);
}
}
CheckCountries(subfolder1, sw) -> Here I am comparing and deleting the mail items.
//Deletion part of code below
foreach (object todel in delItem)
{
DateTime d1 = DateTime.Now;
Microsoft.Office.Interop.Outlook.MailItem mailitmType = todel as Microsoft.Office.Interop.Outlook.MailItem;
if (mailitmType is Microsoft.Office.Interop.Outlook.MailItem)
{
if ((mailitmType.IsConflict != true) & (mailitmType.MessageClass.Contains("IPM.Note.SMIME") == false))
{
DateTime d2 = mailitmType.ReceivedTime;
if ((d1 - d2).TotalDays > iDays)
{
sw.WriteLine("Deleting Mail with Subject line as = \"" + mailitmType.Subject + "\" and Received time = " + mailitmType.ReceivedTime);
mailitmType.Delete();
iCnt = iCnt + 1;
} //mailitmType.Save();
}
}
}
I want to improve on the following areas -
It takes almost 5-7 hours to execute this as it reads through all the
mailitems (if there are 2000 of which only 1000 are > 15 days) in each
of the 15 folders and compares the age of the mail and then deletes.
Some of the folders fails due to access issue. So I need to add an id at the start of the code which has access to all of these public folders and can be used to delete. Currently it takes the default id that is running the executable.
Never loop through all item in a folder - use Items.Find/FindNext of Items.Restrict with a query on ReceivedTime property being less than some value.
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!
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
What is the correct way to concatenate these elements?
Environment: C#-WinForm-Desktop.
In my app, I have a text file called config.ini. This file has values with this nomenclature:
csv_month_hour=value
The data are thus:
[csv]
csv_01_01=value // 24 hours a day in January
csv_01_02=value
csv_01_03=value
.
csv_02_01=value // 24 hours a day in February
csv_02_02=value
csv_02_03=value
.
// and so on
My app has this method called:
private void getMonthHour()
{
DateTime Xdt = DateTime.Now;
int Xmonth = Xdt.Month;
int Xhour = Xdt.Hour;
if (File.Exists("config.ini"))
{
IniFile ini = new IniFile("config.ini");
m3h = Convert.ToDouble(confg.csv["csv_" + Xmonth.ToString + "_" + Xhour.ToString]);
}
}
This method is called every seconds in timer_tick to check the month and time to use the corresponding value.
I need to know how to concatenate this:
m3h = Convert.ToDouble(confg.csv["csv_"+Xmonth.ToString+"_"+Xhour.ToString]);
An example of the code would be:
if (Xmonth==1&&Xhour==1){m3h = Convert.ToDouble(confg.csv.csv_01_01);}
else if (Xmonth==1&&Xhour==2){m3h = Convert.ToDouble(confg.csv.csv_01_02);}
else if (Xmonth==1&&Xhour==3){m3h = Convert.ToDouble(confg.csv.csv_01_03);}
// csv_month_hour in this case 01 is January.
else if (Xmonth==2&&Xhour==1){m3h = Convert.ToDouble(confg.csv.csv_02_01);}
// And so on, until December (12).
Putting aside the invalid syntax/compiler error from your method calls in your code, I suspect you're building the string but can't get the leading 0 in front of digits 0-9. So when Xmonth and Xhour are less than 10, your string is being built as "csv_1_1" instead of your intended "csv_01_01".
To instruct the ToString method to include a leading zero when needed, you can supply a custom numeric format string "00" (see the first entry in the link for "Zero placeholder").
Try using Xmonth.ToString("00") and Xhour.ToString("00"):
Monitor.malyt.m3h = Convert.ToDouble(confg.csv["csv_" +
Xmonth.ToString("00") + "_" +
Xhour.ToString("00")]);
This will output the values of Xmonth and Xhour with a single leading zero where needed.
This question already has answers here:
2d Array from text file c# [closed]
(3 answers)
Closed 9 years ago.
How can I loop through a text file to create six arrays from the content of the text file.
For example, the text file will look like this but with more lines(without title) maybe 200 of them
top_speed average_speed cadence altitude heart_rate power
84 73 0 -124 0 50
86 179 84 -125 121 3893
It would be nice to have an array for each. So, for example
top_speed = 84 + 86 : average_speed = 73 + 179 ... (and so on)
What's the best way to do this?
Anyway, if that is homework, following code will not help you :) But if it is not homework, you will understand how to parse such files with LINQ
var items =
File.ReadAllLines(filename) // read lines from file
.Select(line => line.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries)
.Select(Int32.Parse)
.ToArray()) // convert each line to array of integers
.Select(values => new {
TopSpeed = values[0],
AverageSpeed = values[1],
Cadence = values[2],
Altitude = values[3],
HeartRate = values[4],
Power = values[5]
}); // create anonymous object with nice strongly-typed properties
int[] topSpeeds = items.Select(i => i.TopSpeed).ToArray();
You could create a Record class and then use a simple LINQ query:
var records = File.ReadLines("file.txt")
.Select(line =>
{
string[] parts = line.Split('\t');
return new Record
{
TopSpeed = int.Parse(parts[0]),
AverageSpeed = int.Parse(parts[1]),
Cadence = int.Parse(parts[2]),
Altitude = int.Parse(parts[3]),
HeartRate = int.Parse(parts[4]),
Power = int.Parse(parts[5])
};
}).ToArray();
This will give you a bunch of Records, one per line in the original file. If you wanted to then check all of HeartRates for building a histogram or graphing or whatever, you could grab them like this:
var allHeartRates = records.Select(rec => rec.HeartRate);