Whenever I run this code, it returns one character. I've tried various things, and at most it returns 5 or so lines, each containing one character. I'm trying to find each folder in the "Users" folder, and make my code list them, any help would be appreciated.
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
//Search for directories and foreach, try to start discord
try
{
var Bruhm = new List<string>();
Bruhm.Add(Directory.GetDirectories(#"C:\Users\").ToString());
int y = 0;
foreach (string x in Bruhm) {
Console.WriteLine(x[y]);
y = y+1;
}
}
catch(Exception e)
{
Console.WriteLine(e);
System.Threading.Thread.Sleep(-1);
}
System.Threading.Thread.Sleep(-1);
}
}
}
The first mistake you are making is;
Bruhm.Add(Directory.GetDirectories(#"C:\Users\").ToString());
will add only one string, which is System.String[] to your list.
The second mistake is, x[y] will print only one character, which is the character at y index inside the string x.
Change the Add() to AddRange(), and do not call ToString() on your list.
Try this:
var Bruhm = new List<string>();
Bruhm.AddRange(Directory.GetDirectories(#"C:\Users\"));
foreach (string x in Bruhm)
{
Console.WriteLine(x);
}
It's quite simple. You're doing error with this: Directory.GetDirectories(#"C:\Users\").ToString()
Instead try this:
var Bruhm = Directory.GetDirectories(#"C:\Users\");
foreach(var subdir in Bruhm)
Console.WriteLine(subDir);
You are converting a list into a string and printing an index of it and it makes wrong result. You can extract the folder name using this code. "C:\Users\" has removed from the folder's path to provide folders' name not path.
var path = #"C:\Users\";
var Bruhm = Directory.GetDirectories(path).Select(x => x.Substring(path.Length));
foreach (string x in Bruhm)
{
Console.WriteLine(x);
}
Related
I have a list(in txt file) that looks like this field:description
field20D.name = Reference
field20[101].name = Sender's Reference
field20[102].name = File Reference
field20[102_STP].name = File Reference
field20[103].name = Sender's Reference
The numbers in [] like 101,102 are messagetype.
How can i write the code so when i have a property with any value in that list, to get the equivalent description for it.
example: when a field has a value "20D" to build a string "20D - Reference"
Here's a good class that can do what you stated above.
using System;
using System.Collections.Generic;
namespace TestConsoleProject
{
public class WeirdLineFormatReader
{
public IEnumerable<Tuple<string, string>> ReadLines(IEnumerable<string> lines)
{
foreach (string line in lines)
{
// split each line on the =
string[] strLineArray = line.Split('=');
// get the first and second values of the split line
string field = strLineArray[0];
string value = strLineArray[1];
// remove the first field word
field = field.Substring("field".Length);
// remove the .name portion
field = field.Replace(".name", "");
// remove the surrounding white-space
field = field.Trim();
// remove all white space before/after the description
value = value.Trim();
yield return new Tuple<string, string>(field, value);
}
}
}
}
Here's a quick console project that will use the class to output your format to the console the way you want.
using System;
using System.IO;
namespace TestConsoleProject
{
class Program
{
static void Main(string[] args)
{
var lines = File.ReadLines(args[0]);
var reader = new WeirdLineFormatReader();
var tuples = reader.ReadLines(lines);
foreach (var tuple in tuples)
Console.WriteLine("{0} - {1}", tuple.Item1, tuple.Item2);
Console.ReadKey();
}
}
}
Just for the fun of it and also because I suspect you are only showing us a couple of the lines in a much larger text file; here's a format for unit testing when you find that you need to add more code to the ReadLines(string[]) method later.
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Linq;
using TestConsoleProject;
namespace UnitTestProject
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestFormatter_WithoutBrackets()
{
// Arrange
var reader = new WeirdLineFormatReader();
string[] lines = {
"field20D.name = Reference"
};
// Act
var tuples = reader.ReadLines(lines).ToList();
// Assert
Assert.AreEqual(tuples[0].Item1, "20D", "Field 20D did not format correctly, Actual:" + tuples[0].Item1);
Assert.AreEqual(tuples[0].Item2, "Reference", "Field 20D's description did not format correctly, Actual:" + tuples[0].Item2);
}
[TestMethod]
public void TestFormatter_WithBrackets()
{
// Arrange
var reader = new WeirdLineFormatReader();
string[] lines = {
"field20[103].name = Sender's Reference"
};
// Act
var tuples = reader.ReadLines(lines).ToList();
// Assert
Assert.AreEqual(tuples[0].Item1, "20[103]", "Field 20[103] did not format correctly, Actual:" + tuples[0].Item1);
Assert.AreEqual(tuples[0].Item2, "Sender's Reference", "Field 20[103]'s description did not format correctly, Actual:" + tuples[0].Item2);
}
}
}
Using this unit test project you can quickly write new tests for edge cases that you discover. After you modify the ReadLines() method, you can re-run all the unit tests to see if you broke any of the older tests.
Pseudo:
create a dictionary of key value pairs
split on carriage return
split on equals sign (can there be an equals sign in the value?)
regex the first half to get everything between 'field' and '.name', put that in the key
put the split from after the equals sign in the value
now you can reference your dictionary by key:
entry = myDictionary["20D"];
return $"{entry.Key} - {entry.value}";
In C#,
I want directory names list.
Type is List and I have full pah list(List fullPathList).
fullpathList is like this..
[0] C:\temp\image\a.jpg;
[1] C:\temp\image\b.bmp;
[2] c:\temp\bin\my.exe;
[3] c:\temp\document\resume.doc;
[4] c:\temp\document\timetable.xlsx;
In this case,
I want it.
List<string> dirs;
[0] iamge
[1] bin
[2] document
I guess possible if i using Regx.
But, i dont know detailed method.
how can I do for it?
(dont use loop statement)
I believe this prints what you want...
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
namespace Test {
class Program {
static void Main(string[] args) {
var files = new string[] {
#"C:\temp\image\a.jpg",
#"C:\temp\image\b.bmp",
#"c:\temp\bin\my.exe",
#"c:\temp\document\resume.doc",
#"c:\temp\document\timetable.xlsx",
};
var dirNames = files.Select(x => new DirectoryInfo(Path.GetDirectoryName(x)).Name);
Debug.WriteLine($"dirNames={string.Join(",", dirNames)}");
}
}
}
The Path.GetDirectoryName() returns the full path and new DirectoryInfo().Name returns just the name of the last part of the path.
If you want the result in a list, use...
var dirNames = files.Select(x => new DirectoryInfo(Path.GetDirectoryName(x)).Name).ToList();
Check if this solution Works.
it gets all the directory in the specified drive.
Please go through the reference link ref link
List<string> dir = new List<string>();
System.IO.DriveInfo di = new System.IO.DriveInfo(#"D:\");
System.IO.DirectoryInfo dirInfo = di.RootDirectory;
System.IO.DirectoryInfo[] dirInfos = dirInfo.GetDirectories("*.*");
foreach (System.IO.DirectoryInfo d in dirInfos)
{
dir.Add(d.Name);
}
For a real filesystem DirectoryInfo is the way to go.
If you do not have a real filesystem to query, but have a list of strings that are like paths you can use System.IO.Path - Static methods to split them up like this:
using System;
using System.Linq;
using System.IO;
public class Program
{
public static void Main()
{
// some strings that are like paths
var dirs = new[]
{
#"C:\temp\image\a.jpg", #"C:\temp\image\b.bmp", #"c:\temp\bin\my.exe",
#"c:\temp\document\resume.doc", #"c:\temp\document\timetable.xlsx"
};
// this will use a static method to extract only the path-part
var fullDirs = dirs.Select(d => Path.GetDirectoryName(d)).ToList();
// this will use the same method but split the result at the default systems
// path-seperator char and use only the last part, only uses distinct values
var lastDirsDistinct = dirs.Select(d => Path.GetDirectoryName(d)
.Split(Path.DirectorySeparatorChar).Last()
).Distinct().ToList();
// joins the list with linebreaks and outputs it
Console.WriteLine(string.Join("\n", fullDirs));
// joins the list with linebreaks and outputs it
Console.WriteLine(string.Join("\n", lastDirsDistinct ));
}
}
Output:
C:\temp\image
C:\temp\image
c:\temp\bin
c:\temp\document
c:\temp\document
image
bin
document
I'm new to Roslyn. I'm writing a code fix provider that transforms foreach blocks that iterate through the results of a Select, e.g.
foreach (var item in new int[0].Select(i => i.ToString()))
{
...
}
to
foreach (int i in new int[0])
{
var item = i.ToString();
...
}
To do this, I need to insert a statement at the beginning of the BlockSyntax inside the ForEachStatementSyntax that represents the foreach block. Here is my code for that:
var blockStatement = forEach.Statement as BlockSyntax;
if (blockStatement == null)
{
return document;
}
forEach = forEach.WithStatement(
blockStatment.WithStatements(
blockStatement.Statements.Insert(0, selectorStatement));
Unfortunately, doing that results in the whitespace being off:
foreach (int i in new int[0])
{
var item = i.ToString();
...
}
I Googled solutions for this. I came across this answer, which recommended using either Formatter.Format or SyntaxNode.NormalizeWhitespace.
I can't use Formatter.Format because that takes a Workspace parameter, and it looks I don't have access to a Workspace per Roslyn: Current Workspace in Diagnostic with code fix project.
I tried using NormalizeWhitespace() on the syntax root of the document, but that invasively formatted other code not related to the fix. I tried using it on just the ForEachStatementSyntax associated with the foreach block, and then calling syntaxRoot = syntaxRoot.ReplaceNode(oldForEach, newForEach), but that results in the entire foreach block not being properly indented.
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var array = new int[0];
int length = array.Length;
foreach (int i in array)
{
string item = i.ToString();
} }
}
}
So is it possible to simply insert the statement with the correct indentation in the first place, without having to format other code?
Thanks.
You can add the Formatter Annotation to the nodes that you want the formatter to run on using WithAdditionalAnnotations
blockStatement.Statements.Insert(0, selectorStatement.WithAdditionalAnnotations(Formatter.Annotation))
I am currently working on a project that involves taking a text file with information in it and storing the values into an array for use in determining if a certain book should be "split" based on its ID.
I have declared a string array in the class that is executing the method for this task, and assigning the values from the text file using a StreamReader.
Here is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.Odbc;
using System.Data.OleDb;
using System.IO;
namespace ElectionsPollBooks
{
class dbElections
{
//arrays, ints, for pollbook splits
string[] as_splitNumbers;
int i_splitCount;
public void Process()
{
//opens conenction
OpenConn();
//Gets the precinct info for later parsing
GetDistrictInfo();
//populate splits array
PopulateSplits();
//the hard work
SeperateDataSet();
CloseConn();
}
//...other methods in here, not related
private void PopulateSplits()
{
//sets the count
i_splitCount = 0;
//reads the split file
StreamReader sr_splits = new StreamReader(#"a\file\path\here\.txt");
//begin populating the array
while (sr_splits.ReadLine() != null)
{
//split ID
as_splitNumbers[i_splitCount] = sr_splits.ReadLine();
i_splitCount = i_splitCount + 1;
}
sr_splits.Close();
sr_splits.Dispose();
}
}
}
Visual Studio is telling me at this line:
string[] as_splitNumbers;
That:
"as_splitNumbers is never assigned to and will always return a null value."
When I also run the program, it throws a NullReferenceException during the while loop.
My question is then, what am I doing wrong when it comes to assigning the StreamReader values to the as_splitNumbers array? What am I missing in my logic?
Thank you.
You're not initializing your array with a size.
What you could do if you don't know the size is use List<int>.
Change
string[] as_splitNumbers
to
List<string> as_SplitNumbers = new List<string>();
and your method to:
private void PopulateSplits()
{
//sets the count
i_splitCount = 0;
//reads the split file
using(StreamReader sr_splits = new StreamReader(#"a\file\path\here\.txt"))
{
//begin populating the array
while (sr_splits.ReadLine() != null)
{
//split ID
string split = sr_splits.ReadLine();
as_splitNumbers.Add(split);
i_splitCount = i_splitCount + 1;
}
}
}
If what you're sending it to (SeperateDataSet();?) requires an array, you can cast it by using _asSplitNumbers.ToArray() later on. List<T> just allows you to add without knowing the size.
Try to use a List (System.Enumerable).
Because you donn't know the size of the array before reading.
At the declaration of the variable it will means:
List<string> as_splitNumbers = new List<string>();
in the loop you can simply write
as_splitNumbers.Add(sr_splits.ReadLine())
and it will work!
Your as_splitNumbers array is never allocated. You need to initialize the array with a size first.
string[] as_splitNumbers = new string[SIZE];
However, it seems you should just use a List in your case.
List<string> as_splitNumbers = new List<string>();
Then
//split ID
as_splitNumbers.Add(sr_splits.ReadLine());
Why is my delimiter not appearing in the final output? It's initialized to be a comma, but I only get ~5 white spaces between each attribute using:
SELECT [article_id]
, dbo.GROUP_CONCAT(0, t.tag_name, ',') AS col
FROM [AdventureWorks].[dbo].[ARTICLE_TAG_XREF] atx
JOIN [AdventureWorks].[dbo].[TAGS] t ON t.tag_id = atx.tag_id
GROUP BY article_id
The bit for DISTINCT works fine, but it operates within the Accumulate scope...
Output:
article_id | col
-------------------------------------------------
1 | a a b c
Update: The excess space between values is because the column as defined as NCHAR(10), so 10 characters would appear in the output. Silly mistake on my part...
Solution
With Martin Smith's help about working with the Write(BinaryWriter w) method, this update works for me:
public void Write(BinaryWriter w)
{
w.Write(list.Count);
for (int i = 0; i < list.Count; i++ )
{
if (i < list.Count - 1)
{
w.Write(list[i].ToString() + delimiter);
}
else
{
w.Write(list[i].ToString());
}
}
}
The Question:
Why does the above solve my problem? And why wouldn't it let me use more than one w.write call inside the FOR loop?
C# Code:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Xml.Serialization;
using System.Xml;
using System.IO;
using System.Collections;
using System.Text;
[Serializable]
[SqlUserDefinedAggregate(Format.UserDefined, MaxByteSize = 8000)]
public struct GROUP_CONCAT : IBinarySerialize
{
ArrayList list;
string delimiter;
public void Init()
{
list = new ArrayList();
delimiter = ",";
}
public void Accumulate(SqlBoolean isDistinct, SqlString Value, SqlString separator)
{
delimiter = (separator.IsNull) ? "," : separator.Value ;
if (!Value.IsNull)
{
if (isDistinct)
{
if (!list.Contains(Value.Value))
{
list.Add(Value.Value);
}
}
else
{
list.Add(Value.Value);
}
}
}
public void Merge(GROUP_CONCAT Group)
{
list.AddRange(Group.list);
}
public SqlString Terminate()
{
string[] strings = new string[list.Count];
for (int i = 0; i < list.Count; i++)
{
strings[i] = list[i].ToString();
}
return new SqlString(string.Join(delimiter, strings));
}
#region IBinarySerialize Members
public void Read(BinaryReader r)
{
int itemCount = r.ReadInt32();
list = new ArrayList(itemCount);
for (int i = 0; i < itemCount; i++)
{
this.list.Add(r.ReadString());
}
}
public void Write(BinaryWriter w)
{
w.Write(list.Count);
foreach (string s in list)
{
w.Write(s);
}
}
#endregion
}
The problem here is that you do not serialize delimiter. Add:
w.Write(delimiter)
as a first line in your Write method and
delimiter = r.ReadString();
as a first line in your Read method.
Regarding your questions to suggested work-around:
Why does the above solve my problem?
It does not. It merely worked with your test scenario.
And why wouldn't it let me use more than one w.write call inside the FOR loop?
Write method needs to be compatible with Read method. If you write two strings and read only one then it is not going to work. The idea here is that your object may be removed from the memory and then loaded. This is what Write and Read are supposed to do. In your case - this indeed was happening and you were not able to keep the object value.
The answer given by #agsamek is correct but not complete. The query processor may instantiate multiple aggregators, e.g. for parallel computations, and the one that will eventually hold all data after successive calls of Merge() may be assigned an empty recordset, i.e. its Accumulate() method may be never called:
var concat1 = new GROUP_CONCAT();
concat1.Init();
results = getPartialResults(1); // no records returned
foreach (var result in results)
concat1.Accumulate(result[0], delimiter); // never called
...
var concat2 = new GROUP_CONCAT();
concat2.Init();
results = getPartialResults(2);
foreach (var result in results)
concat2.Accumulate(result[0], delimiter);
...
concat1.Merge(concat2);
...
result = concat1.Terminate();
In this scenario, concat1's private field delimiter used in Terminate() remains what it is by default in Init() but not what you pass in SQL. Luckily or not, your test SQL uses the same delimiter value as in Init(), so you can't reveal the difference.
I'm not sure if this is a bug or if it has been fixed in later versions (I stumbled on it in SQL Server 2008 R2). My workaround was to make use of the other group that is passed in Merge():
public void Merge(GROUP_CONCAT Group)
{
if (Group.list.Count != 0) // Group's Accumulate() has been called at least once
{
if (list.Count == 0) // this Accumulate() has not been called
delimiter = Group.delimiter;
list.AddRange(Group.list);
}
}
P.S. I would use StringBuilder instead of ArrayList.