In my database, I store phone numbers like this "7279884545". One solid string with no spaces.
In my class that stores the phone number info, I have a function that will add the correct punctuation.
public static String beautifyPhoneNumber(String number, String extension)
{
String beautifulNumber = "";
if (!String.IsNullOrEmpty(number))
{
beautifulNumber = "(" + number.Substring(0, 3) + ") " +
number.Substring(3, 3) + "-" +
number.Substring(6, 4);
}
if (!String.IsNullOrEmpty(extension))
{
beautifulNumber += " x" + extension;
}
return beautifulNumber;
}
And here is how I have the variable in the class itself.
private string _PhonePrimary;
[DisplayName("Phone Primary")]
public string PhonePrimary
{
get
{
if(this._PhonePrimary != null)
{
this._PhonePrimary = beautifyPhoneNumber(this._PhonePrimary, this.Extension);
}
return this._PhonePrimary;
}
set
{
this._PhonePrimary = value;
}
}
This works fine most of the time. The numbers are outputted to the screen in a "(727) 988-4545" or "(727) 988-4545 x12" if there is an extension for that record in the database.
The problem comes when I do a HttpPost request. The model information that is inside of the post request looks like this.
_PhonePrimary = "(727) 988-4545"
PhonePrimary = "(((7) 2) -7) -"
As noted, it looks like you're calling beautifyPhoneNumber on a number you've already beautified.
Here's an implementation using regular expressions that should get you started:
public static String BeautifyPhoneNumber(string numberToBeautify)
{
//The below gives us capture groups for each
//individual piece of the number.
var regularExpression = new Regex(#"(\d{3})(\d{3})(\d{4})(x\d*)?");
//This matches a number that's already been beautified,
//so we can guard against beautifying twice.
var alreadyBeautifulExpression = new Regex(#"(\(\d{3}\)) (\d{3})-(\d{4}) ?(x\d*)?");
var beautifulNumber = string.Empty;
var separator = "-";
var space = " ";
//This prevents us from accidentally beautifying
//something more than once
//You could also guard against this in your getter using a
//IsBeautified extension, using the alreadyBeautifulExpression above
if (alreadyBeautifulExpression.IsMatch(numberToBeautify))
{
return numberToBeautify;
}
//Trying to protect against invalid input... May be insufficient,
//Or unnecessary
if (string.IsNullOrEmpty(numberToBeautify)
|| regularExpression.Matches(numberToBeautify).Count <= 0)
{
return beautifulNumber;
}
GroupCollection groups = regularExpression.Matches(
numberToBeautify)[0].Groups;
//More protection against invalid input
if (groups.Count < 3)
{
return beautifulNumber;
}
//Given "7689131234",
beautifulNumber += "(" + groups[1] + ")" + space; //gives us "(768) "
beautifulNumber += groups[2] + separator; //gives us "(768) 913-"
beautifulNumber += groups[3]; //gives us "(768) 913-1234"
//If we have an extension, we add it.
if (groups[4] != null)
{
beautifulNumber += space + groups[4];
}
return beautifulNumber;
}
Given inputs of:
7279884545
7279884545x12
(727) 988-4545
This returns:
(727) 988-4545
(727) 988-4545 x12
(727) 988-4545
Related
I'm writing a project, and the part I'm doing now is getting arrow shaped real fast. How can I remove the nested if statements, but still have the same behaviour?
The code below might not look so bad now, but I'm planning on refactoring to include more methods.
public async Task FirstDiffTestAsync()
{
string folderDir = "../../../";
string correctReportDir = folderDir + "Reports To Compare/Testing - Copy.pdf";
string OptyNumber = "122906";
//Making a POST call to generate report
string result = ReportGeneration(OptyNumber).Result;
Response reportResponse = JsonConvert.DeserializeObject<Response>(result);
string newURL = reportResponse.documentUrl;
//Logging the Response to a text file for tracking purposes
await File.WriteAllTextAsync(Context.TestRunDirectory + "/REST_Response.txt", result);
using (StreamWriter w = File.AppendText(Context.TestDir + "/../log.txt"))
{
//Checking if the Integration failed
if (reportResponse.Error == null)
{
//now we have the url, reading in the pdf reports
List<string> Files = new List<string> { correctReportDir, newURL };
List<string> parsedText = PdfToParsedText(Files);
DiffPaneModel diff = InlineDiffBuilder.Diff(parsedText[0], parsedText[1]);
// DiffReport is a customised object
DiffReport diffReport = new DiffReport(correctReportDir, newURL);
diffReport.RunDiffReport(diff);
//In-test Logging
string indent = "\n - ";
string logMsg = $"{indent}Opty Number: {OptyNumber}{indent}Activity Number: {reportResponse.ActivityNumber}{indent}File Name: {reportResponse.FileName}";
if (diffReport.totalDiff != 0)
{
await File.WriteAllTextAsync(Context.TestRunDirectory + "/DiffReport.html", diffReport.htmlDiffHeader + diffReport.htmlDiffBody);
logMsg += $"{indent}Different lines: {diffReport.insertCounter} Inserted, {diffReport.deleteCounter} Deleted";
}
LogTesting(logMsg, w);
//Writing HTML report conditionally
if (diffReport.totalDiff != 0)
{
await File.WriteAllTextAsync(Context.TestRunDirectory + "/DiffReport.html", diffReport.htmlDiffHeader + diffReport.htmlDiffBody);
}
Assert.IsTrue(diffReport.insertCounter + diffReport.deleteCounter == 0);
}
else
{
LogTesting($" Integration Failed: {reportResponse.Error}", w);
Assert.IsNull(reportResponse.Error);
}
}
}
As mentioned in the comment, the indentation level is fine for now, but its always better to minimize when possible, especially when you are repeating same blocks of code.
The best way to do this is to write a separate function that contains that block of code and then call that function instead of the nested if statements.
In your case it would be something like this:
private async void checkTotalDiff(diffReport) {
...
}
You could pass anything you might need in the parameters. This way in your main code, you could replace the if statements with checkTotalDiff(diffReport) and save the return (if any) to a variable.
Also note I used void for return but you could change the type depending on what the function returns.
I wouldn't consider this as having an excessive amount of nested if-statements. It is fine as is. Otherwise you could do the following (also suggested by #Caius Jard):
public async Task FirstDiffTestAsync()
{
string folderDir = "../../../";
string correctReportDir = folderDir + "Reports To Compare/Testing - Copy.pdf";
string OptyNumber = "122906";
//Making a POST call to generate report
string result = ReportGeneration(OptyNumber).Result;
Response reportResponse = JsonConvert.DeserializeObject<Response>(result);
//Checking if the Integration failed
if (reportResponse.Error != null)
{
LogTesting($" Integration Failed: {reportResponse.Error}", w);
Assert.IsNull(reportResponse.Error);
return;
}
string newURL = reportResponse.documentUrl;
//Logging the Response to a text file for tracking purposes
await File.WriteAllTextAsync(Context.TestRunDirectory + "/REST_Response.txt", result);
using (StreamWriter w = File.AppendText(Context.TestDir + "/../log.txt"))
{
//now we have the url, reading in the pdf reports
List<string> Files = new List<string> { correctReportDir, newURL };
List<string> parsedText = PdfToParsedText(Files);
DiffPaneModel diff = InlineDiffBuilder.Diff(parsedText[0], parsedText[1]);
// DiffReport is a customised object
DiffReport diffReport = new DiffReport(correctReportDir, newURL);
diffReport.RunDiffReport(diff);
//In-test Logging
string indent = "\n - ";
string logMsg = $"{indent}Opty Number: {OptyNumber}{indent}Activity Number: {reportResponse.ActivityNumber}{indent}File Name: {reportResponse.FileName}";
if (diffReport.totalDiff != 0)
{
await File.WriteAllTextAsync(Context.TestRunDirectory + "/DiffReport.html", diffReport.htmlDiffHeader + diffReport.htmlDiffBody);
logMsg += $"{indent}Different lines: {diffReport.insertCounter} Inserted, {diffReport.deleteCounter} Deleted";
}
LogTesting(logMsg, w);
//Writing HTML report conditionally
if (diffReport.totalDiff != 0)
{
await File.WriteAllTextAsync(Context.TestRunDirectory + "/DiffReport.html", diffReport.htmlDiffHeader + diffReport.htmlDiffBody);
}
Assert.IsTrue(diffReport.insertCounter + diffReport.deleteCounter == 0);
}
}
I need to copy multiple lines from text file(cisco config file): based on the below condition
if the line starts with interface copy from interface until '! '
my file is like :
!
access-list 1>
!
interface 1
ip address xx.xx.xx.xx
!
interface 2
ip address xx.xx.xx.xx
!
route 1
!
I try the below code :
var lines = File.ReadAllLines("C:\\My File2.txt");
foreach (var line1 in lines){
string firstWord = line1.Split(' ').First();
if ((firstWord == "access-list") && (!line1.Contains("remark ")))
{
TextBox1.Text = TextBox1.Text + "\r\n" + line1;
}
else if (firstWord == "nat")
{
TextBox2.Text = TextBox2.Text + "\r\n" + line1;
}
else if (firstWord == "interface")
{
var result = lines.Substring(line1.LastIndexOf('!') + 1);
TextBox3.Text = TextBox3.Text + "\r\n" + result;
}
but I get only one line as output
In case you want to keep your algorithm, this will work for you.
var lines = File.ReadAllLines("C:\\My File2.txt");
int i;
for (i = 0; i<lines.Length;i++)
{
var line1 = lines[i];
if (line1 == "!" || line1 == " ") continue;
if (line1.StartsWith("access-list")) && (!line1.Contains("remark ")))
{
TextBox1.Text = TextBox1.Text + "\r\n" + line1;
}
else if (line1.StartsWith("nat"))
{
TextBox2.Text = TextBox2.Text + "\r\n" + line1;
}
if (line1.StartsWith("interface"))
{
var str = line1;
while (!Equals(lines[i + 1], "!"))
{
str += lines[i + 1];
i++;
}
TextBox3.Text = TextBox3.Text + "\r\n" + str;
}
}
As per the file structure shown by you interface and ip address are on different lines. So you won't get it in same iteration of for loop. When you find that firstWord == "interface" you will need to set a flag that will tell you that next line is ip address and in next iteration check if that flag is true parse the current line as ip address and process it the way you want.
You should use "File.ReadAllText" instead of "File.ReadAllLines". "File.ReadAllText" returns a string with the complete text file text. After that, you can use the "String.Split" method to generate a string array.
var lines = File.ReadAllText("C:\\My File2.txt");
var seperatedStrings = lines.Split('!');
Each index of "seperatedStrings" contains what you want.
UPDATE: Here is a code snippet, that can help:
var lines = File.ReadAllText("C:\\My File2.txt");
var seperatedStrings = lines.Split('!');
foreach (var oneString in seperatedStrings)
{
if (oneString.Contains("access-list"))
{
Console.WriteLine("Access-List: " + oneString);
}else if (oneString.Contains("nat"))
{
Console.WriteLine("Nat: " + oneString);
}else if (oneString.Contains("interface"))
{
Console.WriteLine("Interface: " + oneString);
}
}
This is the output of my code snippet:
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Here is what I am actually trying to do, I am trying to use lists and classes instead of the way it is now to do the same thing:
public ActionResult Testcsvbp()
{
string Workingfolder = System.Web.HttpContext.Current.Server.MapPath(#"~/Files");
string FileNamer = DateTime.Now.Hour.ToString() + DateTime.Now.Millisecond.ToString() + DateTime.Now.Day.ToString();
ViewBag.Output = "No Test Data Available...........";
ViewBag.Details = "No Details Avalable...........";
// Output the start time.
DateTime startTime = DateTime.Now;
ViewBag.Output = "Program Start Time: " + startTime.ToString("T");
// Read all log file lines into an array.
string[] lines = System.IO.File.ReadAllLines(Workingfolder + #"/access.log");
// Build a data table for all the lines we decide to keep.
DataTable dt = new DataTable();
dt.Columns.Add("Count", typeof(long));
dt.Columns.Add("IP_Address", typeof(string));
dt.Columns.Add("IP_Address_Integer", typeof(long));
// Make the IP_Address Column a primary key to speed up the process of searching the data table over and over.
// Note: the DataTable type does not have the capability to be indexed.
dt.PrimaryKey = new DataColumn[] { dt.Columns["IP_Address"] };
// Iterate over the lines array. Since this iteration will be expensive, we want to hunt out bad lines and append the good lines into a dataTable.
for (int i = 0; i < lines.Length; i++)
{
// Create array for that line, splitting fields by sspaces. From this point, much of our conditional logic will be specific array indexes.
// This assumes that this program is only for schema used in the logs/access.log file.
string[] lineArray = lines[i].Split(' ');
// We don't want to use comment lines or data within the comment lines. To avoid this, we'll assume a length of 21 items for lines[i].
if (lines[i].Substring(0, 1) != "#" && lineArray.Length == 21)
{
// Isolate lines where the request was a GET protocol on port 80. Also eliminate IPs starting with 207.114 .
if (lineArray[7] == "80" && lineArray[8] == "GET" && lineArray[2].Substring(0, 7) != "207.114")
{
// Create datarow to add to data table container.
DataRow dr = dt.NewRow();
dr["Count"] = 1;
dr["IP_Address"] = lineArray[2];
dr["IP_Address_Integer"] = IPtoInt(lineArray[2]);
// Create duplicate search expression and check for duplicates.
string searchExpression = "IP_Address = '" + lineArray[2].ToString() + "'";
DataRow[] duplicateRow = dt.Select(searchExpression);
// Prevent duplicate rows for an IP address. If a duplicate is fount, add 1 to the "Count" row. Else, add the row.
if (duplicateRow.Length > 0)
{
int duplicateIndex = dt.Rows.IndexOf(duplicateRow[0]);
dt.Rows[duplicateIndex]["Count"] = int.Parse(dt.Rows[duplicateIndex]["Count"].ToString()) + 1;
}
else
{
dt.Rows.Add(dr);
}
// Have the data table accept all changes.
dt.AcceptChanges();
}
}
}
// Now sort the datatable by the IP Address integer representation.
DataView dv = dt.DefaultView;
dv.Sort = "Count desc, IP_Address_Integer desc";
dt = dv.ToTable();
// Create a string builder to contain the CSV file contents.
StringBuilder sb = new StringBuilder();
// Add column names as the first line.
sb.Append("Count,IP_Address");
// Add the data to subsequent lines
ViewBag.Output = ""; //
foreach (DataRow row in dt.Rows)
{
var fields = row["Count"] + ",\"" + row["IP_Address"] + "\"\n";
var columns = row["Count"] + ",\"" + row["IP_Address"] + "<br>";//mbelcher
sb.AppendLine(fields);
ViewBag.Output += columns; //
}
// Write the CSV file to the file system.
string SaveFilePath = Workingfolder + #"\IPaddressComplete" + FileNamer + ".csv";
using (StreamWriter sw = new StreamWriter(SaveFilePath))
{
sw.Write(sb.ToString());
ViewBag.Details = sb.ToString();//
ViewBag.FileNamer = SaveFilePath;
}
ViewBag.LinkToFile = "<a target='_blank' href='http://logparser.lol.com/files/" + #"IPaddressComplete" + FileNamer + ".csv'>Download File</a>";
// Output the start time.
TimeSpan duration = endTime - startTime;
Console.WriteLine("Program Duration: " + duration.Seconds.ToString() + " seconds");
return View("Testcsvbp");
}
IIS LOG FILE line sample:
#Software: Microsoft Internet Information Services 5.0
#Version: 1.0
#Date: 2010-08-12 00:00:01
#Fields: date time c-ip cs-username s-sitename s-computername s-ip s-port cs-method cs-uri-stem cs-uri-query sc-status sc-win32-status sc-bytes cs-bytes time-taken cs-version cs-host cs(User-Agent) cs(Cookie) cs(Referer)
2010-08-12 00:00:01 69.143.116.98 - W3SVC106 STREAM 207.22.66.152 80 GET /includes/scripts.js - 200 0 2258 381 94 HTTP/1.1 www.lol.com Mozilla/4.0+(compatible;+MSIE+7.0;+Windows+NT+6.0;+WOW64;+GoogleT5;+SLCC1;+.NET+CLR+2.0.50727;+Media+Center+PC+5.0;+.NET+CLR+3.5.30729;+.NET+CLR+3.0.30618;+.NET4.0C) - http://www.lol.com/
I started with writing the below code, all I am getting in the view is this:
System.String[]
System.String[]
I am probably missing something but now really sure how to accomplish what I want with lists and classes.
// List to contain rows we are going to use.
List<LogParserModel> LogListParsed = new List<LogParserModel>();
var logFile = System.IO.File.ReadAllLines(Workingfolder + #"/accessShort.log");
List<string> LogList = new List<string>();
foreach (var s in logFile) LogList.Add(s);
var LogListCount = LogList.Count();
ViewBag.LogListCount = LogListCount;
// This will go through each line of the log file that was loaded into list LogList
// 1. We split this by spaces to delemite values.
string LineItemCheck = "";
int LineItemCount = 0;
//for (var m = 0; m < LogList.Count; m++)
foreach (string line in LogList)
{
LineItemCount++;
//Split on space - need to do this then turn back into alist?
LineItemCheck = line;// LogList.ToString();
LineItemCheck = LineItemCheck.Split(' ').ToString();
if (LineItemCheck.Substring(0, 1) == "#")
{
// we remove this line from the collection.
ViewBag.RemovedLines += "(" + LineItemCount + ")" + LineItemCheck + "<br>";
}
else
{
//process it and add to the final "List<LogParser> LogListParsed"
ViewBag.AddedLines += "(" + LineItemCount + ")" + LineItemCheck.ToString() + "<br>";
}
}
ViewBag.LASTLineItemChecked = LineItemCheck;
ViewBag.TotalLinesProcessed = LineItemCount.ToString();
return View("Testcsv");
}
Here are the classes I made; nothing in them at all yet:
public class LogParserModel
{
public long HostCount { get; set; }
[Key]
public string IPAddress { get; set; }
public long IPfilter { get; set; }
}
Below was to do the parsing with methods.
public class LogParser
{
//Method to return something here
//Method to return something here
public string[] GetParsedList(string[] SomeArray)
{
return SomeArray.ToArray();
}
}
In LineItemCheck = LineItemCheck.Split(' ').ToString(); part you've splitting string, and it returns an array. So if you ToString() it, it will return the type of your array/list.
Try below code
foreach (string line in LogList)
{
LineItemCount++;
//Split on space - need to do this then turn back into alist?
string LineItem = LineItemCheck = line;
if (LineItem.Substring(0, 1) == "#")
{
// we remove this line from the collection.
ViewBag.RemovedLines += "(" + LineItemCount + ")" + LineItemCheck + "<br>";
}
else
{
//process it and add to the final "List<LogParser> LogListParsed"
ViewBag.AddedLines += "(" + LineItemCount + ")" + LineItemCheck.ToString() + "<br>";
}
}
I have a file with some rows and I can read everything, but I will get an error if one column has a empty cell.
What should I do?
while ((line = reader.ReadLine()) != null) {
FundPriceModel model = new FundPriceModel();
if (isColumn) {
model.Columns = line.Split(spliter[0]);
isColumn = false;
} else {
string[] row = line.Split(spliter);
model.LipperID = Int32.Parse(row[0]);
model.PriceDate = DateTime.Parse(row[1]);
model.PriceCode = row[2][0];
model.PriceType = row[3][0];
model.PriceCurrency = row[4];
model.PriceValueLC = float.Parse(row[5]);
model.Estimate = row[6][0];
Console.WriteLine(model.LipperID + "\t" + model.PriceDate + "\t" + model.PriceCode + "\t" + model.PriceType + "\t" + model.PriceCurrency + "\t" + model.PriceValueLC + "\t" + model.Estimate);
}
}
Table:
The error is probably when you try to parse something. This leads me to believe that you need to use TryParse instead or Parse :)
Something like this: int x; int? val=int.TryParse(row[0],out x)?x:(int?)null;
Also, row[3][0] gets the first letter in an existing string and returning an error when the string is empty. You could encapsulate it somewhat like this:
private T safeValue<T>(string text, Func<string,T> func) {
if (string.IsNullOrEmpty(text)) return default(T);
return func(text)
}
and you would use it like this:
model.LipperID = safeValue(row[0],v=>Int32.Parse(v));
model.PriceCode = safeValue(row[2], v=>v[0]);
I want to use textbox and checkboxlist to search data in gridview using asp.net c#. Using textbox can search the data. But for checkboxlist only can search the data when check only one checkbox. If check more than one checkbox, can't search the data. thanks a lot for helping.
the code:
c# code
protected void btnSearch_Click(object sender, EventArgs e)
{
if (cblDay.SelectedIndex != -1)
{
foreach (ListItem val in cblDay.Items)
{
if (val.Selected == true)
{
RptRateData.Day += val.Value + "";
}
}
}
RptRateData.RateAmount = txtRate.Text.Trim();
BindGrid();
}
code for class:
public string RateAmount { get; set; }
public string Day { get; set; }
internal DataSet GetRptRateSet()
{
DataSet tmpDS = new DataSet();
try
{
string strSQL = #"SELECT ComplexRateInfo.ComplexRateId,
ComplexRateDetailInfo.Day,
ComplexRateInfo.RateAmount
FROM ComplexRateInfo
LEFT JOIN ComplexRateDetailInfo ON ComplexRateInfo.ComplexRateId = ComplexRateDetailInfo.ComplexRateId ";
string whereSQL = " WHERE";
string orderBySQL = " order by Day ;";
int filterCount = 0; //to keep track of needed filter that are going to be used by the sql string
string[] sIndex = new string[2]; //to keep track of scalar variable needed by the sql, four string of sIndex because maximum filter available is 4
int indexCount = 0; //count to access sIndex members
//filter with or without day
if (_ds.Day != null && _ds.Day != "")
{
if (filterCount > 0) //query need additional filter
whereSQL = whereSQL + " AND ComplexRateDetailInfo.Day LIKE '{" + filterCount + "}'";
else //if this is the first filter
whereSQL = whereSQL + " ComplexRateDetailInfo.Day LIKE '{" + filterCount + "}'";
filterCount++;
sIndex[indexCount] = _ds.Day;
indexCount++;
}
//filter with or without rate amount
if (_ds.RateAmount != null && _ds.RateAmount != "")
{
if (filterCount > 0) //query need additional filter
whereSQL = whereSQL + " AND ComplexRateInfo.RateAmount LIKE '{" + filterCount + "}'";
else //if this is the first filter
whereSQL = whereSQL + " ComplexRateInfo.RateAmount LIKE '{" + filterCount + "}'";
filterCount++;
sIndex[indexCount] = _ds.RateAmount;
indexCount++;
}
//build complete query with no filter at all
if (filterCount == 0)
{
strSQL = strSQL + orderBySQL;
tmpDS = Db.GetDataSet(string.Format(strSQL));
}
//build complete query with 1 or more filter
else
{
strSQL = strSQL + whereSQL + orderBySQL;
tmpDS = Db.GetDataSet(string.Format(strSQL, sIndex));
}
}
catch (Exception ex)
{
throw ex;
}
return tmpDS;
}
There are two mistakes in your code.
Assigning values to RptRateData.Day from CheckBoxList.
Description: You assign selected values to object without using any separator. So For example if you have selected 1, 2, 4 days then as per your code, value of RptRateData.Day will be 124. Instead of that, it should be separated with comma as shown below:
var selectedDays = string.Empty;
foreach (ListItem val in cblDay.Items)
{
if (val.Selected == true)
{
selectedDays += "'" + val.Value + "',";
}
}
RptRateData.Day = selectedDays.TrimEnd(new char[] { ',' });
Now come to the second point which is in your SQL query which you make dynamically.
Description: In this query in WHERE clause you use Like operator for ComplexRateDetailInfo.Day. This will not work anymore. Instead of that you should use IN operator.
Note: Are you sure that your Like operator is working with curly braces ('{' and '}') and without '%' symbol ?