How to accelerate buffering of output string? - c#

This code times two methods of outputting a ~380Kb string:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
static string outbuff = "";
static void Main(string[] args)
{
{
Stopwatch exectime = new Stopwatch();
System.IO.StreamWriter file;
exectime.Reset(); exectime.Start();
file = new System.IO.StreamWriter("output.html");
for (int i = 0; i < 18000; i++)
{
outbuff += "444444444, 5555555555\n";
}
string fin = "\nString method took " + exectime.Elapsed.TotalSeconds + "s";
file.WriteLine(outbuff);
Console.WriteLine(fin);
file.WriteLine(fin);
file.Close();
}
{
Stopwatch exectime = new Stopwatch();
System.IO.StreamWriter file;
exectime.Reset(); exectime.Start();
file = new System.IO.StreamWriter("output2.html");
for (int i = 0; i < 18000; i++)
{
file.Write("444444444, 5555555555\n");
}
string fin = "\nDirect method took " + exectime.Elapsed.TotalSeconds + "s";
Console.WriteLine(fin);
file.WriteLine(fin);
file.Close();
}
}
}
}
String method took 2.2985349s
Direct method took 0.07191s
This is on a 3.5GHz CPU with 5Gb RAM.
I'm disappointed that simply buffering the output in a string is so costly!
In my real program, I need to deferr output until the string is assembled. Is there a faster way?

Yes, use a StringBuilder instead to assemble your string.
For an in-depth explanation for the performance boost see "Using the StringBuilder Class" - but basically because strings are immutable a new string is created when you concatenate, which is very expensive.

Related

Keep receiving error code CS0165

I keep getting the aggravated CS0165 error code. I have re-written this several times and even googled the issues. I cannot resolve this, it is for a college assignment that is now 2 days late. Can anyone please help. Would appreciate. This is the code below:
using System;
using System.IO;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Threading.Tasks;
namespace Assignment_2
{
class Program
{
static void Main()
{
string InputPath = #"C:\Users\....\Desktop\CP Class\Assignment 2\Asgn2InputFile.txt";
string OutputPath = #"C:\Users\....\Desktop\CP Class\Assignment 2\Payroll.txt";
using (StreamReader sr = new StreamReader(InputPath))
using (StreamWriter sw = new StreamWriter(OutputPath))
{
// input line
string InputLine;
// input fields
string First;
string Last;
int Hours;
int OverT;
double Pay;
// output fields
double Earnings;
double Gross;
//
sw.Write("NAME".PadRight(11));
sw.Write("HOURS WORKED ".PadRight(23));
sw.Write("PAY RATE".PadRight(20));
sw.Write("OVERTIME".PadRight(27));
sw.WriteLine();
while ((InputLine = sr.ReadLine()) != null)
// parse input line
First = InputLine.Substring(0, 5);
Last = InputLine.Substring(0, 11);
Pay = double.Parse(InputLine.Substring(31, 5));
Hours = int.Parse(InputLine.Substring(16, 2));
OverT = int.Parse(InputLine.Substring(29, 1));
//
Earnings = (Hours * Pay);
Gross = Earnings + (OverT * (Pay * 1.5));
sw.Write(First.PadRight(11)); [[ Error Code occurs here ]]
sw.WriteLine(Last.PadRight(11));
//
sw.Write(Earnings.ToString().PadLeft(10) + " # " + Gross.ToString("C").PadRight(9));
sw.WriteLine(Earnings.ToString("C").PadLeft(17));
sw.WriteLine();
//Total += Earnings;
}
}
}
}
The error CS0165 is because you are using variables that are not initialized....
the reason is the omitting of the { } here
while ((InputLine = sr.ReadLine()) != null)
which means, the while loop has as scope something else as what you need
in fact your code is equivalent to:
while ((InputLine = sr.ReadLine()) != null){
First = InputLine.Substring(0, 5);
}
leaving the rest uninitialized
Because your while loop doesn't have any braces to block the code it contains, it only takes the first line of code beneath as the content. Because the compiler cannot guarantee that line will run, the variable First might not be initialised.
So instead of doing this:
while (something)
DoSomething();
DoSomethingElse();
You should write:
while (something)
{
DoSomething();
DoSomethingElse();
}
You have multiple issues in your code
While loop braces are missing
You have declared your variables so far away from its first use and made it so long that it is difficult to see issues
Look at the below code which I think is what you want
using System;
using System.IO;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Threading.Tasks;
namespace Assignment_2 {
class Program {
static void Main() {
string InputPath = #"C:\Users\....\Desktop\CP Class\Assignment 2\Asgn2InputFile.txt";
string OutputPath = #"C:\Users\....\Desktop\CP Class\Assignment 2\Payroll.txt";
using (StreamReader sr = new StreamReader(InputPath))
using (StreamWriter sw = new StreamWriter(OutputPath)) {
sw.Write("NAME".PadRight(11));
sw.Write("HOURS WORKED ".PadRight(23));
sw.Write("PAY RATE".PadRight(20));
sw.Write("OVERTIME".PadRight(27));
sw.WriteLine();
// input line
string InputLine;
while ((InputLine = sr.ReadLine()) != null) {
// parse input line
var First = InputLine.Substring(0, 5);
var Last = InputLine.Substring(0, 11);
var Pay = double.Parse(InputLine.Substring(31, 5));
var Hours = int.Parse(InputLine.Substring(16, 2));
var OverT = int.Parse(InputLine.Substring(29, 1));
//
var Earnings = (Hours * Pay);
var Gross = Earnings + (OverT * (Pay * 1.5));
sw.Write(First.PadRight(11)); //Error Code occurs here
sw.WriteLine(Last.PadRight(11));
//
sw.Write(Earnings.ToString().PadLeft(10) + " # " + Gross.ToString("C").PadRight(9));
sw.WriteLine(Earnings.ToString("C").PadLeft(17));
sw.WriteLine();
//Total += Earnings;
}
}
}
}
}

