My message box displays hi and his, whenever, my file has the word hello.
My project is supposed to display the messagebox hi only,
and for my code (rtbDisplay.Text = "\n"+"hey";) it override the hello word that
I type.
My project is to create a chatbox. Whenever i type in certain word, it will reply me back with the words that i choose.
File.AppendAllLines(#"C:\\Users\\L31011\\Desktop\\version17\\version17\\FinalProject\\WinRecognize\\bin\\Debug\\Chat\\messages.txt", new[] { rtbType.Text });
StreamReader sr = new StreamReader("C:\\Users\\L31011\\Desktop\\version17\\version17\\FinalProject\\WinRecognize\\bin\\Debug\\Chat\\messages.txt");
rtbDisplay.Text = sr.ReadLine();
//here
string record;
string input = "hello";
string input1 = "goodbye";
try
{
record = sr.ReadToEnd();
while (record != null)
{
if (record.Contains(input))
{
MessageBox.Show("hi");
//rtbDisplay.Text = "\n"+"hey";
}
if (record.Contains(input1))
{
MessageBox.Show("byebye");
}
else
{
MessageBox.Show("his");
}
break;
}
}
finally
{
sr.Close();
}
There are a whole bunch of things that you can do to this. First, the #"string goes here" construct (i.e., with an "at" sign as a preface to the string) means that there is no escaping needed. So you don't need to double up your backslashes (I've been writing in C# since the alpha at the end of 2000, and I didn't realize that #"c:\\some\\file.ext" would work). You can say either "c:\\some\\file.ext" or #"c:\some\file.ext" -- but #"c:\\some\\file.ext" is just weird (and too much typing).
You should read up on using using. It's simpler and clearer than try { } finally { CloseOrDispose() }.
Then there is what #ChetanRanpariya is talking about. Put a breakpoint on the first if statement, when there is "hello" somewhere in the second line to the end. Start single-stepping. Notice that you step into the first message box because of the "hello". Then continue stepping. You don't step into the second message box, because there's no "goodbye". But, there is an else. See what happens next.
By the way, is this really what you want to do? You read the first line, stick it in a text box. Then you read lines 2 through N (all in one go, and into one string) and check to see if "hello" or "goodbye" is on any of them - all in a while loop that will only ever be executed once.
Related
I'm using the TextFieldParser class to read CSV files. It has two methods for ingesting lines of data: ReadFields() and ReadLine(). As you might imagine the former treats the data as columnar, separated by pre-set delimiters and the latter reads the raw data. I'm using the former, in code like this:
using (TextFieldParser parser = new TextFieldParser(newestFile.FullName))
{
parser.Delimiters = ","
parser.HasFieldsEnclosedInQuotes = true;
while (!parser.EndOfData)
{
try
{
List<string> result = parser.ReadFields().ToList();
// do something
}
catch(MalformedLineException ex)
{
// log error to record line where it happened
}
}
}
The catch for MalformedLineException is there to ensure the thing doesn't fall over if it meets a line that doesn't meet the parsing criteria - it might have additional quotes within a field, for example - it registers this and then moves on to the next line without bringing the whole thing to a halt.
What I'd really like to do in the catch block, though, is log the actual text of the line along with the line number to make it a bit easier to find out what the problem was. But I have no idea how I can get it: ReadFields appears to move on to the next line even when it errors, and if I call ReadLine in the catch block it also moves on to the next line, meaning lines get skipped. It does not appear to be part of the exception thrown, or available via the object when ReadFields fails.
Is there a way to use the TextFieldParser to capture this data?
I didn't actually intend to answer my own question, but this turned out to be very easy: there are other methods on the object to do just this: ErrorLine and ErrorLineNumber.
using (TextFieldParser parser = new TextFieldParser(newestFile.FullName))
{
parser.Delimiters = ","
parser.HasFieldsEnclosedInQuotes = true;
while (!parser.EndOfData)
{
try
{
List<string> result = parser.ReadFields().ToList();
// do something
}
catch(MalformedLineException ex)
{
int errorLine = parser.ErrorLineNumber;
string originalData = parser.ErrorLine;
// log them
}
}
}
I've created *.txt file with data like this:
deviceid,model,availability,renterID,renterName,reneterSurname,OS
0001,iPhone_5S,false,002,John,Dowland,iOS-7.1.2
0002,GalaxyS3,false,002,Amadeus,Mozart,Android-4.3.2
In my C# app (WPF application) got this function to operate on the file:
private void rentSaveButton_Click(object sender, RoutedEventArgs e)
{
StreamWriter sw = new StreamWriter(#"D:\deviceLib.txt", true);
var currentUser = _list.Where(u => u.Id == int.Parse(userIDTextBox.Text)).FirstOrDefault();
var currentDevice = _list2.Where(i => i.deviceId == int.Parse(deviceIDTextBox.Text)).FirstOrDefault();
if (currentDevice != null && currentUser != null)
{
currentDevice.Availability = false;
currentDevice.rentId = currentUser.Id;
currentDevice.rentName = currentUser.Name;
currentDevice.rentSurname = currentUser.Surname;
dataGridDeviceList.Items.Refresh();
sw.WriteLine();
sw.Close();
MessageBox.Show("Rent done. Thanks!");
tabControl.SelectedItem = mainTab;
}
else
{
MessageBox.Show("We don't have such device. Sorry :( ");
userIDTextBox.Clear();
deviceIDTextBox.Clear();
}
}
Now, the problem is that I can normally work on this file during program work, it changes values, can read it etc but when I turn off app (by X button) nothing happen. TXT file is untouched nor any changes are saved.
You aren't writing anything to the file.
sw.WriteLine(); // you need to pass a string in to this function
It seems to me that you must have invented a theory that any changes you make to currentDevice should, somehow, affect what's written to sw. What you're seeing here is what Karl Popper used to call "disconfirmation": Your theory predicts behavior that can be observed; you observe; the behavior is not happening. The first explanation for that is that your theory is wrong.
And that is in fact the correct explanation for what you're (not) seeing. There is absolutely no connection whatsoever between currentDevice and sw. None. It's like you're pressing buttons on the microwave in an effort to start your car. You'll be walking to work if you don't switch to another approach.
currentDevice.Availability = false;
currentDevice.rentId = currentUser.Id;
currentDevice.rentName = currentUser.Name;
currentDevice.rentSurname = currentUser.Surname;
dataGridDeviceList.Items.Refresh();
sw.WriteLine();
sw.Close();
All you do there is change a bunch of properties on a random object, refresh your data grid, and then write a newline, a newline and nothing else, to the output stream. Why does sw.WriteLine();, with no arguments do that? Well, it does that because that's what the designers decided it would do. There's nothing else it sanely can do, because you're not giving it anything to write. And that behavior is documented, which you would know if you had spent ten seconds reading the documentation.
If you want to write a non-empty line to a file, use one of the many, many overloads of WriteLine which are documented in the documentation. If you want to write just part of a line, use one of the many overloads of Write, which are also documented.
Something like this would be fine (I'm guessing at your field names; if you don't know what they are, maybe somebody else on StackOverflow knows what that part of your code looks like and can help you):
currentDevice.Availability = false;
currentDevice.rentId = currentUser.Id;
currentDevice.rentName = currentUser.Name;
currentDevice.rentSurname = currentUser.Surname;
// Write fields in desired order of appearance in the file.
sw.Write(currentDevice.deviceID);
// There are many far superior ways to write a comma to the file,
// and I'll hear about all of them in comments, but we're keeping
// it as simple as possible for the moment.
sw.Write(",");
sw.Write(currentDevice.model);
sw.Write(",");
// Properties you just set
sw.Write(currentDevice.Availability);
sw.Write(",");
sw.Write(currentDevice.rentID);
sw.Write(",");
sw.Write(currentDevice.rentName);
sw.Write(",");
sw.Write(currentDevice.rentSurname);
sw.Write(",");
sw.Write(currentDevice.OS);
// NOW write a newline.
sw.WriteLine();
But that's ugly. So we'll roll it into a method to hide it. This is called "refactoring".
public void WriteDeviceStateToStream(StreamWriter stream, WhateverTheDeviceClassIs device)
{
// Write fields in desired order of appearance in the file.
stream.Write(device.deviceID);
// There are many far superior ways to write a comma to the file,
// and I'll hear about all of them in comments, but we're keeping
// it as simple as possible for the moment.
stream.Write(",");
stream.Write(device.model);
stream.Write(",");
// Properties you just set
stream.Write(device.Availability);
stream.Write(",");
stream.Write(device.rentID);
stream.Write(",");
stream.Write(device.rentName);
stream.Write(",");
stream.Write(device.rentSurname);
stream.Write(",");
stream.Write(device.OS);
// NOW write a newline.
stream.WriteLine();
// DO NOT close the stream here. The stream belongs to the caller; make no
// assumptions about what he plans to do with it next.
}
...and in your event handler, call that method. Also note using statement for the StreamWriter. That disposes of it properly, which closes the file and so on. That's important.
private void rentSaveButton_Click(object sender, RoutedEventArgs e)
{
using (StreamWriter sw = new StreamWriter(#"D:\deviceLib.txt", true))
{
var currentUser = _list.Where(u => u.Id == int.Parse(userIDTextBox.Text)).FirstOrDefault();
var currentDevice = _list2.Where(i => i.deviceId == int.Parse(deviceIDTextBox.Text)).FirstOrDefault();
if (currentDevice != null && currentUser != null)
{
currentDevice.Availability = false;
currentDevice.rentId = currentUser.Id;
currentDevice.rentName = currentUser.Name;
currentDevice.rentSurname = currentUser.Surname;
dataGridDeviceList.Items.Refresh();
// Call write method
WriteDeviceStateToStream(sw, currentDevice);
// The user's going to get real tired of this messagebox real fast.
MessageBox.Show("Rent done. Thanks!");
tabControl.SelectedItem = mainTab;
}
else
{
MessageBox.Show("We don't have such device. Sorry :( ");
userIDTextBox.Clear();
deviceIDTextBox.Clear();
}
}
}
I have sample data
string test = #"allprojects {
repositories {
test()
}
}"
When I read the test, I should get the exact string with spaces/tabs/new lines instead of me writing Environment.NewLine etc wherever it requires new line. When I print, it should print the same format [WYSIWYG] type.
Presently it gives something like this in debugger allprojects {\r\n\t\t repositories { \r\n\t\t test() \r\n\t\t } \r\n\t\t }
There are several ways to determine a new line, and it is dependant on the OS you are using:
Windows: \r\n
Unix: \n
Mac: \r
As for a tab, all you need is \t.
Therefore, in your string all you need is:
string test = #"allprojects {\r\n\trepositories {\r\n\t\ttest()\r\n\t}\r\n}"
Which will output:
allprojects {
repositories {
test()
}
}
What I do in string literals that need this is just not indent the content at all:
namespace Foo {
class Bar {
const string test = #"
allprojects {
repositories {
test()
}
}";
}
}
And strip away the initial newline. Looks a bit ugly, but it does get the point across that the leading whitespace matters.
You can also place the #" on the second chance, but automatic code formatting could move that and it doesn't look as close to the actual text. (Code formatting should not touch the contents of a string, but I can't guarantee that.)
This should round-trip correctly if processing the string line-by-line, as would seem appropriate anyway:
var reader = new StringReader(test);
reader.ReadLine();
string line;
while ((line = reader.ReadLine()) != null)
{
Console.WriteLine(line);
}
Console.ReadLine();
Or just read them from a file / resource.
I'm trying to send/receive a string through C#, in C# i just do:
SerialPort.WriteLine("A6");
but in CCS, if i try sending a string char after char it does not work at all, neither with ReadLine nor with ReadExisting! This is what i have tried creating an array, so that everytime we enter the RXBUFF pragma, we add the received char to the array, until the array is full (i randomly defined the array size to be 2, which means we deal with 2-char-length strings), and eventually send the string by sending char after char:
#pragma vector = USCI_A1_VECTOR
__interrupt void USCI_A1_ISR(void)
if(__even_in_range(UCA1IV,18) == 0x02){ // Vector 2 - RXIFG
if(counter==0)
{
Data[0]=UCA1RXBUF;
counter++;
}
else
{
Data[1]=UCA1RXBUF;
counter=0;
UCA1TXBUF=Data[0];
while(!(UCA1IFG & UCTXIFG)); // until UCTXBUF1 is empty
UCA1TXBUF=Data[1];
}
}
in C#:
listBox2.Items.Add(SerialPort.ReadExisting());
i get non-sense text, like : ??A??? sometimes : ????A? etc.., but with:
listBox2.Items.Add(SerialPort.ReadLine());
in the first time i press the Send button which sends the "A6", i get nothing, the second time i get non-sense aswell , just like the ReadExisting behavior.
by the way, even if i try to send the string in the easiest way (without array and conditions), i mean like this:
#pragma vector = USCI_A1_VECTOR
__interrupt void USCI_A1_ISR(void)
UCA1TXBUF='A';
while(!(UCA1IFG & UCTXIFG)); // until UCTXBUF1 is empty
UCA1TXBUF='6';
i also get inconsistent items in the listbox.
However, if i do this:
#pragma vector = USCI_A1_VECTOR
__interrupt void USCI_A1_ISR(void)
UCA1TXBUF=UCA1RXBUF;
i do get "A6" in the listbox and everything just work fine (with ReadLine and ReadExisting)!
could anyone just tell me why this is happening?
I'v just neutralized the Parity bit, everything works now, Thank you all!
This indicates that you shouldn't be waiting for the TX flag inside the RX ISR. The RX interrupt routine should simply fill a FIFO buffer (a byte queue), so that you can parse its contents somewhere else (main routine?), and then create a response when needed.
Pseudo code for the RX ISR should be something like:
#pragma vector = USCI_A1_VECTOR
__interrupt void USCI_A1_ISR(void)
FIFO_Enqueue(&RxBuffer, UCA1RXBUF);
And somewhere inside the main() loop you can parse its contents:
while (1)
{
// find the first occurrence of "A6" and dequeue it
if (FIFO_StartsWith(&RxBuffer, "A6")
SendResponse();
}
Solved - Accidentally wiped the actual file of data but the ide doesn't update that file unless you reopen it so I thought the data was still in there.
I'm working on a project in C# that reads in a fake inventory and then transactions to go with that inventory in another class. I know the code is quite messy at the moment, i'm just trying to figure out one thing specifically.
this code here will read in my file "Inventory.in", check if the file exists(which it does) and then start my streamreader and readline into a string.
private void btnFill_Click(object sender, EventArgs e)
{
string strInputLine;
string inFile = "Inventory.in";
StreamReader iSR;
InvRec currInvent;
if (File.Exists(inFile))
{
iSR = new StreamReader(inFile);
strInputLine = iSR.ReadLine();
while (strInputLine != null)
{
all of it isn't there but the point of emphasis is that the
"strInputLine = iSR.ReadLine();"
does indeed give me the correct value from that file.
now moving on to my question, the second block of code from another button is below:
private void btnProcess_Click(object sender, EventArgs e)
{
string strInputVal;
string inFileName = "Transactions.in";
TransRec currTrans;
StreamReader iSR2;
transListClass transactionList = new transListClass();
InvRec inventItem = inventoryList.Retrieve();
if (File.Exists(inFileName))
{
iSR2 = new StreamReader(inFileName);
strInputVal = iSR2.ReadLine();
while (strInputVal != null)
{
my problem lies when I try and do my ReadLine() into iSR2. it gives me null instead of the value from the file I'm supposed to get. Everything is the same otherwise, it just refuses to give me the correct value. I'm following the debugger in Visual Studio 2010, so I know the file is found and exists, I see it being opened, just a null value instead of my string I need.
Thank you to anybody in advance, I appreciate it.
-Anthony
edit:
the second block of code is supposed to read from "Transactions.in" instead of the first one that reads from "Inventory.in"
Important edit:
I have noticed when i changed "Transactions.in" to "Inventory.in" in the second block of code for the process button, it reads the values from Inventory.in and gives me a proper string unlike null from Transactions.in. The file is found and is just a text file named Transactions.in that was provided by my teacher, nobody else had a problem with it.