I have a problem. I have to save figures to txt ( its not important what it means). I would like to have space between numbers.
When I try to save it without spaces it works good
This is my code without space
if (x_dolny > x1_sqr && x_dolny < x2_sqr)
{
using (StreamWriter streamW = new StreamWriter("C:\\Users\\Desktop\\outputdata.txt", true))
{
streamW.Write("1");
}
}
else if (y_prawy < y1_sqr && y_prawy > y2_sqr)
{
using (StreamWriter streamW = new StreamWriter("C:\\Users\\Desktop\\outputdata.txt", true))
{
streamW.Write("1");
}
}
else if (delta >= 0.0)
{
using (StreamWriter streamW = new StreamWriter("C:\\Users\\Desktop\\outputdata.txt", true))
{
streamW.Write("2");
}
}
else
{
using (StreamWriter streamW = new StreamWriter("C:\\Users\\Desktop\\outputdata.txt", true))
{
streamW.Write("0");
}
}
using (StreamWriter streamW = new StreamWriter("C:\\Users\\Desktop\\outputdata.txt", true))
{
streamW.WriteLine("New line");
}
And here is a screenshot outputdata.txt
and then I tried to add "\t"
So now I have
streamW.Write("1 \t");
streamW.Write("2 \t");
streamW.Write("0 \t");
but the file looks like this
I dont understand why it cuts my line and move to the next line...
Any ideas?
As #Sinatr mentioned in the comments, this could just be a word-wrap issue in your text editor.
Off topic though, this code could really use some refactoring to make it simpler and much easier to read and understand.
using (var streamWriter = new StreamWriter(#"C:\Users\Desktop\outputdata.txt", true))
{
string message = "0";
if (MessageIs1(x_dolny, x1_sqr, x2_sqr, y_prawy, y1_sqr, y2_sqr))
message = "1";
else if (delta >= 0.0)
message = "2";
streamWriter.Write(message);
streamWriter.WriteLine("New line");
}
// ...
private static bool MessageIs1(int x_dolny, int x1_sqr, int x2_sqr,
int y_prawy, int y1_sqr, int y2_sqr)
{
return (x_dolny > x1_sqr && x_dolny < x2_sqr)
|| (y_prawy < y1_sqr && y_prawy > y2_sqr);
}
Here's some suggestions:
You reused the StreamWriter in every branch of your if statements and even after. Instead of typing the using statements several times, wrap it all in one using statement. Try to follow the DRY principle (Don't Repeat Yourself).
You can use var when the data type is obvious from the assignment (such as creating new objects).
Try to make your identifiers (variable names and method names) as clear and concise as possible. Others reading your code shouldn't have to look around a lot to figure out what your variables or methods are doing; it should be obvious just from the name. Avoid abbreviations because others may not know what the abbreviation stands for or may assume it means something else. I didn't know what your variables were for because I couldn't look at the full source, but I would definitely rename the following from my example above: x_dolny, x1_sqr, x2_sqr, y_prawy, y1_sqr, y2_sqr, MessageIs1.
Extract complex boolean logic into a method so it is easier to read and change if you or someone else needs to later.
Use verbatim string literals for file paths.
Try to adhere to the KISS Principle (Keep It Simple, Stupid) as much as possible. Most developers over-engineer. Simple code is easy to read, understand, maintain, and extend.
Related
I decided to get into coding and am learning c#, after making a few small projects, I decided to step it up a little and make a text adventure game, with saving and loading, and if I get to feeling zany I'll try to add some multiplayer. While I haven't really hit a road block because of it, I can't help but feel that I am doing load function REALLY sub-optimally. The save is fine, I feel like it works for me, but the load I feel can be really simplified, I just don't know what to use.
I also wouldn't really mind, but with this way, if I add other attributes/skills or whatever else that needs to be saved, I will have to add everything to the load function as well, and it will be even longer.
I have tried to search around on here, the c# documentation, and other sites, but can't find a solution that works for this case. can anyone help me find a better way of doing this? Or is this the best I can really do since it's varying data types?
Edit: To simplify and clarify what answer I am searching for, I am trying to find a simpler and more scalable way to save and load the data to a file.
static void LoadGame(CharData PlayerData)
{
Console.WriteLine("Enter the name of the character to load as shown below.");
//getting current directory info, setting to di
DirectoryInfo di = new DirectoryInfo(Directory.GetCurrentDirectory());
//need to initialize these outside of a loop
int SaveFiles = 0;
string DisplayName = " ";
int DisplayNameLength = 0;
//looks through files in working directory ending in '.fasv', displays them in format '{x}. John Smith'
foreach (var fi in di.GetFiles("*.fasv"))
{
SaveFiles++;
DisplayNameLength = fi.Name.Length;
//remove .fasv from displayed name to make it look nicer
DisplayName = fi.Name.Remove(DisplayNameLength - 5, 5);
Console.WriteLine(SaveFiles.ToString() + ". " + DisplayName);
}
string toLoad = Console.ReadLine();
using StreamReader sr = new StreamReader(toLoad + ".fasv");
//the name is easy to get since it's a string. but integers...
PlayerData.Name = sr.ReadLine();
//... not so much. i hate all of this and i feel like it's gross, but i don't know how else to do it
int hp, xp, level, toughness, innovation, mind, empathy, spryness;
Int32.TryParse(sr.ReadLine(), out hp);
Int32.TryParse(sr.ReadLine(), out xp);
Int32.TryParse(sr.ReadLine(), out level);
Int32.TryParse(sr.ReadLine(), out toughness);
Int32.TryParse(sr.ReadLine(), out innovation);
Int32.TryParse(sr.ReadLine(), out mind);
Int32.TryParse(sr.ReadLine(), out empathy);
Int32.TryParse(sr.ReadLine(), out spryness);
PlayerData.Health = hp;
PlayerData.Level = level;
PlayerData.XP = xp;
PlayerData.Toughness = toughness;
PlayerData.Innovation = innovation;
PlayerData.Mind = mind;
PlayerData.Empathy = empathy;
PlayerData.Spryness = spryness;
sr.Close();
InGame(PlayerData);
}
static void SaveGame(CharData PlayerData)
{
using (StreamWriter sw = new StreamWriter(PlayerData.Name + ".fasv"))
{
foreach (System.Reflection.PropertyInfo stat in PlayerData.GetType().GetProperties())
{
//write player data properties to file line by line, using stat to iterate through the player data properties
sw.WriteLine(stat.GetValue(PlayerData));
}
sw.Close();
}
}
If you aren't set on a particular data format for the file data, I would recommend using a serializer such as JSON.NET. You can use NuGet to add newtonsoft.json to your project, and that would allow you to just do something similar to:
using (StreamWriter file = File.CreateText(pathToPlayerFile))
{
var serializer = new JsonSerializer();
serializer.Serialize(file, playerData);
}
And then your code to read from the file would be pretty similar:
using (var file = File.OpenText(pathToPlayerFile))
{
var serializer = new JsonSerializer();
return (CharData)serializer.Deserialize(file, typeof(CharData));
}
I borrowed those code snippets from newtonsoft.com. CreateText will create (or overwrite) the file and write the object as a JSON object.
So this is how a portion of the XML I am trying to parse looks like:
<azsa:Views>
<azsa:Spatial_Array>
<azsa:Spatial>
<azsa:ViewName>Spatial</azsa:ViewName>
<azsa:BBox>
<azsa:PointLo>
<azsa:x>0</azsa:x>
<azsa:y>0</azsa:y>
<azsa:z>0</azsa:z>
</azsa:PointLo>
<azsa:PointHi>
<azsa:x>2925</azsa:x>
<azsa:y>3375</azsa:y>
<azsa:z>2775</azsa:z>
</azsa:PointHi>
</azsa:BBox>
</azsa:Spatial>
</azsa:Spatial_Array>
</azsa:Views>
I have to read the x,y and z coordinates for both PointHi and PointLo
I was using the XMLReader() class to perform the task.
XmlTextReader reader = new XmlTextReader(openFileDialog1.FileName);
while (reader.Read())
{
reader.ReadToFollowing("azsa:Views");
reader.ReadToFollowing("azsa:Spatial_Array");
reader.ReadToFollowing("azsa:Spatial");
reader.ReadToFollowing("azsa:ViewName");
reader.ReadToFollowing("azsa:BBox");
reader.ReadToFollowing("azsa:PointLo");
reader.ReadToFollowing("azsa:x");
low[0] = (int)(Double.Parse(reader.ReadElementString()));
reader.ReadToFollowing("azsa:y");
low[1] = (int)(Double.Parse(reader.ReadElementString()));
reader.ReadToFollowing("azsa:z");
low[2] = (int)(Double.Parse(reader.ReadElementString()));
reader.ReadToFollowing("azsa:PointHi");
reader.ReadToFollowing("azsa:x");
high[0] = (int)(Double.Parse(reader.ReadElementString()));
reader.ReadToFollowing("azsa:y");
high[1] = (int)(Double.Parse(reader.ReadElementString()));
reader.ReadToFollowing("azsa:z");
high[2] = (int)(Double.Parse(reader.ReadElementString()));
}
The reader works perfectly until it gets to the first x in the PointLo and then it just skips to the y in PointHi instead. I have tried using descendants, subtrees and readinnerxml but it still does the same thing.
NOTE: 1. There is more code in the while loop for reading the remaining part of the XML but was not necessary for this problem so I have not included it in the post.
2. Changing the way the XML is organized is not possible because that's how they are required to be stored for the task I am performing.
3. XMLReader is the preferable method as I am dealing with a large number of documents and there is no scope for having this use cache memory.
I had a fairly similar issue a while back when reading subtrees. The solution in that scenario was to dispose the subtree XmlReaders. Granted, the situation here is slightly different, but could you consider an approach such as below (note that I removed the element prefixes for simplicity of testing, as well as read in the XML string rather than a file)?
It is certainly ugly looking, but this was more a proof of concept and could be tidied up a bit. It is also lacking the appropriate error checking, but again this was more for demonstration purposes. It does at least parse out the different point values.
As a side note, I think perhaps a lot of the ugliness could be abstracted away by making classes to represent the different components (or objects) within the XML stream, and making those classes responsible for parsing out their own properties.
Just one way (of many I'm sure) to skin a cat...
private void ParseXml(string xml)
{
double[] low = null;
double[] hi = null;
using (StringReader stringReader = new StringReader(xml))
{
using (XmlReader xmlReader = XmlReader.Create(stringReader))
{
while (xmlReader.Read())
{
if (xmlReader.NodeType != XmlNodeType.Element) continue;
if (xmlReader.Name == "PointLo")
{
low = ParsePoint(xmlReader);
}
else if (xmlReader.Name == "PointHi")
{
hi = ParsePoint(xmlReader);
}
}
}
}
}
private double[] ParsePoint(XmlReader xmlReader)
{
double[] point = new double[3];
using (XmlReader pointReader = xmlReader.ReadSubtree())
{
while (pointReader.Read())
{
if (pointReader.NodeType != XmlNodeType.Element) continue;
if (pointReader.Name == "x")
{
point[0] = GetDimensionValue(pointReader);
}
else if (pointReader.Name == "y")
{
point[1] = GetDimensionValue(pointReader);
}
else if (pointReader.Name == "z")
{
point[2] = GetDimensionValue(pointReader);
}
}
}
return point;
}
private double GetDimensionValue(XmlReader reader)
{
using (XmlReader dimensionReader = reader.ReadSubtree())
{
dimensionReader.Read();
return reader.ReadElementContentAsDouble();
}
}
So as I mentioned in the comments to manderson's solution that for some reason it does not see the y element as an element and instead sees it as a text element, I made the following changes to the while loop in ParsePoint()
while (pointReader.Read())
{
if (pointReader.NodeType == XmlNodeType.Element || pointReader.NodeType== XmlNodeType.Text)
{
if (pointReader.Name == "azsa:x")
{
point[0] = pointReader.ReadElementContentAsDouble();
}
else if (pointReader.Name == "")
{
point[1] = Double.Parse(pointReader.Value);
}
else if (pointReader.Name == "azsa:z")
{
point[2] = pointReader.ReadElementContentAsDouble();
}
}
}
While I am not claiming that this is the ideal way to do this, it works for the XML files I am dealing with. I also removed the GetDimensionValue method and just do the reading of the values/element contents in this method itself.
i'm having trouble searching a virtual listview in c#.
what i am doing right now is reading a large log file. here is what i have implemented so far
I read the file one line at a time and note the position of the start of the line. Add these positions to a List and when RetrieveVirtualItem is called - look up the position in the file using the index of the item and the List and then read the line from file.
So there is no lag when reading the file.
I want to now search for items. Here is what I have thought of so far, but I have not been able to implement it successfully.
I am not actually searching the listview, but during my filereading, i mark the position of hits of the specific string, say "INFO". if it hits, i add the position to a List.
When RetrieveVirtualItem is called, I just read the line back with all the hits.
Seems that through debugging - if (line.IndexOf("INFO", StringComparison.OrdinalIgnoreCase) >= 0) is not hitting any matches. I'm not sure why, anyone help?
using (var sr = new myStreamReader("test.log"))
{
while ((line = sr.ReadLine()) != null)
{
if (line.IndexOf("INFO", StringComparison.OrdinalIgnoreCase) >= 0)
{
position = sr.BytesRead;
Search.Add(position);
searchcount++;
}
}
newMessageView.VirtualListSize = searchcount;
}
I don't know how your "myScreamReader" class works, but if it similar to StreamReader this code could be working for you:
using (var sr = new StreamReader("test.log"))
{
while (!sr.EndOfStream)
{
string line = sr.ReadLine();
if (line.IndexOf("INFO", StringComparison.OrdinalIgnoreCase) >= 0)
{
// line contains "info"
}
}
}
You should debug your code by setting a breakpoint at line.IndexOf... check to see if value of line is changing and look correct.
This is what my team and I chose to do for our school project. Well, actually we haven't decided on how to parse the C# source files yet.
What we are aiming to achieve is, perform a full analysis on a C# source file, and produce up a report.
In which the report is going to contain stuff that happening in the codes.
The report only has to contain:
string literals
method names
variable names
field names
etc
I'm in charge of looking into this Irony library. To be honest, I don't know the best way to sort the data out into a clean readable report. I am using the C# grammar class packed with the zip.
Is there any step where I can properly identify each node children? (eg: using directives, namespace declaration, class declaration etc, method body)
Any help or advice would be very much appreciated. Thanks.
EDIT: Sorry I forgot to say we need to analysis the method calls too.
Your main goal is to master the basics of formal languages. A good start-up might be found here. This article describes the way to use Irony on the sample of a grammar of a simple numeric calculator.
Suppose you want to parse a certain file containing C# code the path to which you know:
private void ParseForLongMethods(string path)
{
_parser = new Parser(new CSharpGrammar());
if (_parser == null || !_parser.Language.CanParse()) return;
_parseTree = null;
GC.Collect(); //to avoid disruption of perf times with occasional collections
_parser.Context.SetOption(ParseOptions.TraceParser, true);
try
{
string contents = File.ReadAllText(path);
_parser.Parse(contents);//, "<source>");
}
catch (Exception ex)
{
}
finally
{
_parseTree = _parser.Context.CurrentParseTree;
TraverseParseTree();
}
}
And here is the traversal method itself with counting some info in the nodes. Actually this code counts the number of statements in every method of the class. If you have any question you are always welcome to ask me
private void TraverseParseTree()
{
if (_parseTree == null) return;
ParseNodeRec(_parseTree.Root);
}
private void ParseNodeRec(ParseTreeNode node)
{
if (node == null) return;
string functionName = "";
if (node.ToString().CompareTo("class_declaration") == 0)
{
ParseTreeNode tmpNode = node.ChildNodes[2];
currentClass = tmpNode.AstNode.ToString();
}
if (node.ToString().CompareTo("method_declaration") == 0)
{
foreach (var child in node.ChildNodes)
{
if (child.ToString().CompareTo("qual_name_with_targs") == 0)
{
ParseTreeNode tmpNode = child.ChildNodes[0];
while (tmpNode.ChildNodes.Count != 0)
{ tmpNode = tmpNode.ChildNodes[0]; }
functionName = tmpNode.AstNode.ToString();
}
if (child.ToString().CompareTo("method_body") == 0) //method_declaration
{
int statementsCount = FindStatements(child);
//Register bad smell
if (statementsCount>(((LongMethodsOptions)this.Options).MaxMethodLength))
{
//function.StartPoint.Line
int functionLine = GetLine(functionName);
foundSmells.Add(new BadSmellRegistry(name, functionLine,currentFile,currentProject,currentSolution,false));
}
}
}
}
foreach (var child in node.ChildNodes)
{ ParseNodeRec(child); }
}
I'm not sure this is what you need but you could use the CodeDom and CodeDom.Compiler namespaces to compile the C# code, and than analyze the results using Reflection, something like:
// Create assamblly in Memory
CodeSnippetCompileUnit code = new CodeSnippetCompileUnit(classCode);
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerResults results = provider.CompileAssemblyFromDom(compileParams, code);
foreach(var type in results.CompiledAssembly)
{
// Your analysis go here
}
Update: In VS2015 you could use the new C# compiler (AKA Roslyn) to do the same, for example:
var root = (CompilationUnitSyntax)tree.GetRoot();
var compilation = CSharpCompilation.Create("HelloTDN")
.AddReferences(references: new[] { MetadataReference.CreateFromAssembly(typeof(object).Assembly) })
.AddSyntaxTrees(tree);
var model = compilation.GetSemanticModel(tree);
var nameInfo = model.GetSymbolInfo(root.Usings[0].Name);
var systemSymbol = (INamespaceSymbol)nameInfo.Symbol;
foreach (var ns in systemSymbol.GetNamespaceMembers())
{
Console.WriteLine(ns.Name);
}
This thread is a continuation of Is there a reason to check for null inside multiple using clausule in c#?
I've noticed that resharper lets me define using without opening any opening/closing bracket like in the method below (but then i can't use defined vars later on if the brackets ain't there, other then the one that is used exactly beneath defined using):
public static string sqlGetDatabaseRows() {
string varRows = "";
const string preparedCommand = #"
SELECT SUM(row_count) AS 'Rows'
FROM sys.dm_db_partition_stats
WHERE index_id IN (0,1)
AND OBJECTPROPERTY([object_id], 'IsMsShipped') = 0;";
using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetailsDZP))
using (var sqlQuery = new SqlCommand(preparedCommand, varConnection))
using (var sqlQueryResult = sqlQuery.ExecuteReader())
if (sqlQueryResult != null) {
while (sqlQueryResult.Read()) {
varRows = sqlQueryResult["Rows"].ToString();
}
sqlQueryResult.Close();
}
return varRows;
}
Is it good? Or should i use it like this?
public static string sqlGetDatabaseRows() {
string varRows = "";
const string preparedCommand = #"
SELECT SUM(row_count) AS 'Rows'
FROM sys.dm_db_partition_stats
WHERE index_id IN (0,1)
AND OBJECTPROPERTY([object_id], 'IsMsShipped') = 0;";
using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetailsDZP)) {
using (var sqlQuery = new SqlCommand(preparedCommand, varConnection))
using (var sqlQueryResult = sqlQuery.ExecuteReader())
if (sqlQueryResult != null) {
while (sqlQueryResult.Read()) {
varRows = sqlQueryResult["Rows"].ToString();
}
sqlQueryResult.Close();
}
varConnection.Close();
}
return varRows;
}
sqlConnectOneTime looks like this:
public static SqlConnection sqlConnectOneTime(string varSqlConnectionDetails) {
SqlConnection sqlConnection = new SqlConnection(varSqlConnectionDetails);
sqlConnect(sqlConnection);
if (sqlConnection.State == ConnectionState.Open) {
return sqlConnection;
}
return null;
}
My questions are:
Should I be closing varConnection by using varConnection.Close() and sqlQueryResult.Close(); in the end? (but this enforces use of brackets) or will the connection close itself when using is done.
Should i be checking for NULL for varConnection since it's possible it will return null (on the other hand resharper doesn't complain here).
Is there some better approach i could use for defining sqlConnectOneTime ? Like when the connection fails to open it should return ConnectionState.Closed instead of null?
Also just on a note i open up new connection every time i execute new query / update / insert since i am using threading and it was the smartest idea i could come up at that very moment. Feel free to suggest better one :-)
I am asking about all this since i want to better understand whole process and stop making silly mistakes so be gentle with me.
MadBoy
Edit: modified question if varConnection.Close() and sqlQueryResult.Close() are nessecary if using is used.
Close() is called by the Dispose() method, so as long as you are using "using" properly you don't need to call Close() explicitly.
If it's possible for a NULL to be returned, you should check for it. I would advise that if you control the code that gets the sql connection, you strongly consider throwing an exception rather than returning NULL. Otherwise other developers may run into the same sorts of problems. Failure to open a SQL connection that is required seems to me to be a valid exceptional case. If necessary, you can always include a TryConnectOneTime for when a developer wants to avoid exception handling.
Also, another style note - I would advise properly bracing your using statements in case a stray extra line is added and an unexpected error occurs. Style-wise, I usually don't tend to indent using statements when I have multiple statements together, but that's all down to personal preference.
It's safe to use it like in the first example. using closes the reader, command and connection objects and even checks for null values (so you don't get a NullReferenceException if varConnection is null)