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?
Related
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.
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.
I have an app that reads from text files to determine which reports should be generated. It works as it should most of the time, but once in awhile, the program deletes one of the text files it reads from/writes to. Then an exception is thrown ("Could not find file") and progress ceases.
Here is some pertinent code.
First, reading from the file:
List<String> delPerfRecords = ReadFileContents(DelPerfFile);
. . .
private static List<String> ReadFileContents(string fileName)
{
List<String> fileContents = new List<string>();
try
{
fileContents = File.ReadAllLines(fileName).ToList();
}
catch (Exception ex)
{
RoboReporterConstsAndUtils.HandleException(ex);
}
return fileContents;
}
Then, writing to the file -- it marks the record/line in that file as having been processed, so that the same report is not re-generated the next time the file is examined:
MarkAsProcessed(DelPerfFile, qrRecord);
. . .
private static void MarkAsProcessed(string fileToUpdate, string
qrRecord)
{
try
{
var fileContents = File.ReadAllLines(fileToUpdate).ToList();
for (int i = 0; i < fileContents.Count; i++)
{
if (fileContents[i] == qrRecord)
{
fileContents[i] = string.Format("{0}{1} {2}"
qrRecord, RoboReporterConstsAndUtils.COMPLETED_FLAG, DateTime.Now);
}
}
// Will this automatically overwrite the existing?
File.Delete(fileToUpdate);
File.WriteAllLines(fileToUpdate, fileContents);
}
catch (Exception ex)
{
RoboReporterConstsAndUtils.HandleException(ex);
}
}
So I do delete the file, but immediately replace it:
File.Delete(fileToUpdate);
File.WriteAllLines(fileToUpdate, fileContents);
The files being read have contents such as this:
Opas,20170110,20161127,20161231-COMPLETED 1/10/2017 12:33:27 AM
Opas,20170209,20170101,20170128-COMPLETED 2/9/2017 11:26:04 AM
Opas,20170309,20170129,20170225-COMPLETED
Opas,20170409,20170226,20170401
If "-COMPLETED" appears at the end of the record/row/line, it is ignored - will not be processed.
Also, if the second element (at index 1) is a date in the future, it will not be processed (yet).
So, for these examples shown above, the first three have already been done, and will be subsequently ignored. The fourth one will not be acted on until on or after April 9th, 2017 (at which time the data within the data range of the last two dates will be retrieved).
Why is the file sometimes deleted? What can I do to prevent it from ever happening?
If helpful, in more context, the logic is like so:
internal static string GenerateAndSaveDelPerfReports()
{
string allUnitsProcessed = String.Empty;
bool success = false;
try
{
List<String> delPerfRecords = ReadFileContents(DelPerfFile);
List<QueuedReports> qrList = new List<QueuedReports>();
foreach (string qrRecord in delPerfRecords)
{
var qr = ConvertCRVRecordToQueuedReport(qrRecord);
// Rows that have already been processed return null
if (null == qr) continue;
// If the report has not yet been run, and it is due, add i
to the list
if (qr.DateToGenerate <= DateTime.Today)
{
var unit = qr.Unit;
qrList.Add(qr);
MarkAsProcessed(DelPerfFile, qrRecord);
if (String.IsNullOrWhiteSpace(allUnitsProcessed))
{
allUnitsProcessed = unit;
}
else if (!allUnitsProcessed.Contains(unit))
{
allUnitsProcessed = allUnitsProcessed + " and "
unit;
}
}
}
foreach (QueuedReports qrs in qrList)
{
GenerateAndSaveDelPerfReport(qrs);
success = true;
}
}
catch
{
success = false;
}
if (success)
{
return String.Format("Delivery Performance report[s] generate
for {0} by RoboReporter2017", allUnitsProcessed);
}
return String.Empty;
}
How can I ironclad this code to prevent the files from being periodically trashed?
UPDATE
I can't really test this, because the problem occurs so infrequently, but I wonder if adding a "pause" between the File.Delete() and the File.WriteAllLines() would solve the problem?
UPDATE 2
I'm not absolutely sure what the answer to my question is, so I won't add this as an answer, but my guess is that the File.Delete() and File.WriteAllLines() were occurring too close together and so the delete was sometimes occurring on both the old and the new copy of the file.
If so, a pause between the two calls may have solved the problem 99.42% of the time, but from what I found here, it seems the File.Delete() is redundant/superfluous anyway, and so I tested with the File.Delete() commented out, and it worked fine; so, I'm just doing without that occasionally problematic call now. I expect that to solve the issue.
// Will this automatically overwrite the existing?
File.Delete(fileToUpdate);
File.WriteAllLines(fileToUpdate, fileContents);
I would simply add an extra parameter to WriteAllLines() (which could default to false) to tell the function to open the file in overwrite mode, and not call File.Delete() at all then.
Do you currently check the return value of the file open?
Update: ok, it looks like WriteAllLines() is a .Net Framework function and therefore cannot be changed, so I deleted this answer. However now this shows up in the comments, as a proposed solution on another forum:
"just use something like File.WriteAllText where if the file exists,
the data is just overwritten, if the file does not exist it will be
created."
And this was exactly what I meant (while thinking WriteAllLines() was a user defined function), because I've had similar problems in the past.
So, a solution like that could solve some tricky problems (instead of deleting/fast reopening, just overwriting the file) - also less work for the OS, and possibly less file/disk fragmentation.
Okay so i'm trying to load up a bunch of profiles through C# and I keep getting this error when I try to start up the program.
C:\C#FILES>program.exe
Unhandled Exception: System.IndexOutOfRangeException: Index was outside the boun
ds of the array.
at ConsoleApplication2.Program.loadAccounts()
at ConsoleApplication2.Program.Main(String[] args)
C:\C#FILES>
i've investigated and i think it has to do with the format of the accounts in the file
i'm wondering what the proper way is, i've tried every way i can think of
here's the loading accounts method
private static void loadAccounts()
{
using (TextReader tr = new StreamReader("accounts.txt"))
{
string line = null;
while ((line = tr.ReadLine()) != null)
{
String[] details = line.Split('\t');
accounts.Add(details[0] + ":" + details[1]);
}
}
}
the accounts.txt part is the part i'm unsure about, i thought it would be as follows
username(tab)password
like this
username password
however it gives the error shown above
does anyone know what the proper account format should be?
You're getting an IndexOutOfRangeException, which suggests that details only had a single entry - which means there wasn't a tab on that line.
I suggest you print out the line in question before splitting, so you can see which line is causing problems. Or possibly do it conditionally:
while ((line = tr.ReadLine()) != null)
{
String[] details = line.Split('\t');
if (details.Length == 1)
{
// Or log it, or whatever...
Console.WriteLine("Input error: no tab in line '{0}'", line);
}
else
{
accounts.Add(details[0] + ":" + details[1]);
}
}
This is occurring because the line you are splitting from your input does not contain the elements requested.
It is unlikely that the first (read: 0th) element in the array is the cause of the issue because of the way that .NET deals with Split.
Have you check that there are no blank lines in your input file? A single blank line (even at the end of the file) would cause this issue.
There are multiple checks you could add such as..
if(!string.IsNullOrWhitespace(line)) ...
or
if(details.Length > 1)
These are a few checks, either or both I would recommend implementing (there are more to consider) otherwise you are just blindly trusting input values and that is not good practice in general.
If my program is printing to the console, I perform word-wrapping in a certain way according to Console.WindowWidth by inserting newlines - and this works perfectly.
However if the output of the program is redirected to a file or another program I would like it to skip the word-wrapping. How can I detect when this is the case?
Console.WindowWidth returns the same number in both cases.
Bonus points if the solution can distinguish redirected Console.Out from redirected Console.Error.
.NET 4.5 adds Console.IsOutputRedirected and Console.IsErrorRedirected.
p/invoke GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)), or call an innocuous console function like GetConsoleScreenBufferInfo to check for invalid handle error. If you want to know about standard error, use STD_ERROR_HANDLE. I believe you can even compare handles returned by GetStdHandle(STD_OUTPUT_HANDLE) and GetStdHandle(STD_ERROR_HANDLE) to detect stuff like 2>&1.
While this is a little shady and probably isn't guaranteed to work, you can try this:
bool isRedirected;
try
{
isRedirected = Console.CursorVisible && false;
}
catch
{
isRedirected = true;
}
Calling CursorVisible throws an exception when the console is redirected.
You need to use reflection - a bit grubby but the following will work:
static bool IsConsoleRedirected()
{
var writer = Console.Out;
if (writer == null || writer.GetType ().FullName != "System.IO.TextWriter+SyncTextWriter") return true;
var fld = writer.GetType ().GetField ("_out", BindingFlags.Instance | BindingFlags.NonPublic);
if (fld == null) return true;
var streamWriter = fld.GetValue (writer) as StreamWriter;
if (streamWriter == null) return true;
return streamWriter.BaseStream.GetType ().FullName != "System.IO.__ConsoleStream";
}
Why does the ouput wrap in the redirected file? The wrapping that the console does is not by means of line breaks. In other words this string:
hello my name is Andrew Hare
would wrap in a skinny console like this:
hello my nam
e is Andrew
Hare
but if you were to redirect the output to a file it would be written like this:
hello my name is Andrew Hare
since there are no true line-breaks in the output.
Don't do that! Just pass an additional command line parameter that specifies the formatting you want to be applied. It's simpler, cleaner, and easier to understand both by people that will use your app and by people who will work on your code.