I have a program that reads text files filled with code designed to be executed line by line by the program, like a batch file. The problem is that I don't no how to do the line executing part. Here is my code, I thought using the \r would fool the console. But it just shows me a list of lines in the file.
if (tok[0] == "read" && length == 2)
{
try
{
StreamReader tr = new StreamReader(#"C:\Users\Public\"+tok[1]+".txt");
while (!tr.EndOfStream)
{
Console.WriteLine(tr.ReadLine());
}
}
catch
{
Console.WriteLine("No such text file.\n");
}
Prompt();
}
If I knew what to search for to fix my problem in Google, I would have. But I've got no idea.
Thanks
EDIT - My program is a crude synthesizer. It takes inputs in the form of 440 5, or 415 2. The first number is frequency, the second duration. What I'm wanting to do is read text files, which my code does, and execute the sound info line by line, which it doesn't, hence my question. It works perfectly fine from standard input.
Audio synthesis is not straightforward, there used to be
Console.Beep(frequency,duration);
but that's using the PC speaker most systems don't have anymore - here's an example though using DirectSound to achieve something close to what you want.
To read the frequency and duration from your text file you can use something like this (splitting on space):
StreamReader tr = new StreamReader(#"test.txt");
while(!tr.EndOfStream)
{
string[] parts = tr.ReadLine().Split(new[]{' '});
int frequency = Convert.ToInt32(parts[0]);
int duration = Convert.ToInt32(parts[1]);
}
You should load your code and compile it in the runtime.
Check out following examples:
http://www.csharpfriends.com/articles/getarticle.aspx?articleid=118
http://www.codeproject.com/KB/dotnet/evaluator.aspx
EDIT:
You should use Process.Start(cmd); to execute commands in the shell. Here I've found few nice examples: http://dotnetperls.com/process-start
If your program works fine using Standard Input just pass the text file to it like this:
yourprogram.exe < textFile.txt
Then the contents of the text file will be passed to your program on Standard Input.
Related
Is it possible to save what is typed in the console to a text file?
I know how to write and read from a text file, but I would like to know how to save what is typed in console itself to a text file.
So opening a console, typing text in the console itself (the black console screen), pressing Enter (or something else), and saving it to a file.
I haven't found any answers that work so I'm beginning to think it isn't possible.
On a side note; is there another name for that console application window? Or is it actually called console application window?
I haven't found any answers that work so I'm beginning to think it isn't possible.
What were you searching on? Console.ReadLine() returns a string, which is easily appended to a file:
using (var writer = new StreamWriter("ConsoleOutput.txt", append: true))
{
string line = Console.ReadLine();
writer.WriteLine(line);
}
Not all problems are solved on the web exactly as you require; break it up in smaller parts ("get string from console", "write string to file") and you will find the solution specific to your situation.
If this is about reading output from another process, this is a duplicate of How to spawn a process and capture its STDOUT in .NET?.
Use this code to redirect console output to a text file with name consoleOut.txt
FileStream filestream = new FileStream("consoleOut.txt", FileMode.Create);
var streamwriter = new StreamWriter(filestream);
streamwriter.AutoFlush = true;
Console.SetOut(streamwriter);
There are different approaches:
Just use Console.ReadLine() for this in loop until some specific symbol. At the same time adding lines to a file stream.
Another elegant solution to use Console.SetOUt method. Take a look on second example from MSDN. Pretty much what you need.
If it is no external console window, you can use Console.ReadLine() to get the typed string and save it to a file by calling e.g. File.WriteAllText, StreamWriter,...
If I am searching for strings in the same LOG file many times through the day would it be faster to somehow go to the last line read in the file on the previous search and then begin reading line by line? Would there be any significant savings here?
EXAMPLE FILE
process ID logic
11111 Run some silly logic on middle tier servers.
11111 Still running logic
22222 Run some silly logic on middle tier servers from another user.
11111 Oh look the first process is done.
22222 Still running logic on the second process.
There are times I want many lines of a file from the last time I last loaded it. Currently I use UltraEdit to load the file once and then update file but this still takes quite a bit of time.
In this example above I want ever line from the first process.
NOTE:
The file can be several hundred MB in size at times.
The example above is abbreviated, each process ID may contain 100''s of lines of logic.
I am accessing the log file across a network. I have found that with UE it is faster to load the file from across the network and then continue to update file than to copy to my local PC and then open it.
I am hoping to have a C# console application that can be ran from powershell and pipe the lines I want to the screen or to a file.
Another question I have is what would make this process as efficient as possible?
1. in regards to C# methods used for my file size?
2. in regards to application used to write the utility? I have powershell, C#, C++, perl
This would be possible using Stream.Seek. You would just have to remember what the last position in the stream was, then move forward from there. If your log file only adds lines to it, this will work just fine, and it will certainly be faster than reading and scanning the same lines over and over again.
If you post some of your existing code, I can even help you write the code to do it.
http://msdn.microsoft.com/en-us/library/system.io.stream.seek.aspx
I've wanted to implement something like this myself, so I took some time to give it a shot. Here's an extension method (you'll have to put it in a static class) to FileStream I've come up with:
public static string ReadLineAndCountPosition(this FileStream fs, ref long position)
{
//Check if too great a position was passed in:
if (position > fs.Length)
return null;
bool is_carriage_return = false;
StringBuilder sb = new StringBuilder();
fs.Seek(position, SeekOrigin.Begin);
while (position < fs.Length)
{
var my_byte = fs.ReadByte();
position++;
//Check for newlines
if (is_carriage_return && my_byte == 10)// \n
return sb.ToString();
if (my_byte == 13) // \r
is_carriage_return = true;
else
{
is_carriage_return = false;
sb.Append((char)my_byte);
}
}
return sb.ToString();//We've consumed the entire file.
}
And to use it, you can use ReadLineAndCountPosition by simply calling it and passing in a long parameter which we will save the position in. We will simply .Seek() to this position some time later.
static void Main(string[] args)
{
FileStream fs = new FileStream("testfile.txt",FileMode.Open);
long saved_position = 0;
while(true)
{
string current_line = fs.ReadLineAndCountPosition(ref saved_position);
if (current_line == null || current_line == "SomeSearchString")
break;
}
//Some time later we want to search from the saved position:
while(true)
{
string current_line = fs.ReadLineAndCountPosition(ref saved_position);
if (current_line == null || current_line == "SecondSearchString")
break;
}
}
I ran a few tests myself, and it seems to have worked fine. Let me know if you have any troubles. Hopefully it helps you out.
A few days ago I've asked a question concerning how to detect an end of input file of N(N is unknown) lines.
StringBuilder input = new StringBuilder();
int endOfFile = 0
while ((endOfFile = Console.Read()) != -1) {
input.Append(((char)endOfFile).ToString());
input.Append(Console.ReadLine());
}
I've edited my question, but I guess this is the same as some of the hints below.
#Jagannath basically had it, exactly as you asked, except for one little detail: That method works on the console as well, without involving an explicit StreamReader:
string line;
while ((line = Console.ReadLine()) != null)
{
// TODO: Add processing
Console.WriteLine(line);
}
If you're typing directly in the console instead of relying on input redirected from a file, press CTRL-Z or F6 to trigger an "end of file" on the console input. Inside the console, F6 is just a synonym of CTRL-Z.
Be aware that CTRL-Z here is an interrupt sequence or signal, not an input character. It will show ^Z on the screen. but you will not receive the CTRL-Z (U+001A) character in the program. The CTRL-Z sequence is trapped by the console and causes the input stream to close as if the "file had reached the end". Do not insert a CTRL-Z in the input file.
The origin of using CTRL-Z for this purpose goes back to at least the CP/M operating system (a short entertaining story on its own right, but one which is out of scope).
This could help in looping through the file and check for end of file.
using (StreamReader sr = new StreamReader(#"test.txt"))
{
string line;
while ( (line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
UPDATE
Here is a link from msdn ReadLine method
Are you planning on using the shell to redirect standard input to your input file?
Why not use something like TextReader.Read() or TextReader.ReadLine()? http://msdn.microsoft.com/en-us/library/system.io.textreader.aspx
Not quite sure why you're asking this, since the answer you accepted to your previous question is the easiest way to do what you were asking there. Are you just looking for alternate solutions?
You should check the documentation for Console.ReadKey. In the Remarks it says:
The ReadKey method reads from the keyboard even if the standard input is redirected to a file with the SetIn method.
ReadKey will block until you press a key on the keyboard. You can't use ReadKey to detect the end of redirected input.
To read input from a file you can use
var text = File.ReadAllLines("path/to/file.txt");
If what you want is to get input from the console character by character, you can do something like this:
ConsoleKeyInfo keyInfo;
while ((keyInfo = Console.ReadKey()).Key != ConsoleKey.Escape)
{
}
You can replace ConsoleKey.Escape with any other key, or check for key combinations like CTRL+D, CTRL+C, by using keyInfo.Modifiers.
This question seems to have been asked a million times around the web, but I cannot find an answer which will work for me.
Basically, I have a CSV file which has a number of columns (say two). The program goes through each row in the CSV file, taking the first column value, then asks the user for the value to be placed in the second column. This is done on a handheld running Windows 6. I am developing using C#.
It seems a simple thing to do. But I cant seem to add text to a line.
I cant use OleDb, as System.Data.Oledb isnt in the .Net version I am using. I could use another CSV file, and when they complete each line, it writes it to another CSV file. But the problems with that are - The file thats produced at the end needs to contain EVERY line (so what if they pull the batterys out half way). And what if they go back, to continue doing this another time, how will the program know where to start back from.
For every row, open the output file, append the new row to it, and then close the output file. To restart, count the number of rows in the existing output file from the previous run, which will give you your starting in the input file (i.e., skip that number of rows in the input file).
Edit: right at the start, use System.IO.File.Copy to copy the input file to the output file, so you have all the file in case of failure. Now open the input file, read a line, convert it, use File.ReadAllLines to read ALL of the output file into an array, replace the line you have changed at the right index in the array, then use File.WriteAllLines to write out the new output file.
Something like this:
string inputFileName = ""; // Use a sensible file name.
string outputFileName = ""; // Use a sensible file name.
File.Copy(inputFileName, outputFileName, true);
using (StreamReader reader = new StreamReader(inputFileName))
{
string line = null;
int inputLinesIndex = 0;
while ((line = reader.ReadLine()) != null)
{
string convertedLine = ConvertLine(line);
string[] outputFileLines = File.ReadAllLines(outputFileName);
if (inputLinesIndex < outputFileLines.Length)
{
outputFileLines[inputLinesIndex] = convertedLine;
File.WriteAllLines(outputFileName, outputFileLines);
}
inputLinesIndex++;
}
}
Yes this is an exact duplicate of this question, but the link given and accepted as answer is not working for me. It is returning incorrect values (a 2 minutes mp3 will be listed as 1'30, 3 minutes as 2'20) with no obvious pattern.
So here it is again: how can I get the length of a MP3 using C# ?
or
What am I doing wrong with the MP3Header class:
MP3Header mp3hdr = new MP3Header();
bool boolIsMP3 = mp3hdr.ReadMP3Information("1.mp3");
if(boolIsMP3)
Response.Write(mp3hdr.intLength);
Apparently this class computes the duration using fileSize / bitRate. This can only work for constant bitrate, and I assume your MP3 has variable bitRate...
EDIT : have a look at TagLib Sharp, it can give you the duration
How have you ascertained the lengths of the MP3s which are "wrong"? I've often found that the header information can be wrong: there was a particular version of LAME which had this problem, for example.
If you bring the file's properties up in Windows Explorer, what does that show?
I wrapped mp3 decoder library and made it available for .net developers. You can find it here:
http://sourceforge.net/projects/mpg123net/
Included are the samples to convert mp3 file to PCM, and read ID3 tags.
I guess that you can use it to read mp3 file duration. Worst case will be that you read all the frames and compute the duration - VBR file.
To accurately determine mp3 duration, you HAVE TO read all the frames and calculate duration from their summed duration. There are lots of cases when people put various 'metadata' inside mp3 files, so if you estimate from bitrate and file size, you'll guess wrong.
I would consider using an external application to do this. Consider trying Sox and just run the version of the program that's executed by using soxi (no exe) and try parsing that output. Given your options I think you're better off just trusting someone else who has spent the time to work out all the weirdness in mp3 files unless this functionality is core to what you're doing. Good luck!
The second post in the thread might help you: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/c72033c2-c392-4e0e-9993-1f8991acb2fd
Length of the VBR file CAN'T be estimated at all. Every mp3 frame inside of it could have different bitrate, so from reading any part of the file you can't know what density of the data is at any other part of the file. Only way of determining EXACT length of VBR mp3 is to DECODE it in whole, OR (if you know how) read all the headers of the frames one by one, and collect their decoded DURATION.
You will use later method only if the CPU that you use is a precious resource that you need to save. Otherwise, decode the whole file and you'll have the duration.
You can use my port of mpg123 to do the job: http://sourceforge.net/projects/mpg123net/
More: many mp3 files have "stuff" added to it, as a id3 tags, and if you don't go through all the file you could mistakenly use that tag in duration calculation.
There is my solution for C# with sox sound processing library.
public static double GetAudioDuration(string soxPath, string audioPath)
{
double duration = 0;
var startInfo = new ProcessStartInfo(soxPath,
string.Format("\"{0}\" -n stat", audioPath));
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardOutput = true;
var process = Process.Start(startInfo);
process.WaitForExit();
string str;
using (var outputThread = process.StandardError)
str = outputThread.ReadToEnd();
if (string.IsNullOrEmpty(str))
using (var outputThread = process.StandardOutput)
str = outputThread.ReadToEnd();
try
{
string[] lines = str.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
string lengthLine = lines.First(line => line.Contains("Length (seconds)"));
duration = double.Parse(lengthLine.Split(':')[1]);
}
catch (Exception ex)
{
}
return duration;
}