How to read the null string with Streamreader c# - c#

I am reading the file which has data as below
123456788|TUUKKA|RASK|01/01/85|HOCKEY|123
123456786|TOM|BRADY|01/01/75|FOOTBALL|123
123456787|RAJON|RONDO|01/01/80|BASKETBALL|ABC
123456785|DUSTIN|PEDROIA|01/01/83|BASEBALL|
123456789|DAVID|ORTIZ|01/01/77|BASEBALL|123
and splitting it with the delimiter '|', but I am the stream reader is not reading the line 4 which contains a null at the end.How do I handle this?
This is my code for reading and splitting the text file line
string s = string.Empty;
using (System.IO.StreamReader File = new System.IO.StreamReader(Path))
{
File.ReadLine();//Removing the first line
while ((s = File.ReadLine()) != null)
{
string[] str = s.Split('|');
UpdateRecords.Athelete(str);
}
}
this is my UpdateRecords.Athelete(str) code:
public static void Athelete(string[] Records) {
tblAthlete athlete = new tblAthlete();
using (SportEntities sportEntities = new SportEntities()) {
var temp = Convert.ToInt32(Records[0]);
if (sportEntities.tblAthletes.FirstOrDefault(x => x.SSN == temp) == null) {
athlete.SSN = Convert.ToInt32(Records[0]);
athlete.First_Name = Records[1];
athlete.Last_Name=Records[2];
athlete.DOB = Convert.ToDateTime(Records[3]);
athlete.SportsCode = Records[4];
athlete.Agency_Code = Records[5];
sportEntities.tblAthletes.Add(athlete);
sportEntities.SaveChanges();
}
}
}

If we put:
athlete.Agency_Code = Records[5];
together with (from comments):
The column is an FK referenced to another table PK and it can accept null values.
the problem becomes clear. An empty string ("") is not a null; it is an empty string! It sounds like you simply want something like:
var agencyCode = Records[5];
athlete.Agency_Code = string.IsNullOrEmpty(agencyCode) ? null : agencyCode;

Related

String or binary data would be truncated.\r\nThe statement has been terminated. c#

