问题
Below is a problem that I have been having the past couple of days. This question is very similar to one I asked yesterday, but when I updated the question no one touched it so I am asking it again in a new question.
I am working on a program that takes a large text file, splits it into 2 groups: a and b, and then reads each line of the data. A line of data will look like this:
5/22/2015 12:15:55 AM | Batch 8|429/529|81.10 %|BLV-R|Processed VLZYYL...Checking refundable fares. Traditional Booking. Inside ticketing window. Minimum Savings Required: $100.00. Actual Savings: $1,780.60. Savings found: $1,780.60 (31.11 %). Remark written. UDID written. Queued to 0TA9/208*11. Queued to 0TA9/161*222.
I am not going to explain what everything means. But the key elements that this program is looking at is "Savings found:" and the percent that is next to it. Not every line however has savings, actually most of the lines do not, but some of them do. Below I have a piece of code that will Tell me what the file name is, how many lines the file has, and look at every line in the a group and write out how many PNRS were processed, how many PNRS have savings, what the percent of all the PNRS that had savings(Percent rounded to 3 decimals) and then it is supposed to write out every line that has "Savings found:" if the percent is 30% or greater, it will place an asterisk infront of the line. If it has 30% or greater savings and has $500 or more in savings, then it will place two asterisks in the front of that line. Below I have an example of what the overall output should be and the code that I have thus far:
Console Idea:
FIle Name: PNRS
Total Lines: 123,123
Group: A
Total PNRS: 123
PNRS With Savings: 23
% With Savings: 10%
* 5/21/2015 11:55:56 PM | Batch 6|386/767|50.33 %|CH2M-R|Processed NXRMN5...Checking refundable and non-refundable fares. Traditional Booking. Inside ticketing window. Minimum Savings Required: $131.00. Actual Savings: $257.18. Savings found: $257.18 (11.55 %). Savings were previously found.
2015-234wefsaf LINE GOES HERE** 2015 LINES
Group: B SAME FORMAT AS GROUP A
Code that I have been working on:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Linq;
namespace DanProject
{
class Program_Origional
{
static void Main(string[] args)
{
//the following series of code is phase1
try
{
string path = @"c:\users\povermyer\documents\visual studio 2013\Projects\DanProject\PNRS\PNRS.log";
if (!File.Exists(path))
{
//Console.WriteLine("File Not Found");
throw new FileNotFoundException();
}
else
{
string[] lines = System.IO.File.ReadAllLines(path);
var count = File.ReadLines(path).Count();
List<string> a = lines.Take(7678).ToList();
List<string> s = lines.Skip(7678).Take(5292).ToList();
Console.WriteLine(System.IO.Path.GetFileNameWithoutExtension(path));
Console.WriteLine(lines.Count());
if (a.Any(item => item.Contains("Savings found")))
{
Console.WriteLine("\nGroup a\n");
var aPNRSThatWereProcessed = a.Count(line => line.Contains("Processed"));
Console.WriteLine("There were " + aPNRSThatWereProcessed + " PNRS that were processed in a");
//code to find number of savings
int aPNRSWhereSavingsWereFound = a.Count(line => line.Contains("Savings found:"));
Console.WriteLine("In a, there were " + aPNRSWhereSavingsWereFound + " PNRS that had savings");
//code to find percentage for a
decimal aPercentage = ((decimal)aPNRSWhereSavingsWereFound / aPNRSThatWereProcessed *100);
decimal result1 = Math.Round(aPercentage, 3);
Console.WriteLine("The percentage of PNRS in a that had savings were " + result1 + "%");
string find = "Savings found:";
foreach (var line in a.Where(w => w.Contains(find)))
{
var subStr = line.Substring(0, line.IndexOf(find) + find.Length);
var startIndex = subStr.IndexOf('(');
var endIndex = subStr.IndexOf(')');
var savings = double.Parse(subStr.Substring(2, startIndex - 1).Trim());
var percent = double.Parse(subStr.Substring(startIndex + 1, endIndex - startIndex - 2).Trim());
Console.WriteLine("{0}{1}{2}", (percent >= 30) ? "*" : string.Empty,
(percent >= 30 && savings >= 500) ? "*" : string.Empty,
line);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
finally
{
Console.ReadKey();
}
}
}
}
My problem lies within the the foreach loop. Everything above that foreach loop is working perfect, and then when I compile this, I am getting this exact error message: System.ArgumentOutOfRangeException: Length cannot be less than zero. Parameter name: length at System.String.Substring(Int32, startIndex, Int32, length) at (Really long file name for the text file I am working with): line 66
As I can see, the problem is with the .Length statement, however when I try to fix it with the (), VS yells at me and says that I can't do it. It says "Non-invocable member 'string.Length' cannot be used like a method".
Now that I have been as specific, as detailed as possible, please help me in figuring out how I can get rid of this problem and get this console application rolling!
回答1:
Then @steve16351 told you what the problem was.
You are doing var subStr = line.Substring(0, line.IndexOf(find) + find.Length);
which will return 'Savings found'
you want something like
var subStr = line.Substring(line.IndexOf(find) + find.Length);
Which will give you everything after 'Savings found'
Told you it would be a Doh moment. :)
来源:https://stackoverflow.com/questions/30623600/argumentindexoutofbounds-exception-string-length