Execute code from external file using Roslyn - c#

I'm using Roslyn to execute C# code at runtime.
First I tried this code (which works fine) :
engine.Execute(#"System.Console.WriteLine(""Hello World"");");
After that, I wanted to execute code from a text file, so I did this :
string line;
System.IO.StreamReader file = new System.IO.StreamReader("test.txt");
while ((line = file.ReadLine()) != null)
{
engine.Execute(line);
}
I copied the string that I used before in a external file called test.txt.
So my test.txt contains the following line : #"System.Console.Write(""Hello World"");"
When compliling the code I get an error that something is missing.
So I figured out that, it was just the backslash.
And changed the code to this :
string line;
System.IO.StreamReader file = new System.IO.StreamReader("test.txt");
while ((line = file.ReadLine()) != null)
{
string toto = line;
string titi = toto.Replace(#"\\", #"");
engine.Execute(toto);
}
Now when I run this code, nothing happens (no error).
And when I inspect the variables content, I get this :
toto : "#\"System.Console.Write(\"\"Hello World\"\");\""
titi : "#\"System.Console.Write(\"\"Hello World\"\");\""
Is that normal ! Normally the baskslash should be removed, but it not the case.
What's the problem
EDIT
I want to keep the exact string that I passe to Roslyn in code, so don't suggest answers like change the string in the file. Another solutions please !

You're misunderstanding strings.
#"..." is a string literal; it creates a string with a value of ....
Therefore, when you write Execute(#"System.Console.WriteLine(""Hello World"");"), the actual value that you pass to Execute() is System.Console.WriteLine("Hello World");
When you read a string from a file, you get the actual value of the string.
StreamReader does not assume that the file contains a C# string literal expression (that would be extremely weird, unexpected, and useless).
Therefore, when you read a file containing the text #"System.Console.WriteLine(""Hello World"");", you get a string with the actual value #"System.Console.WriteLine(""Hello World"");".
(to write this in a string literal, you would need to write #"#""System.Console.WriteLine(""""Hello World"""");"""")
When you then pass that string to Roslyn's Execute() method, Roslyn evaluates the string literal expression, and returns the string value of the literal.

Related

How to change text dynamic in unity

at line 161,I want to insert my text in parameter t,but it won't change when i debug it.although the parameter tmp had alredy changed.
I want to change this Text in UI,when my parameter t changes.
With respect to your specific issue, Insert is defined as:
public string Insert (int startIndex, string value);
and returns a new string. In C#, strings aren't modified, new strings are created. In this way, they act like a value type, even though they're a reference type. In other words, once a string is created, it is never modified - it's 'immutable'. So, you need to store your newly created string.
In cases like this, I like to use the string interpolation, as it allows me to get a slightly clearer representation of what the final string will look like.
var tmp = System.Text.Encoding.UTF8.GetString ( e.Message );
t.text = $"{tmp}\n{t.text}"; // Note that a newline is represented as \n
Or, if you add the System.Text namespace; you could reduce it down to:
using System.Text;
...
t.text = $"{Encoding.UTF8.GetString ( e.Message )}\n{t.text}";
The string type in c# is immutable, therefore Insert returns a new string instead of modifying the current one.
Do:
t = t.text.Insert(0, tmp + "//n");
See also
How to modify string contents in C#

I am stuck in a loop while processing hexadecimal data from file

I'm trying to take in a file which contains hex values to convert to binary but the file reader is not reading in the next lines and it is stuck in a loop.
Here is what the hex file looks like:
3c011001
34300000
8e080000
Below is the code I use to generate the output:
using System;
using System.IO;
class MaddinClass
{
static void Main (string[] args)
{
StreamReader sr = new StreamReader("MachineCode.txt");
string binary_from_file = sr.ReadLine();
while(!sr.EndOfStream)
{
uint binary = Convert.ToUInt32(binary_from_file, 16);
Console.WriteLine(binary);
}
}
}
I am getting a loop result like this:
1006702593
1006702593
1006702593
I expect it to move to the next line and store a new binary result, instead it just prints the same value repetitively.
With your current setup you're not really reading the file to the end. You've created your StreamReader object, and read the first line from the file. You then end up in an endless loop due to:
while (!sr.EndOfStream)
Since you're loop body doesn't read any of the information from the stream, you're continuously processing the same line from the file you stored prior to entering the loop which is why you consistently see 1006702593. If you convert that value back to hexadecimal from decimal, you'll see that it matches your first hexadecimal input of 3c011001.
uint binary = Convert.ToUInt32(binary_from_file, 16);
Per the Microsoft instruction you should be assigning each line in the condition clause of your while loop. This will allow you to process each line individually until the end of the file, where ReadLine should return null since there is nothing left to read.
This example reads the contents of a text file, one line at a time,
into a string using the ReadLine method of the StreamReader class.
Each text line is stored into the string line and displayed on the
screen.
I would also like to point out that the line above isn't converting to binary, but rather an unsigned integer (hence your value of 1006702593 instead of 111100000000010001000000000001); you'll need to convert the result of that to string with base 2 representation, and unless you have a valid reason to use unsigned integers, I would used signed integers instead:
string binary = Convert.ToString(Convert.ToInt32(binary_from_file, 16), 2);
Below is a refactored copy paste from the link above to meet your needs:
string line;
using (StreamReader file = new StreamReader(#"c:\test.txt"))
while((line = file.ReadLine()) != null)
Console.WriteLine(Convert.ToString(Convert.ToInt32(line, 16), 2));
Console.ReadLine();
In a nutshell, the code above follows the execution path below:
Create the variable for storing each line.
Create a new StreamReader object pointed at your file.
Read each line from the file.
Print that line in a binary representation.
Close the stream.
Dispose of the stream.
Suspend the Console to prevent it from closing automatically.

Using .Except without case sensitivity C#

I am working on a project with reads in 2 csv files:
var myFullCsv = ReadFile(myFullCsvFilePath);
var masterCsv = ReadFile(csvFilePath);
and then creates a new var containing the extra lines that exist in myFullCsv but not master Csv. The code is great because of its simplicity:
var extraFilesCsv = myFullCsv.Except(masterCsv);
The csv files read in contain data like this:
c01.jpg,95182,24f77a1e,\Folder1\FolderA\,
c02.jpg,131088,c17b1f13,\Folder1\FolderA\,
c03.jpg,129485,ddc964ec,\Folder1\FolderA\,
c04.jpg,100999,930ee633,\Folder1\FolderA\,
c05.jpg,101638,b89f1f28,\Folder1\FolderA\,
However, I have just found a situation where the case of some characters in each file does not match. For example (JPG in caps):
c01.JPG,95182,24f77a1e,\Folder1\FolderA\,
If the data is like this then it is not included in extraFilesCsv but I need it to be. Can anybody tell me how I can make this code insensitive to the case of the text?
Edit: Sorry, I forgot that ReadFile was not a standard command. Here is the code:
public static IEnumerable<string> ReadFile(string path)
{
string line;
using (var reader = File.OpenText(path))
while ((line = reader.ReadLine()) != null)
yield return line;
}
I'm assuming you've read in both csv files and have a collection of strings representing each file.
You can specify a specific EqualityComparer in the call to Except(), which instructs on the type of comparison to do between two collections of objects.
You can create your own comparer or, assuming both collections are of strings, try specifying an existing one that ignores case:
var extraFilesCsv
= myFullCsv.Except(masterCsv, StringComparer.CurrentCultureIgnoreCase);
By default, if you don't specify a comparer, it uses EqualityComparer<TElement>.Default, which differs based on the class type you're comparing.
For strings, it first does a straight-up a==b comparison by default, which is case-sensitive. (The exact implementation on the string class is a little more complicated, but it's probably unnecessary to post it here.)

C# String compare not working

I'm having some issues with the string comparison of a string the is received by Request.queryString and a line from a file .resx.
The code receive Request.queryString to a variable named q, then it goes to a function to compare if a line has q value in it:
while ((line = filehtml.ReadLine()) != null)
{
if (line.ToLower().Contains(q.ToLower().ToString()))
HttpContext.Current.Response.Write("<b>Content found!</b>");
else
HttpContext.Current.Response.Write("<b>Content not found!</b>");
}
As it's a search in static files, special characters must be consider and seraching for: Iberê for example, isn't returning true because the .Contains, .IndexOf or .LastindexOf is comparing: iberê, that is coming from q, with iberê that is coming from the line.
Consider that I already tried to use ResXResourceReader (which can't be found by Visual Studio), ResourceReader and ResourceManager (these I couldn't set a static file by the path to be read).
EDIT:
Problem solved. There was a instance of SpecialChars, overwriting q value with EntitiesEncode method
The problem is that the ê character is escaped in both strings. So if you did something like this, it wouldn't work:
string line = "sample iberê text";
string q = "iberê";
if (line.Contains(q)) {
// do something
}
You need to unscape the strings. Use HttpUtility in the System.Web assembly. This will work:
line = System.Web.HttpUtility.HtmlDecode(line);
q = System.Web.HttpUtility.HtmlDecode(q);
if (line.Contains(q)) {
// do something
}
As suggested by #r3bel below, if you're using .net 4 or above you can also use System.Net.WebUtility.HtmlDecode, so you don't need an extra assembly reference.

Read file into byte array is different to string

I have a file in visual studio with the following contents:"{"Name":"Pete"}"
If I read the file with the following code it appears to create a string with the original value:
byte[] byteArray = System.IO.File.ReadAllBytes(filePath);
string jsonResponse = System.Text.Encoding.UTF8.GetString(byteArray);
However, the string is actually different to the version that exists if I use the following code:
string jsonResponse = "{\"Name\":\"Pete\"}";
Why? (The reason I think it is different is because when I pass each version to a json deserializer it behaves differently)
Thanks.
Given your final comment in the question, I suspect the problem is that you've got a byte-order mark at the start of the file. Try loading the file like this instead:
string jsonResponse = File.ReadAllText(filePath);
I believe that will strip the BOM for you. Alternatively, you could try explicitly trimming it yourself:
jsonResponse = jsonResponse.TrimStart('\feff');
My guess would be that you have a terminating newline in your file.
You can easily verify if two strings have the same content in C# by just comparing them with a == b.
Here's a short code sample that might help you identify the problem. The strings are output surrounded by < >, which should help you identify surrounding whitespace (which, by the way, can be removed using String.Trim).
byte[] byteArray = System.IO.File.ReadAllBytes(filePath);
string fromFile = System.Text.Encoding.UTF8.GetString(byteArray);
string fromString = "{\"Name\":\"Pete\"}";
if (fromFile == fromString) {
Console.WriteLine("Strings are the same.");
} else {
Console.WriteLine("Strings are different!");
Console.WriteLine("fromFile: <" + fromFile + ">");
Console.WriteLine("fromString: <" + fromString + ">");
}

Categories