I am trying to add email to table but it is throwing error the value in email is "prashhanth#oberonit.com". I don't see any anything wrong in the email.I added other emails added fine not this one.
Column RemovedEmail is varchar(50), null
"String or binary data would be truncated.The statement has been terminated."
var constultantUser = intensifyDb.ConsultantUsers.FirstOrDefault(x => x.Email == email);
// Delete the item
if (constultantUser != null)
{
intensifyDb.DeleteObject(constultantUser);// Save changes
intensifyDb.SaveChanges();
}
if (!intensifyDb.RemovedEmails.Any(x => x.RemovedEmails == email))
{
RemovedEmail consultant = new RemovedEmail
{
RemovedEmails = email
};
intensifyDb.AddToRemovedEmails(consultant);
intensifyDb.SaveChanges(); // Exception throwing here.
}
update
As #Bradley request
Full Code
protected void btnAdd_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(txtEmails.Text))
{
string txt = txtEmails.Text;
string[] lst = txt.Split(new Char[] { '\n', '\r' },
StringSplitOptions.RemoveEmptyEntries);
string email = string.Empty;
var removedEmail = string.Empty;
using (SqlConnection connection = new SqlConnection(connectionString))
{
var foundEmail = string.Empty;
foreach (string emailStr in lst)
{
email = LastCharFromEmailAddress(emailStr).Replace("\r\n", string.Empty);
var intensifyDb = new IntensifyEntities();
var constultantUser = intensifyDb.ConsultantUsers.FirstOrDefault(x => x.Email == email);
// Delete the item
if (constultantUser != null)
{
intensifyDb.DeleteObject(constultantUser);// Save changes
intensifyDb.SaveChanges();
}
if (!intensifyDb.RemovedEmails.Any(x => x.RemovedEmails == email))
{
RemovedEmail consultant = new RemovedEmail
{
RemovedEmails = email
};
intensifyDb.AddToRemovedEmails(consultant);
intensifyDb.SaveChanges();
}
}
connection.Close();
}
}
}
This exception is usually means that your db field doesn't have enough length
I recommend to go over this code in debugger and check what is the length of the string actually is.
EDIT:
I think its extra spaces copy sting to the editor and check and try to use .Trim()
email = email.Trim();
If trim doesn't work it could be some Unicode chars that invisible
Try to add this in code:
var debugCheck = string.Join("",
email.Select(c=> String.Format("{0:X2}", Convert.ToInt32(c))))
and send value of debugCheck back to me so I can check it.
(this convert email value to the hex string it will help to identify extra chars that could look like spaces but they not)
UPDATE:
So you have this string actually (in hex) 707261736868616E7468406F6265726F6E69742E636F6D200B200B200B200B200B200B200B200B2‌​00B200B200B200B200B200B200B200B200B200B200B200B200B200B200B200B200B200B200B200B20‌​0B200B200B200B200B200B200B200B200B200B200B200B200B200B200B200B
200B means Unicode Character 'ZERO WIDTH SPACE' (U+200B) you can remove it by using
.Replace("\u200B", "");
more generic code to remove all unicode whitespace chars:
Regex.Replace(email, #"^[\s,]+|[\s,]+$", "")

Read text file from specific position and store in two arrays

I have text file which contains line like this:
#relation SMILEfeatures
#attribute pcm_LOGenergy_sma_range numeric
#attribute pcm_LOGenergy_sma_maxPos numeric
#attribute pcm_LOGenergy_sma_minPos numeric...
Where are about 6000 lines of these attributes, after attributes where are lines like this:
#data
1.283827e+01,3.800000e+01,2.000000e+00,5.331364e+00
1.850000e+02,4.054457e+01,4.500000e+01,3.200000e+01...
I need to seperate these strings in two different arrays. So far I only managed to store everything in one array.
Here is my code for storing in array:
using (var stream = new FileStream(filePath, FileMode.OpenOrCreate))
{
using (var sr = new StreamReader(stream))
{
String line;
while ((line = sr.ReadLine()) != null)
{
sb.AppendLine(line);
}
}
string allines = sb.ToString();
Console.WriteLine(sb);
}
All strings after #relation SMILEfeatures and contains #attribute are stored in first array. All the strings after #data should are stored in the second array. Hope this is what you wanted.
var relationLineNumbers = new List<int>();
var dataLineNumbers = new List<int>();
var relation = new StringBuilder();
var data = new List<string>();
using (var stream = new FileStream(filepath, FileMode.OpenOrCreate))
{
using (var sr = new StreamReader(stream))
{
string line;
bool isRelation = false;
bool isData = false;
int lineNumber = 0;
while ((line = sr.ReadLine()) != null)
{
lineNumber++;
if (line.StartsWith("#relation SMILEfeatures"))
{
isRelation = true;
isData = false;
continue;
}
if (line.StartsWith("#data"))
{
isData = true;
isRelation = false;
continue;
}
if (isRelation)
{
if (line.StartsWith("#attribute"))
{
relation.Append(line);
relationLineNumbers.Add(lineNumber);
}
}
if (isData)
{
data.AddRange(line.Split(','));
dataLineNumbers.Add(lineNumber);
}
}
}
Console.WriteLine("Relation");
Console.WriteLine(relation.ToString());
Console.WriteLine("Data");
data.ForEach(Console.WriteLine);
All strings which starts with #relation SMILEfeatures and contains #attribute should be stored in first array. Numbers which starts with #data should be stored in second array.
Use string.Contains() and string.StatsWith() for checking.
Read every line and decide in wich array / list you want to put this line
void ReadAndSortInArrays(string fileLocation)
{
List<string> noData = new List<string>();
List<string> Data = new List<string>();
using(StreamReader sr = new StreamReader(fileLocation))
{
string line;
while(!sr.EndOfStream)
{
line = sr.ReadLine();
if(line.StartsWith("#relation") && line.Contains("#attribute"))
{
noData.Add(line);
}
else if(line.StartsWith("#data")
{
Data.Add(line);
}
else
{
// This is stange
}
}
}
var noDataArray = noData.ToArray();
var DataArray = Data.ToArray();
}
But i think that not every line is beginning with "#data"
So you may want to Read all lines and do somethink like this:
string allLines;
using(StreamReader sr = new StreamReader(yourfile))
{
allLines = = sr.ReadToEnd();
}
var arrays = allLines.Split("#data");
// arrays[0] is the part before #data
// arrays[1] is the part after #data (the numbers)
// But array[1] does not contain #data
The question is not really very clear. But my take is, collect all lines that start with #relation or #attribute in one bucket, then collect all number lines in another bucket. I have chosen to ignore the #data lines, as they do not seem to contain any extra information.
Error checking may be performed by making sure that the data lines (i.e. number lines) contain comma separated lists of parsable numerical values.
var dataLines = new List<string>();
var relAttLines = new List<string>();
foreach (var line in File.ReadAllLines())
{
if (line.StartsWith("#relation") || line.StartsWith("#attribute"))
relAttLines.Add(line);
else if (line.StartsWith("#data"))
//ignore these
continue;
else
dataLines.Add(line);
}

How do I refactor a ReadLine loop to Linq

I'd like to make below code cleaner (in the eye of the beholder).
var lines = new StringReader(lotsOfIncomingLinesWithNewLineCharacters);
var resultingLines = new List<string>();
string line;
while( (line = lines.ReadLine() ) != null )
{
if( line.Substring(0,5) == "value" )
{
resultingLines.Add(line);
}
}
to something like
var resultingLinesQuery =
lotsOfIncomingLinesWithNewLineCharacters
.Where(s=>s.Substring(0,5) == "value );
Hopefully I have illustrated that I'd prefer to not have the result as a list (to not fill up memory) and that StringReader is not mandatory.
There is the naïve solution to create an extension and move the ReadLine there but I have a feeling there might be a better way.
Basically you need a way of extracting lines from a TextReader. Here's a simple solution which will only iterate once:
public static IEnumerable<string> ReadLines(this TextReader reader)
{
string line;
while ((line = reader.ReadLine()) != null)
{
yield return line;
}
}
You could use that with:
var resultingLinesQuery =
new StringReader(lotsOfIncomingLinesWithNewLineCharacters)
.ReadLines()
.Where(s => s.Substring(0,5) == "value");
But ideally, you should be able to iterate over an IEnumerable<T> more than once. If you only need this for strings, you could use:
public static IEnumerable<string> SplitIntoLines(this string text)
{
using (var reader = new StringReader(text))
{
string line;
while ((line = reader.ReadLine()) != null)
{
yield return line;
}
}
}
Then:
var resultingLinesQuery =
lotsOfIncomingLinesWithNewLineCharacters
.SplitIntoLines()
.Where(s => s.Substring(0,5) == "value");

How to combine two function's for file deletion

I have two different function to handle two different types of my input text file. One text file with double quotes and one without double quotes.
I wanted to know how can i combine these two functions to a common single function where i can handle in a more efficient way
Code:
//this the function to handle text file without double quotes
public void stack1()
{
string old;
string iniPath = Application.StartupPath + "\\list.ini";
bool isDeleteSectionFound = false;
List<string> deleteCodeList = new List<string>();
using (StreamReader sr = File.OpenText(iniPath))
{
while ((old = sr.ReadLine()) != null)
{
if (old.Trim().Equals("[DELETE]"))
{
isDeleteSectionFound = true;
}
if (isDeleteSectionFound && !old.Trim().Equals("[DELETE]"))
{
deleteCodeList.Add(old.Trim());
}
}
}
StringBuilder sb = new StringBuilder();
using (StreamReader reader = File.OpenText(textBox1.Text))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var value = line.Split('\t');
bool deleteLine = value.Any(v => deleteCodeList.Any(w => v.Equals(w)));
if (!deleteLine)
{
sb.Append(line + Environment.NewLine);
}
}
}
File.WriteAllText(textBox1.Text, sb.ToString());
//return;
}
//this the function to handle text file with double quotes
public void stack()
{
string old;
string iniPath = Application.StartupPath + "\\list.ini";
bool isDeleteSectionFound = false;
List<string> deleteCodeList = new List<string>();
using (StreamReader sr = File.OpenText(iniPath))
{
while ((old = sr.ReadLine()) != null)
{
if (old.Trim().Equals("[DELETE]"))
{
isDeleteSectionFound = true;
}
if (isDeleteSectionFound && !old.Trim().Equals("[DELETE]"))
{
deleteCodeList.Add(old.Trim());
}
}
}
StringBuilder sb = new StringBuilder();
using (StreamReader reader = File.OpenText(textBox1.Text))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split('\t').Select(v => v.Trim(' ', '"'));
bool deleteLines = values.Any(v => deleteCodeList.Any(w => v.Equals(w)));
if (!deleteLines)
{
sb.Append(line + Environment.NewLine);
}
}
}
File.WriteAllText(textBox1.Text, sb.ToString());
MessageBox.Show("finish");
}
The only difference between these two functions is this line:
// stack1 function
var value = line.Split('\t');
// stack2 function
var values = line.Split('\t').Select(v => v.Trim(' ', '"'));
The simplest way would probably be to add a parameter to your method, and then add the check after the split:
public void Split(bool shouldTrimQuotes)
{
...
IEnumerable<string> value = line.Split('\t');
if (shouldTrimQuotes)
{
value = value.Select(v => v.Trim(' ', '"'));
}
...
}
In one case, you would pass true as the parameter (which will cause quotes to be trimmed), while in the second one you would pass false to indicate you don't want to trim them:
// split, but don't trim quotes before comparison
Split(shouldTrimQuotes: false);
// split, trim quotes before comparison
Split(shouldTrimQuotes: true);
You might also play a bit and try to refactor the whole thing, trying to extract smaller general pieces of code into separate methods which might make it clearer what they are doing. This is one approach, for example:
// rewrites the specified file, removing all lines matched by the predicate
public static void RemoveLinesFromFile(string filename, Func<string, bool> match)
{
var linesToKeep = File.ReadAllLines(filename)
.Where(line => match(line))
.ToList();
File.WriteAllLines(filename, linesToKeep);
}
// gets the list of "delete codes" from the specified ini file
public IList<string> GetDeleteCodeList(string iniPath)
{
return File.ReadLines(iniPath)
.SkipWhile(l => l.Trim() != "[DELETE]")
.Skip(1).ToList();
}
// removes lines from a tab-delimited file, where the specified listOfCodes contains
// at least one of the tokens inside that line
public static void RemoveLinesUsingCodeList(
string filename,
IList<string> listOfCodes,
bool shouldTrimQuotes)
{
RemoveLinesFromFile(filename, line =>
{
IEnumerable<string> tokens = line.Split('\t');
if (shouldTrimQuotes)
{
tokens = tokens.Select(v => v.Trim(' ', '"'));
}
return (tokens.Any(t => listOfCodes.Any(t.Equals)));
});
}

