I’d like to create a method to replace delimiters for the intended target use (html email, log, database). The delimiters are constant so I’d like to be able to reference a object that maps recognizable names to string values (semicolon = “;”, htmlLineBreak = “<br/>”, etc.). Is there a better means to do this than this below?
public static class Utilities
{
public string ReplaceDelimiter(string content
, Delimiter currentDelimiter, Delimiter outputDelimiter)
{
return content.Replace(currentDelimiter.ToString()
, outputDelimiter.ToString());
}
}
public class Delimiter
{
public const string comma = ",";
public const string semicolon = ";";
public const string colon = ":";
public const string lineBreak = "\r\n";
public const string htmlLineBreak = "<br/>";
}
Edited following comments:
A use case would be when I want to log an error to different targets and send the same contents (formatted differently) in an email. The log may go to a database column (want key/value with semicolon delimiter) or log file (want delimiter to be line breaks). The email would be HTML so want the delimiter to be replaced with <br/>.
Below would be an excerpt from a logging method that has a few parameters including the actual Exception:
StringBuilder delimitedMessage = new StringBuilder();
delimitedMessage.Append("Date=" + DateTime.Now.ToShortDateString() + ";");
delimitedMessage.Append("Time=" + DateTime.Now.ToLongTimeString() + ";");
delimitedMessage.Append("Source=" + objException.Source.ToString().Trim() + ";");
delimitedMessage.Append("Method=" + objException.TargetSite.Name.ToString() + ";");
delimitedMessage.Append("Erring Method=" + methodName + ";");
delimitedMessage.Append("Computer=" + System.Environment.MachineName.ToString() + ";");
delimitedMessage.Append("Log Message=" + logMessage + ";");
delimitedMessage.Append("Exception Error=" + objException.Message.ToString().Trim() + ";");
delimitedMessage.Append("Severity=" + severity.ToString() + ";");
delimitedMessage.Append("Stack Trace=" + objException.StackTrace.ToString().Trim() + ";");
contentToLog = delimitedMessage.ToString();
WriteToDb(contentToLog);
WriteToLog(Utilities.ReplaceDelimiter(contentToLog, Delimiter.semicolon, Delimiter.lineBreak));
SendEmail(Utilities.ReplaceDelimiter(contentToLog, Delimiter.semicolon, Delimiter.htmlLineBreak));
Code
public class Delimiter {
public static readonly Delimiter
HtmlLineBreak=new Delimiter {
Value="<br/>"
},
LineBreak=new Delimiter {
Value="\r\n"
},
Semicolon=new Delimiter {
Value=";"
},
Colon=new Delimiter {
Value=":"
},
Comma=new Delimiter {
Value=","
};
public override String ToString() {
return Value;
}
public String Value {
get;
set;
}
}
Test
var t=Utilities.ReplaceDelimiter("123\r\n", Delimiter.LineBreak, Delimiter.HtmlLineBreak);
Debug.Print("{0}", t);
Output
123<br/>
Related
the information I enter in my form is not being stored in my CSV file. Just a blank file. the file name updates with todays date.
here is my code.
private void btnSave_Click(object sender, EventArgs e)
{
string date = DateTime.Today.ToString("dd-MM-yyyy"); //get today's date
string filePath = "Policy_" + date + ".csv"; //create a name of the new csv file (including the date)
string delimiter = ","; //comma needed to create new csv file
StringBuilder sb = new StringBuilder();
foreach (DriverDetails driverDetails in driverDet) //go through the List called DriverDetails and examine each object in turn
{
sb.AppendLine(driverDetails.Title + delimiter + driverDetails.FName + delimiter + driverDetails.SName + delimiter + driverDetails.Dob + delimiter + driverDetails.Phone + delimiter + driverDetails.Email + delimiter + driverDetails.Employment + delimiter + driverDetails.Marital + delimiter + driverDetails.HouseNo + delimiter + driverDetails.Street + delimiter + driverDetails.Postcode + delimiter);//uild up a String containing all the data in the List
}
File.WriteAllText(filePath, sb.ToString());
//File.AppendAllText(filePath, sb.ToString()); //add the new string (made up of SEVERAL lines, each representing data from ONE order) to the end of the csv file
MessageBox.Show("Driver details saved to file");
}
I use the following code to fill the driverDet, and then can write the data to the csv file.
class DriverDetails
{
public string Title { get; set; }
public string FName { get; set; }
public string SName { get; set; }
}
List<DriverDetails> driverDet = new List<DriverDetails> {
new DriverDetails { Title = "T1", FName = "F1", SName = "S1"},
new DriverDetails { Title = "T2", FName = "F2", SName = "S2"},
new DriverDetails { Title = "T3", FName = "F3", SName = "S3"}};
You can replace
File.WriteAllText(filePath, csv.ToString());
with
File.AppendAllText(filePath, csv.ToString());
When i program,i want to delete a specify string in a long string.
For example:
The source string is:
abcdffff<fdfs>adbcccc
abcdffff<fdferfefs>adbcccc
abcdffff<fdffefes>adbcccc
abcdffff<fdffefefs>adbcccc
The i want to delete the string like <fdfs>
The result should be:
abcdffffadbcccc
abcdffffadbcccc
abcdffffadbcccc
abcdffffadbcccc
How could i do?
This is my code:
public string formatMailMessageBody(string herf,string notifyinfo)
{
StringBuilder sb = new StringBuilder();
sb.Append(notifyinfo.Replace("〈%〉", "") + "<br><br>");
sb.Append("单击下面的链接查看您当前任务:<br>");
sb.Append("<a href='" + herf + "'><b>" + herf + "</b></a>");
string s = sb.ToString();
return sb.ToString();
}
Is it right?
Note that the following code is applicable only if the string you want to delete has this format <...> (no other pairs of <> inside):
var output = Regex.Replace(input, #"\<[^>]*\>", "");
The Regex class is located in the namespace System.Text.RegularExpressions.
I have a string like this:
“I’m a member of the Imperial Senate on a diplomatic mission to Alderaan.”
I want to insert <strong> around the "a" in "a diplomatic", but nowhere else.
What I have as input is diplomatic from a previous function, and I wan't to add <strong>to the closest instance of "a".
Right now, of course when I use .Replace("a", "<strong>a</strong>"), every single instance of "a" receives the <strong>-treatment, but is there any way to apply this to just to one I want?
Edit
The string and word/char ("a" in the case above) could be anything, as I'm looping through a lot of these, so the solution has to be dynamic.
var stringyourusing = "";
var letter = "";
var regex = new Regex(Regex.Escape(letter));
var newText = regex.Replace(stringyourusing , "<strong>letter</strong>", 1);
Would this suffice?
string MakeStrongBefore(string strong, string before, string s)
{
return s.Replace(strong + " " + subject, "<strong>" + strong + "</strong> " + before);
}
Used like this:
string s = “I’m a member of the Imperial Senate on a diplomatic mission to Alderaan.”;
string bolded = MakeStrongBefore("a", "diplomatic", s);
Try this:
public string BoldBeforeString(string source, string bolded,
int boldBeforePosition)
{
string beforeSelected = source.Substring(0, boldBeforePosition).TrimEnd();
int testedWordStartIndex = beforeSelected.LastIndexOf(' ') + 1;
string boldedString;
if (beforeSelected.Substring(testedWordStartIndex).Equals(bolded))
{
boldedString = source.Substring(0, testedWordStartIndex) +
"<strong>" + bolded + "</strong>" +
source.Substring(testedWordStartIndex + bolded.Length);
}
else
{
boldedString = source;
}
return boldedString;
}
string phrase = "I’m a member of the Imperial Senate on a diplomatic mission to Alderaan.";
string boldedPhrase = BoldBeforeString(phrase, "a", 41);
Hei!
I've tested this and it works:
String replaced = Regex.Replace(
"I’m a member of the Imperial Senate on a diplomatic mission to Alderaan.",
#"(a) diplomatic",
match => "<strong>" + match.Result("$1") + "</strong>");
So to make it a general function:
public static String StrongReplace(String sentence, String toStrong, String wordAfterStrong)
{
return Regex.Replace(
sentence,
#"("+Regex.Escape(toStrong)+") " + Regex.Escape(wordAfterStrong),
match => "<strong>" + match.Result("$1") + "</strong>");
}
Usage:
String sentence = "I’m a member of the Imperial Senate on a diplomatic mission to Alderaan.";
String replaced = StrongReplace(sentence, "a", "diplomatic");
edit:
considering your other comments, this is a function for placing strong tags around each word surrounding the search word:
public static String StrongReplace(String sentence, String word)
{
return Regex.Replace(
sentence,
#"(\w+) " + Regex.Escape(word) + #" (\w+)",
match => "<strong>" + match.Result("$1") + "</strong> " + word + " <strong>" + match.Result("$2") + "</strong>");
}
I have the following code that inputs a CSV file and then converts it and outputs a CSV file. I am using FileHelper for CSV reading. I am having a couple problems with it. First, an extra line with field information is being inserted (see below). The second problem is that I have added double quotes so I can have a string in a cell that contains a comma; I can't find anything wrong with the formatting but it will not import into excel and only shows the double quotes and the first item. I have tried using the double quotation mark for escaping text option when importing into excel. The third problem is that some fields are blank and result in later offset of fields.
Second line of fields:
, base, 0, 0, 0, Product Name, Size, Brand, Gender, Type, SKU, Stock, Sí, "Photo1, Photo2, Photo3", Photo1, Photo1, Photo1
Code:
using System;
using FileHelpers;
using System.IO;
[DelimitedRecord(";")]
public sealed class StoreItems
{
[FieldOptional()]
public String Attribut;
[FieldOptional()]
public String ProductName;
[FieldOptional()]
public String Size;
[FieldOptional()]
public String Brand;
[FieldOptional()]
public String Type;
[FieldOptional()]
public String ParentSKU;
[FieldOptional()]
public String SKU;
[FieldOptional()]
public String Stock;
[FieldOptional()]
public String RetailEURO;
[FieldOptional()]
public String SuggestedsellEURO;
[FieldOptional()]
public String Weight;
[FieldOptional()]
public String Description;
[FieldOptional()]
public String Photo1;
[FieldOptional()]
public String Photo2;
[FieldOptional()]
public String Photo3;
[FieldOptional()]
public String Gender;
[FieldOptional()]
public String EAN13;
}
public class RunProgram
{
public static void Main()
{
FileHelperEngine engine = new FileHelperEngine(typeof(StoreItems));
StoreItems[] res = engine.ReadFile("Presta.csv") as StoreItems[];
Directory.CreateDirectory("Output");
StreamWriter sw = new StreamWriter(#".\Output\" + DateTime.Now.ToString("hhmmss") + ".csv");
sw.AutoFlush = true;
Console.SetOut(sw);
Console.WriteLine("_type, _product_websites, tax_class_id, _visibility, is_in_stock, name, taglia, manufacturer, gender, _attribute_set, sku, qty, use_external_images, external_gallery, " +
"thumbnail_external_url, small_image_external_url, image_external_url");
foreach(StoreItems item in res)
{
string newtype = null;
int visibility = 0;
if (item.Attribut == "Parent")
{
newtype = "Configurable";
visibility = 4;
}
else if (item.Attribut == "Child")
{
newtype = "Simple";
visibility = 1;
}
int isinstock;
int stockint;
try
{
stockint = Convert.ToInt32(item.Stock);
}
catch
{
stockint = 0;
}
if (stockint > 0)
{
isinstock = 1;
}
else
{
isinstock = 0;
}
Console.WriteLine(newtype + ", base, 0, " + visibility + ", " + isinstock + ", " + item.ProductName + ", " + item.Size + ", " +
item.Brand + ", " + item.Gender + ", " + item.Type + ", " + item.SKU + ", " + item.Stock + ", Sí, " + #""""+item.Photo1+ ", "+item.Photo2+", "+item.Photo3+#"""" + ", " + item.Photo1 + ", " + item.Photo1 +
", " + item.Photo1);
}
}
}
Edit: I just realized that the second line is being added in from the reading of the input file. I just need to find a way to ignore the first line. The fields also no longer seem to be offsetting. Now just how to use commas in the csv?
Second problem;
You don't have to use commas as a separator, you can use any character you want. So as a quick fix, why not change the ',' separator in your output to '|'.
If, of course, you also need to output '|' in your text, this is not going to help, but if not - quick fix to get you going.
One problem; you have;
string newtype = null;
int visibility = 0;
if (item.Attribut == "Parent")
{
newtype = "Configurable";
visibility = 4;
}
else if (item.Attribut == "Child")
{
newtype = "Simple";
visibility = 1;
}
If item.Attribut is neither "Parent" or "Child" exactly, then newtype is not set. Hence why the first field in your example output is blank.
I have a method which gets the values of the properties of an object and appends some commas to it. I want to make this generinc so i can use it with other objects.
foreach (var row in rows.ToList())
{
sbResult.Append(
delimiter + row.MediaName + delimiter + separator +
delimiter + row.CountryName + delimiter + separator +
delimiter + row.ItemOverRideDate + delimiter + separator +
delimiter + row.Rating + delimiter + separator +
delimiter + row.BatchNo + delimiter + separator +
delimiter + row.NoInBatch + delimiter + separator +
delimiter + row.BatchDate + delimiter + separator +
delimiter + row.DataType + delimiter + separator +
delimiter + row.ByLine + delimiter + separator +
delimiter + row.IssueNo + delimiter + separator +
delimiter + row.Issue + delimiter + separator +
delimiter + row.MessageNo + delimiter + separator +
delimiter + row.Message + delimiter + separator +
delimiter + row.SourceName + delimiter + separator +
delimiter + row.SourceType + delimiter + separator);
//end of each row
sbResult.AppendLine();
}
I have tried using var rowData = row.GetType().GetProperties(); but it only returns the property itself and I dont know how to get the value of the property.
Since Type.GetProperties returns a collection of PropertyInfo, you follow that up by calling PropertyInfo.GetValue. Here's how you can do that (and all the rest together) with LINQ:
var line = string.Join(
row.GetType().GetProperties()
.Select(pi => pi.GetValue(row))
.Select(v => delimiter + v.ToString() + delimiter),
separator);
However, you might want to reconsider your approach. This code will break if GetProperties fetches static properties or indexers along with "normal" properties; it also requires that the code be run with full trust (otherwise no reflection is possible). And finally, it's going to be slow because a) reflection is inherently slow and b) it will keep reflecting on the same things over and over again without caching any of the information it has already discovered.
In addition to the above potential problems, if there is even a remote chance that you will later want to filter what gets printed out it is probably better to encapsulate this logic inside a (virtual?) method on row and just do something like
sbResult.AppendLine(row.SerializeAsLine());
You can use something like this to iterate over all the properties of a particular type:
public static IEnumerable<KeyValuePair<string, T>> PropertiesOfType<T>(object obj)
{
return from p in obj.GetType().GetProperties()
where p.PropertyType == typeof(T)
select new KeyValuePair<string, T>(p.Name, (T)p.GetValue(obj));
}
Then you could specify the type as string for all your string properties.
Compilable sample:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
private static void Main()
{
var test = new Test
{
Str1 = "S1",
Str2 = "S2",
Str3 = "S3",
Str4 = "S4"
};
foreach (var property in PropertiesOfType<string>(test))
{
Console.WriteLine(property.Key + ": " + property.Value);
}
}
public static IEnumerable<KeyValuePair<string, T>> PropertiesOfType<T>(object obj)
{
return from p in obj.GetType().GetProperties()
where p.PropertyType == typeof(T)
select new KeyValuePair<string, T>(p.Name, (T)p.GetValue(obj));
}
}
public class Test
{
public string Str1 { get; set; }
public string Str2 { get; set; }
public string Str3 { get; set; }
public string Str4 { get; set; }
}
}
Here it is.
List<PropertyInfo> _propInfo = _row.GetType().GetProperties();
foreach (var item in _propInfo)
{
object _value = item.GetValue(_row, null);
if (_value != null)
{
// Save the Value
}
}
GetProperties returns an array of PropertyInfo, so use the GetValue method and use your object as it's input to get the value for each property. Here is the code:
public class MyClass
{
public string MyProperty1 { get; set; }
public string MyProperty2 { get; set; }
public string MyProperty3 { get; set; }
}
Then
MyClass myObj = new MyClass() { MyProperty1 = "first", MyProperty2 = "second", MyProperty3 = "third" };
List<string> array = new List<string>();
foreach (var item in typeof(MyClass).GetProperties())
{
array.Add(item.GetValue(myObj, null).ToString());
}
var result = string.Join(",", array); //use your own delimiter
var values = instance
.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Select(z => string.Format("{0}: {1}\n", z.Name, z.GetValue(instance, null)));
string res = string.Concat(values);
Where instance is the instance of your object. You might want to avoid LINQ and use a loop if StringBuilder is required (depending on the number of properties).