Accessing variable in another namespace C#

I know this has been discussed many times on here, I've tried to set my variables as public etc. but I can't seem to be able to use it in my other name space. I'd appreciate if you could give me some tips (I'm a noob at C#)
The string i'm trying access from my other name space is "stringatlinei"
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Security;
using System.Security.Cryptography;
using System.IO;
using System.Net;
using Microsoft.Win32;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Net.Mail;
using ConsoleApplication32;
namespace ConsoleApplication32
{
public class Program
{
static void Main(string[] args)
{
DirSearch(#"C:\\Users\\");
Console.ReadKey();
}
static void DirSearch(string dir)
{
try
{
foreach (string d in Directory.GetDirectories(dir))
{
Console.WriteLine(d);
DirSearch(d);
// Compose a string that consists of three lines.
string lines = d;
// Write the string to a file.
System.IO.StreamWriter file = new
System.IO.StreamWriter("c:\\users\\chris\\desktop\\test.txt", true);
file.WriteLine(lines);
file.Close();
var oldLines = System.IO.File.ReadAllLines("c:\\users\\chris\\desktop\\test.txt");
var newLines = oldLines.Where(line => !line.Contains("Windows"));
System.IO.File.WriteAllLines("c:\\users\\chris\\desktop\\test.txt", newLines);
var oldLines4 = System.IO.File.ReadAllLines("c:\\users\\chris\\desktop\\test.txt");
var newLines4 = oldLines.Where(line => !line.Contains("$Recycle.Bin"));
System.IO.File.WriteAllLines("c:\\users\\chris\\desktop\\test.txt", newLines4);
var oldLines7 = System.IO.File.ReadAllLines("c:\\users\\chris\\desktop\\test.txt");
var newLines7 = oldLines.Where(line => !line.Contains("Program Files"));
System.IO.File.WriteAllLines("c:\\users\\chris\\desktop\\test.txt", newLines7);
var oldLines8 = System.IO.File.ReadAllLines("c:\\users\\chris\\desktop\\test.txt");
var newLines8 = oldLines.Where(line => !line.Contains("Program Files (x86)"));
System.IO.File.WriteAllLines("c:\\users\\chris\\desktop\\test.txt", newLines8);
var oldLines9 = System.IO.File.ReadAllLines("c:\\users\\chris\\desktop\\test.txt");
var newLines9 = oldLines.Where(line => !line.Contains("AppData"));
System.IO.File.WriteAllLines("c:\\users\\chris\\desktop\\test.txt", newLines9);
}
}
catch (System.Exception ex)
{
Console.WriteLine(ex.Message);
}
var lineCount = File.ReadLines(#"c:\\users\\chris\\desktop\\test.txt").Count();
Console.WriteLine(lineCount);
Console.ReadLine();
int element = 0;
for (int i = 0; i < lineCount + 1; i++)
{
element = element + 1;
String stringAtLinei = File.ReadLines("c:\\users\\chris\\desktop\\test.txt").ElementAtOrDefault(element);
Console.WriteLine(stringAtLinei);
}
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "random command example thing";
process.StartInfo = startInfo;
process.Start();
}
}
}
then the other namespace etc.
"stringatlinei" is not a property, or a public anything, it is defined inside a loop inside a function.
Try public static string stringatlinei="", then just assign in your loop.
Accessing that variable in another namespace is not possible. You should read up on the basics, scope in particular, to understand why this is so. Here's a helpful article: https://msdn.microsoft.com/en-us/library/aa691132(v=vs.71).aspx
Basically, your variable you are trying access is created inside your for loop. Each iteration of your loop, it goes away.
Here's the part you should change: (I removed the rest for clarity)
namespace ConsoleApplication32
{
public class Program
{
public String stringAtLinei;
static void DirSearch(string dir)
{
for (int i = 0; i < lineCount + 1; i++)
{
stringAtLinei = File.ReadLines("c:\\users\\chris\\desktop\\test.txt").ElementAtOrDefault(element);
}
}
}
}
The point is that you can access fields and properties of a class, but not variables that are confined to the method they're in. So I changed the variable to be a field in the class.

How do I populate an array with foreach?

How do I get the data I can write in the console to write to the array and the console.
At the moment it only displays on the console (not added functionality to add to array).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
namespace TBParser
{
class Program
{
static void Main(string[] args)
{
String[] arr = new String[100];
string[] lines = System.IO.File.ReadAllLines(#"C:\ShpereCompare3.txt");
Console.WriteLine("Contents of Text File: ");
foreach (string line in lines)
{
Console.WriteLine("\r\t" + line);
}
System.IO.File.WriteAllLines(#"C:\Test.txt",lines);
Console.WriteLine("Press any key to Exit");
Console.ReadKey();
}
}
}
if my lines of text say
hello
my
name
is
Simon
then the first 5 slots of the array should contain each line?
The line:
string[] lines = System.IO.File.ReadAllLines(#"C:\ShpereCompare3.txt");
is already creating an array, each element of which contains one line.
There is no need to populate a new array with this same information via a foreach.
If you want to copy the lines from the text file into another array, then you can do this:
String[] arr = new String[lines.Length];
Array.Copy(lines, arr, lines.Length);
found a work around. the path i was going down was too complicated. thanks for all your input
fixed code here
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
namespace TBParser
{
class Program
{
static void Main(string[] args)
{
string fileName = #"C:shpereCompare3.txt";
List<string> Names = new List<string>();
List<string> Value = new List<string>();
using (StreamReader fileReader = new StreamReader(fileName))
{
string fileLine;
while (!fileReader.EndOfStream)
{
fileLine = fileReader.ReadLine();
if (fileLine.StartsWith("Name"))
{
Names.Add(fileLine.Substring(21));
}
if (fileLine.StartsWith("Center"))
{
string[] fileSplit = fileLine.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
Value.Add(fileSplit[1]);
}
}
string outputString = "";
for (int i = 0;i < Names.Count; i++)
{
outputString += Names[i] + " = " + Value[i] + "\r\n";
}
System.IO.File.WriteAllText(#"C:Test.txt", outputString);
}
}
}
}

Using Stream Writer To Write a data in the text file but how to format it

Names Date Time
Sandra 11/18/2013 10.12AM
Denise 12/21/2013 10.10PM
Prnikshenth 11/11/2019 12.00AM
using System;
using System.Collections;
using System.IO;
class FunWithScheduling
{
public void AddView()
{
FileStream s = new FieStream("Scheduler.txt",FileMode.Append,FileAccess.Write);
StreamWriter w = new StreamWriter(s);
Console.WriteLine("Enter the Name of the Person To Be Met:");
string name = Console.ReadLine();
w.Write(name);
w.Flush();
w.Close();
s.Close();
}
public static void Main(string[] args)
{
FunWithScheduling a = new FunWithScheduling();
a.AddView();
}
}
I used this code to add a name but it gets stored like this
Names Date Time
Sandra 11/18/2013 10.12AM
Denise 12/21/2013 10.10PM
Prnikshenth 11/11/2019 12.00AMShawn
I added Shawn but this is how it gets stuck with the time.
You need to write to a new line before. I've also adding using statements so you don't have to call close manually.
using (StreamWriter sw = File.AppendText(#"Scheduler.txt"))
{
sw.Write(Environment.NewLine + name);
}
Try the following solution which might help
string line = name + "\t" + DateTime.Now.Date.ToString() + "\t" + DateTime.Now.Time.ToString();
w.WriteLine(line );
You might just need to check the formatting of the Date and Time respectively.

Counting number of words in a text file

I'm trying to count the number of words from a text file, namely this, to start.
This is a test of the word count program. This is only a test. If your
program works successfully, you should calculate that there are 30
words in this file.
I am using StreamReader to put everything from the file into a string, and then use the .Split method to get the number of individual words, but I keep getting the wrong value when I compile and run the program.
using System;
using System.IO;
class WordCounter
{
static void Main()
{
string inFileName = null;
Console.WriteLine("Enter the name of the file to process:");
inFileName = Console.ReadLine();
StreamReader sr = new StreamReader(inFileName);
int counter = 0;
string delim = " ,.";
string[] fields = null;
string line = null;
while(!sr.EndOfStream)
{
line = sr.ReadLine();
}
fields = line.Split(delim.ToCharArray());
for(int i = 0; i < fields.Length; i++)
{
counter++;
}
sr.Close();
Console.WriteLine("The word count is {0}", counter);
}
}
Try to use regular expression, e.g.:
int count = Regex.Matches(input, #"\b\w+\b").Count;
this should work for you:
using System;
using System.IO;
class WordCounter
{
static void Main()
{
string inFileName = null;
Console.WriteLine("Enter the name of the file to process:");
inFileName = Console.ReadLine();
StreamReader sr = new StreamReader(inFileName);
int counter = 0;
string delim = " ,."; //maybe some more delimiters like ?! and so on
string[] fields = null;
string line = null;
while(!sr.EndOfStream)
{
line = sr.ReadLine();//each time you read a line you should split it into the words
line.Trim();
fields = line.Split(delim.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
counter+=fields.Length; //and just add how many of them there is
}
sr.Close();
Console.WriteLine("The word count is {0}", counter);
}
}
A couple hints.
What if you just have the sentence "hi" what would be your output?
Your counter calculation is: from 0 through fields.Length, increment counter. How are fields.Length and your counter related?
you're probably getting a one off error, try something like this
counter = 0;
while(!sr.EndOfStream)
{
line = sr.ReadLine();
fields = line.Split(delim.ToCharArray());
counter += field.length();
}
there is no need to iterate over the array to count the elements when you can get the number directly
using System.IO;
using System;
namespace solution
{
class Program
{
static void Main(string[] args)
{
var readFile = File.ReadAllText(#"C:\test\my.txt");
var str = readFile.Split(new char[] { ' ', '\n'}, StringSplitOptions.RemoveEmptyEntries);
System.Console.WriteLine("Number of words: " + str.Length);
}
}
}
//Easy method using Linq to Count number of words in a text file
/// www.techhowdy.com
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FP_WK13
{
static class Util
{
public static IEnumerable<string> GetLines(string yourtextfile)
{
TextReader reader = new StreamReader(yourtextfile);
string result = string.Empty;
string line;
while ((line = reader.ReadLine()) != null)
{
yield return line;
}
reader.Close();
}
// Word Count
public static int GetWordCount(string str)
{
int words = 0;
string s = string.Empty;
var lines = GetLines(str);
foreach (var item in lines)
{
s = item.ToString();
words = words + s.Split(' ').Length;
}
return words;
}
}
}

Categories

Resources