Reading specific lines in a .Log file

I have a log file that I am reading into different objects. One object starts at a Line that contains the words "Announce message" and the following lines contain the data that belongs to that message. This entry stops at a line that contains the word "Disposed".
I want to read all the data from between these 2 lines that, contains certain words.
Im currently using a Dictionary because the line with "Announce message" also contains a UID but the following lines contain the data for that UID.
How would you do that?
This is what i have come up with so far.
public static void P2PLogParser(List<FileInfo> fileList)
{
foreach (FileInfo fi in fileList)
{
//Læser alle linier i csv fil
foreach (var line in File.ReadAllLines(fi.FullName))
{
string MeterUID = GetMeterUID(line);
string MimHashcode = GetMimHashcode(line);
string FirmwareUploadStatus = GetFirmwareUploadStatus(line);
string IsKnown = GetIsKnown(line);
DateTime P2PTimeStamp = GetTimestamp(line);
if (IsMeterEntry(line) && !meters.ContainsKey(MeterUID))
{
string MeterNr = GetMeterUID(line).Replace("4B414D", "");
int meternr = int.Parse(MeterNr, System.Globalization.NumberStyles.HexNumber);
meters.Add(MeterUID, new Meter()
{
MeterUID = MeterUID,
MeterNR = meternr,
P2Pmeterentry = new List<P2PMeterEntry>()
});
}
if (IsMeterEntry(line))
{
P2PMeterEntry p2pmeter = new P2PMeterEntry
{
P2PTimeStamp = P2PTimeStamp,
MimHashcode = MimHashcode,
FirmwareUploadStatus = FirmwareUploadStatus,
IsKnown = IsKnown,
P2PMetersession = new List<P2PMeterSession>()
};
if (IsNoLongerMeterEntry(line))
{
string SessionLevel = GetLevel(line);
string SessionMessage = GetSessionMessage(line);
string Context = GetSessionContext(line);
P2PMeterSession MeterSession = new P2PMeterSession
{
SessionTimeStamp = P2PTimeStamp,
SessionLevel = SessionLevel,
SessionMessage = SessionMessage,
Context = Context
};
meterSession.Add(MeterSession);
}
meters[MeterUID].P2Pmeterentry.Add(p2pmeter);
}
}
}
}
and the IsMeterEntry and IsNoLongerMeterEntry
//IsMeterSession
public static bool IsMeterEntry(string text)
{
return text.ToLower().Contains("announce message received:");
}
public static bool IsNoLongerMeterEntry(string text)
{
return text.ToLower().Contains("context - disposed");
}
Implement a simple state machine with two states: IgnoreLine (initial state) and Announce.
for each line in log
if line contains "Announce message"
read UID
create a StringBuilder
set state=Announce
else if line contains "Disposed"
store the StringBuilder's content in the dictionary[uid]
set state=IgnoreLine
else if state==Announce and line contains "certain words"
append line to StringBuilder

Categories