The end of stream is not being detected by reader.EndOfStream - c#

I am reading strings from command line. But end of stream can not be detected by my program. How do I reconstruct this or is there a way to explicitly set EndOfStream to true?
List<String> str = new List<String>();
using (StreamReader reader = new StreamReader(Console.OpenStandardInput()))
while (!reader.EndOfStream)
{
string line = reader.ReadLine();
if (line != string.Empty)
{
str.Add(line);
}
}

That cannot work out by design. The stdin/stdout console streams are opened as long as the program is active. The EndOfStream is executed just before you close the application in this case.
A good solution for your issue is.
using System;
public class Example
{
public static void Main()
{
string line;
do {
line = Console.ReadLine();
if (line != null)
Console.WriteLine("Now I have detected the end of stream.... " + line);
} while (line != null);
}
}

Your code is fine.
When reading from the console, EOF is indicated by entering:
^z then ENTER.
This is a standard as old as DOS. Unix has a similar standard, but it is ^d.
Bill Gates either didn't know Unix or chose to be different but not better. This is why it is ^z not ^d
Likewise, DOS and Windows treat "/" as a command line option delimiter, even though "/" and "" are handled by windows internals as path delimiters.

Related

"The process cannot access the file because it is being used by another process." with SystemReader

I have no coding experience but have been trying to fix a broken program many years ago. I've been fumbling through fixing things but have stumbled upon a piece that I can't fix. From what I've gathered you get Alexa to append a Dropbox file and the program reads that file looking for the change and, depending on what it is, executes a certain command based on a customizable list in an XML document.
I've gotten this to work about five times in the hundred of attempts I've done, every other time it will crash and Visual Studio gives me: "System.IO.IOException: 'The process cannot access the file 'C:\Users\\"User"\Dropbox\controlcomputer\controlfile.txt' because it is being used by another process.'"
This is the file that Dropbox appends and this only happens when I append the file, otherwise, the program works fine and I can navigate it.
I believe this is the code that handles this as this is the only mention of StreamReader in all of the code:
public static void launchTaskControlFile(string path)
{
int num = 0;
StreamReader streamReader = new StreamReader(path);
string str = "";
while (true)
{
string str1 = streamReader.ReadLine();
string str2 = str1;
if (str1 == null)
{
break;
}
str = str2.TrimStart(new char[] { '#' });
num++;
}
streamReader.Close();
if (str.Contains("Google"))
{
MainWindow.googleSearch(str);
}
else if (str.Contains("LockDown") && Settings.Default.lockdownEnabled)
{
MainWindow.executeLock();
}
else if (str.Contains("Shutdown") && Settings.Default.shutdownEnabled)
{
MainWindow.executeShutdown();
}
else if (str.Contains("Restart") && Settings.Default.restartEnabled)
{
MainWindow.executeRestart();
}
else if (!str.Contains("Password"))
{
MainWindow.launchApplication(str);
}
else
{
SendKeys.SendWait(" ");
Thread.Sleep(500);
string str3 = "potato";
for (int i = 0; i < str3.Length; i++)
{
SendKeys.SendWait(str3[i].ToString());
}
}
Console.ReadLine();
}
I've searched online but have no idea how I could apply anything I've found to this. Once again before working on this I have no coding experience so act like you're talking to a toddler.
Sorry if anything I added here is unnecessary I'm just trying to be thorough. Any help would be appreciated.
I set up a try delay pattern like Adriano Repetti said and it seems to be working, however doing that flat out would only cause it to not crash so I had to add a loop around it and set the loop to stop when a variable hit 1, which happened whenever any command types are triggered. This takes it out of the loop and sets the integer back to 0, triggering the loop again. That seems to be working now.

Search keyword in line and print the line and the following line

I am using the following approach to parse a text file and write the line that contains a specific keyword:
using (StreamReader sr = new StreamReader("C:/Users/Downloads/apple.txt"))
{
string appleLine;
bool lastLine = false;
// currentLine will be null when the StreamReader reaches the end of file
while ((appleLine = sr.ReadLine()) != null)
{
// Search, case insensitive, if the currentLine contains the searched keyword
if (appleLine.IndexOf("Apple", StringComparison.CurrentCultureIgnoreCase) >= 0 || lastLine)
{
Console.WriteLine(appleLine);
Console.WriteLine();
using (System.IO.StreamWriter file = new System.IO.StreamWriter(#"C:\Users\Downloads\parsed.txt", true))
{
file.WriteLine(appleLine);
file.WriteLine();
}
lastLine = true;
}
if (lastLine)
{
lastLine = false;
}
}
In apple.txt I have something like this:
--- Line1 Apple MacBook Pro ---
--- Line2 www.newegg.com ---
But this does not print out the line with the URL (Line 2). The apple.txt file could have something like 200 Lines.
Thank you very much for help!
Try to use a boolean that shows you found something to print and need to print the next line too. for example:
class Program
{
static void Main(string[] args)
{
bool nextLineToPrint = false;
using (StreamReader sr = new StreamReader("c:/temp/ESMDLOG.csv"))
{
string currentLine;
// currentLine will be null when the StreamReader reaches the end of file
while ((currentLine = sr.ReadLine()) != null)
{
if (nextLineToPrint)
{
Console.WriteLine(currentLine);
nextLineToPrint = false;
}
// Search, case insensitive, if the currentLine contains the searched keyword
if (currentLine.IndexOf("I/RPTGEN", StringComparison.CurrentCultureIgnoreCase) >= 0)
{
Console.WriteLine(currentLine);
nextLineToPrint = true;
}
}
}
Console.ReadLine();
}
}
You could try using a boolean that indicates if the 'currentline' has been printed, then break out of the loop after the next line is printed. This way not only the currentLine will be printed, but also the next line, after which the while-loop will be exited.
using (StreamReader sr = new StreamReader("c:/temp/ESMDLOG.csv"))
{
string currentLine;
**bool lastline = false;**
// currentLine will be null when the StreamReader reaches the end of file
while((currentLine = sr.ReadLine()) != null)
{
// Search, case insensitive, if the currentLine contains the searched keyword
if(currentLine.IndexOf("I/RPTGEN", StringComparison.CurrentCultureIgnoreCase) >= 0 **|| lastline**)
{
Console.WriteLine(currentLine);
lastline = true;
}
**//Optional, could also say lastline = false inside if, in case you want to keep looping after printing**
**if(lastline){
break;
}**
}
}
Without a more precise problem statement, it's impossible to know for sure what output you want. But something like the following will meet the goal as constrained so far:
using (StreamReader sr = new StreamReader("c:/temp/ESMDLOG.csv"))
{
bool printWindow = false;
Queue<string> window = new Queue<string>();
string currentLine;
// currentLine will be null when the StreamReader reaches the end of file
while((currentLine = sr.ReadLine()) != null)
{
bool nextPrintWindow = false
// Search, case insensitive, if the currentLine contains the searched keyword
if(currentLine.IndexOf("I/RPTGEN", StringComparison.CurrentCultureIgnoreCase) >= 0)
{
nextPrintWindow = true;
}
if (window.Count >= 3)
{
window.Dequeue();
}
window.Enqueue(currentLine);
if (printWindow)
{
Console.WriteLine(string.Join(Environment.NewLine, window));
}
printWindow = nextPrintWindow;
}
}
(Warning: browser-only code above. Please forgive typos and other oversights.)
The above maintains a window collection, i.e. a three-line "window" of the text in the file, by enqueuing the current line, and dequeuing the oldest line if the collection reaches a count of three elements.
At the same time, it maintains a flag that indicates whether to print the contents of the window after reading the next line. If this flag is set to true, it concatenates the lines in the window collection with newline characters and prints the whole thing out.
In this way, the current line along with the previous and next lines are all printed out if the current line meets your match criteria.
Note that the above will print three-line windows for every match. Lines may be printed more than once (as part of different three-line groups) if, for example, consecutive lines meet the match criteria. An alternative implementation would allow the window to grow beyond three elements if consecutive lines meet the match criteria, printing (and restarting) the window only once a line that doesn't meet the match criteria has been read.
Yet another alternative would require two non-matching lines before printing the window, i.e. if you want to make sure that even the non-matching lines are only ever printed once.
I leave those variation as an exercise for the reader. They would not be a lot different from the above, just minor changes in the maintenance of the window and management of the implied state machine encapsulated in the flag variables.

How to handle EOF when have a string of NUL characters

I am reading a file using this
while ((line = f1.ReadLine()) != null)
however my program can't handle the last line which always have this in debugger "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0....on and on"
what is the best way to handle this?
while ((line = f1.ReadLine()) != null)
{
doing abc
}
when I run debugger it 's still going inside the loop and doing abc. ofcouse it fails because there is nothing in the line
Unfortunately, a string of null:
'\0\0\0\0\0\0\0\0\0\0`
Isn't == null. You could try something like this:
while(!string.IsNullOrEmpty(line = f1.ReadLine()))
{
if (line[0]=='\0') {
/// strings should rarely start with null, so feel feel to break out of your loop here.
}
else
{
// found some real content, so process normally.
}
}
I'm not a fan of those type of checks, though. Hopefully someone else will have a better suggestion.
A better question might be: Why am I getting a massively-long string of nulls when reading a text file line-by-line?

Is it possible to read unknown number of lines from console in C#?

There is a function, which can read a single line from the console input (Console.ReadLine()), but I wish to read or some arbitrary number of lines, which is unknown at compile time.
Of course it is. Just use just read a single line (using ReadLine() or whatever else you please) at a time within either a for loop (if you know at the beginning of reading how many lines you need) or within a while loop (if you want to stop reading when you reach EOF or a certain input).
EDIT:
Sure:
while ((line = Console.ReadLine()) != null) {
// Do whatever you want here with line
}
Some of the other answers here loop until a null line is encountered while others expect the user to type something special like "EXIT". Keep in mind that reading from the console could be either a person typing or a redirected input file:
myprog.exe < somefile.txt
In the case of redirected input Console.ReadLine() would return null when it hits the end of the file. In the case of a user running the program interactively they'd have to know to how to enter the end of file character (Ctrl+Z followed by enter or F6 followed by enter). If it is an interactive user you might need to let them know how to signal the end of input.
simple example:
class Program
{
static void Main()
{
CountLinesInFile("test.txt"); // sample input in file format
}
static long CountLinesInFile(string f)
{
long count = 0;
using (StreamReader r = new StreamReader(f))
{
string line;
while ((line = r.ReadLine()) != null)
{
count++;
}
}
return count;
}
}
The best thing to do here is use a loop:
string input;
Console.WriteLine("Input your text (type EXIT to terminate): ");
input = Console.ReadLine();
while (input.ToUpper() != "EXIT")
{
// do something with input
Console.WriteLine("Input your text(type EXIT to terminate): ");
input = Console.ReadLine();
}
Or you could do something like this:
string input;
do
{
Console.WriteLine("Input your text (type EXIT to terminate): ");
input = Console.ReadLine();
if (input.ToUpper() != "EXIT")
{
// do something with the input
}
} while (input.ToUpper() != "EXIT");

How can I read a value from an INI file in C#?

I have an INI file that I want to read the line DeviceName=PHJ01444-MC35 from group [DEVICE] and assign the value to a string.
[BEGIN-DO NOT CHANGE/MOVE THIS LINE]
[ExecList]
Exec4=PilotMobileBackup v1;Ver="1.0";NoUninst=1
Exec3=MC35 108 U 02;Ver="1.0.8";NoUninst=1
Exec2=FixMGa;Ver="1.0";Bck=1
Exec1=Clear Log MC35;Ver="1.0";Bck=1
[Kiosk]
Menu8=\Program Files\PilotMobile\Pilot Mobile Backup.exe
MenuCount=8
AdminPwd=D85F72A85AE65A71BF3178CC378B260E
MenuName8=Pilot Mobile Backup
Menu7=\Windows\SimManager.exe
MenuName7=Sim Manager
UserPwd=AF2163B24AF45971
PasswordPolicy=C34B3DE916AA052DCB2A63D7DCE83F17
DisableBeam=0
DisableBT=0
DisableSDCard=0
EnableAS=1
ActionCount=0
Url=file://\Application\MCPortal.htz
AutoLaunch=0
Menu6=\Windows\solitare.exe
MenuName6=Solitare
Menu5=\Windows\bubblebreaker.exe
MenuName5=Bubble Breaker
Menu4=\Windows\wrlsmgr.exe
MenuName4=Communications
Menu3=\Windows\Calendar.exe
MenuName3=Calendar
Menu2=\Windows\tmail.exe
MenuName2=Text Messaging
Menu1=\Program Files\PilotMobile\Pilot.Mobile.exe
MenuName1=Pilot Mobile
ShowStartMenu=1
CustomTaskBar=0
IdleTimeout=0
NoTaskbar=0
PPCKeys=1111111111111111
On=1
[Status]
MCLastConn=2006/10/01 00:50:56
[Connection]
DeploySvr1=********
[Locations]
Backup=Backup
Install=\Application
[Comm]
RetryDelay=60000
NoInBoundConnect=0
TLS=0
Broadcast=1
[Info]
LID=090128-117
PWDID=081212-10
TimeSyncID={249CEE72-5918-4D18-BEA8-11E8D8D972BF}
TimeSyncErrorInterval=5
TimeSyncInterval=120
AutoTimeSync=1
SecondarySNTPServer=ntp1.uk.uu.net
DefaultSNTPServer=ntp0.uk.uu.net
DepServerTimeSyncType=4
TimeSyncServerType=1
DFID=080717-8
Platform=PPC
Method=39
SiteName=*****
[Device]
SyncTimer=4
Ver=1
DeviceID={040171BD-3603-6106-A800-FFFFFFFFFFFF}
ShowTrayIcon=1
DeviceIDType=2
DeviceClass=AADE7ECE-DF8C-4AFC-89D2-DE7C73B579D0
DeviceName=PHJ01444-MC35
NameType=2
[END-DO NOT CHANGE/MOVE THIS LINE]
You could use Windows API for this. See http://jachman.wordpress.com/2006/09/11/how-to-access-ini-files-in-c-net/
Edit: As noted in the comments the page is no longer available on the original site, however it's still accessible on the Wayback Machine.
Additionally there is a more recent article on MSDN about accessing the required functions.
Because writing everything in one line makes me a better person than you:
string s = File.ReadAllText("inifile.ini").Split('\r', '\n').First(st => st.StartsWith("DeviceName"));
If you wanted the very simple but not very clean answer:
using System.IO;
StreamReader reader = new StreamReader(filename);
while(reader.ReadLine() != "[DEVICE]") { continue; }
const string DeviceNameString = "DeviceName=";
while(true) {
string line = reader.ReadLine();
if(line.Length < DeviceNameString.Length) { continue; }
else if(line.Substring(0, DeviceNameString.Length) != DeviceNameString) { continue; }
return line.Substring(DeviceNameString.Length);
}
If you're only intending to read one value from the file, it's a plausible option. I would probably combine the loops and add for some end of file checking though myself if you're serious about using this code.
string line;
string deviceName = string.Empty;
// Read the file and display it line by line.
using (System.IO.StreamReader file =
new System.IO.StreamReader("c:\\file.ini"))
{
while ((line = file.ReadLine()) != null)
{
if (line.ToLower().StartsWith("devicename"))
{
string[] fullName = line.Split('=');
deviceName = fullName[1];
break;
}
}
}
Console.WriteLine("Device Name =" + deviceName);
Console.ReadLine();
I am sure there are other ways.

Categories

Resources