First:I have to make a statistics from my csv( https://pastebin.com/jxNSzVYP ) by province. Somewhere you can find a province like this "HU-GD" then you have to see that like "HU" so first 2 letters. And i have to count how many SI/GA/etc province are there. After, i have to write out, when it is at least 3. (If the csv changes, i mean there will no more HU/SI/ etc, and there will a new one, the program have to count that.) [Check: Describe expected result]
Second: I have to make a new "newCNtunnels.csv" file. When there is a province like this "HU-GD" i have to separete them and write them with same datas, just the province is different. [Check: Describe expected result]
I am not a big programmer, so please do not over complicate this.
Sorry for my English. It is not my first language, but probably you have already noticed this.
Thanks for the help!
I am using windows 10 and visual studio. C# language
struct datas
{
public string name;
public int length;
public string date;
public string province;
}
datas[] tunnel = new datas[99];
int i = 0;
int howmanyrow= 0;
StreamReader sr = new StreamReader("CNtunnels.csv");
sr.ReadLine();
while (!sr.EndOfStream)
{
String[] onerow= sr.ReadLine().Split(';');
tunnel[i].name= onerow[0];
tunnel[i].length= Convert.ToInt32(onerow[1]);
tunnel[i].date= onerow[2];
tunnel[i].province= onerow[3];
i++;
howmanyrow++;
}
sr.Close();
Excepted results:
https://pastebin.com/EsQz16A0
See following solution :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string INPUT_CSV_FILENAME = #"c:\temp\test.csv";
const string OUTPUT_CSV_FILENAME = #"c:\temp\test1.csv";
const string OUTPUT_STATISTICS_FILENAME = #"c:\temp\statistic.txt";
static void Main(string[] args)
{
Data data = new Data(INPUT_CSV_FILENAME);
data.WriteStatistics(OUTPUT_STATISTICS_FILENAME);
data.WriteCSV(OUTPUT_CSV_FILENAME);
}
}
class Data
{
public static List<Data> datas = new List<Data>();
public string name;
public int length;
public string date;
public string province;
public Data() { }
public Data(string filename)
{
StreamReader reader = new StreamReader(filename);
string line = "";
int rowCount = 0;
while ((line = reader.ReadLine()) != null)
{
line = line.Trim();
if (line.Length > 0)
{
string[] splitArray = line.Split(new char[] { ';' });
if (++rowCount > 1)
{
string[] splitProvidence = splitArray[3].Split(new char[] { '-' });
foreach (string providence in splitProvidence)
{
Data newRow = new Data();
Data.datas.Add(newRow);
newRow.name = splitArray[0];
newRow.length = int.Parse(splitArray[1]);
newRow.date = splitArray[2];
newRow.province = providence;
}
}
}
}
}
public void WriteStatistics(string filename)
{
StreamWriter writer = new StreamWriter(filename);
var groups = datas.GroupBy(x => x.province).OrderByDescending(x => x.Count()).ToList();
foreach (var group in groups)
{
writer.WriteLine("{0} - {1}", group.Key, group.Count());
}
writer.Flush();
writer.Close();
}
public void WriteCSV(string filename)
{
StreamWriter writer = new StreamWriter(filename);
string header = string.Join(";", new string[] { "name","length","date","province"});
writer.WriteLine(header);
foreach (Data data in datas)
{
writer.WriteLine(string.Join(";",new string[] {
data.name,
data.length.ToString(),
data.date,
data.province
}));
}
writer.Flush();
writer.Close();
}
}
}
Related
I have a file in which i have to read text between startscriptexpression$ and Finish scriptExpression$, and also read between startupdatedescription$ and startupdatedescription$[
The problem is that i want to re write the code in a cleaner format.
My Code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Vesrion
{
class Program
{
static void Main(string[] args)
{
string path = #"C:\Users\Development\Desktop\Read\Test.txt";
using (var reader = new StreamReader(path))
{
var textInBetween = new List<string>();
var ListOFDescription = new List<string>();
string NewString = "";
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
//Reads First line,
switch (line)
{
case "StartScriptExpression$":
continue;
case "FinishScriptExpression$":
if (line.Contains("FinishScriptExpression$"))
{
line = "";
}
string Something = string.Join("", textInBetween);
textInBetween = line.Split(',').ToList();
string[] lines = Something.Split(
new string[] { Environment.NewLine },
StringSplitOptions.None);
foreach (var S in lines)
{
ListOFDescription.Add(S);
Console.WriteLine(S);
}
NewString += ListOFDescription;
break;
case "StartUpdateDescription$":
//Console.WriteLine(Environment.NewLine);
continue;
case "FinishUpdateDescription$":
// Console.WriteLine(Environment.NewLine);
continue;
default:
textInBetween.Add(line);
//Console.WriteLine(line);
break;
}
}
}
}
}
}
Text inside start and finish expression must be in a list of string array.
text inside startupdatedescription and finishupdatedescription must be in a string.
.
One way to do it is using regular expression https://dotnetfiddle.net/pxBAMv
I'm relatively new to c# and I am trying to write a program that finds the mean of every xth value in a file using Streamreader. (For example if I wanted to find the mean of every fifth value in that file)
I written some code that reads the file and splits it into a new line for each comma, and this works fine, when I try and read each specific value.
However I'm struggling to think of a way to find every specific value, such as every 4th one and then find the mean of these and output it in the same program.
static void Main(string[] args)
{
using (var reader = new StreamReader(#"file"))
{
List<string> list = new List<string>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
list.Add(values[0]);
}
}
}
Any suggestions or help would be greatly appreciated
Try like this;
static void Main()
{
using (var reader = new StreamReader(#"file"))
{
int lineNumber = 4;
bool streamEnded = false;
List<string> list = new List<string>();
while (!streamEnded)
{
var line = ReadSpecificLine(reader, lineNumber,out streamEnded);
if (string.IsNullOrEmpty(line))
{
continue;
}
var values = line.Split(',');
list.Add(values[0]);
}
}
}
public static string ReadSpecificLine(StreamReader sr, int lineNumber,out bool streamEnded)
{
streamEnded = false;
for (int i = 1; i < lineNumber; i++)
{
if (sr.EndOfStream)
{
streamEnded = true;
return "";
}
sr.ReadLine();
}
if (sr.EndOfStream)
{
streamEnded = true;
return "";
}
return sr.ReadLine();
}
The exception is happen most of the times but there are times it's working fine.
The exception is always the same
The remote server returned an error: (500) Internal Server Error.
Also the stacktrace is the same:
at System.Net.WebClient.DownloadDataInternal(Uri address, WebRequest& request)
at System.Net.WebClient.DownloadData(Uri address)
at System.Net.WebClient.DownloadData(String address)
at SatelliteImages.ExtractImages.ExtractDateAndTime(String baseAddress) in D:\C-Sharp\SatelliteImages\SatelliteImages\SatelliteImages\ExtractImages.cs:line 120
Line 120 is:
var temp = wc.DownloadData("/en");
The method:
public void ExtractDateAndTime(string baseAddress)
{
try
{
var wc = new WebClient();
wc.BaseAddress = baseAddress;
HtmlDocument doc = new HtmlDocument();
var temp = wc.DownloadData("/en");
doc.Load(new MemoryStream(temp));
var secTokenScript = doc.DocumentNode.Descendants()
.Where(e =>
String.Compare(e.Name, "script", true) == 0 &&
String.Compare(e.ParentNode.Name, "div", true) == 0 &&
e.InnerText.Length > 0 &&
e.InnerText.Trim().StartsWith("var region")
).FirstOrDefault().InnerText;
var securityToken = secTokenScript;
securityToken = securityToken.Substring(0, securityToken.IndexOf("arrayImageTimes.push"));
securityToken = secTokenScript.Substring(securityToken.Length).Replace("arrayImageTimes.push('", "").Replace("')", "");
var dates = securityToken.Trim().Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
var scriptDates = dates.Select(x => new ScriptDate { DateString = x });
foreach (var date in scriptDates)
{
DatesAndTimes.Add(date.DateString);
}
}
catch(WebException wex)
{
if (wex.Response != null)
{
using (var errorResponse = (HttpWebResponse)wex.Response)
{
using (var reader = new StreamReader(errorResponse.GetResponseStream()))
{
string error = reader.ReadToEnd();
}
}
}
countriescodes = new List<string>();
countriesnames = new List<string>();
DatesAndTimes = new List<string>();
imagesUrls = new List<string>();
this.Init();
}
}
When I use a breakpoint on the line:
string error = reader.ReadToEnd();
I see html content and in the content I see the text:
error occurred while processing your request. Return to the homepage of Sat24.com
What I want to do is somehow when the exception happen to start over again and try the download try the method ExtractDateAndTime.
I think using a timer some how and count back showing the user something like 30 seconds and try again. Will 30 seconds try will be consider as spam/flooding in the server site ?
This is the full class code but the exception is on this method ExtractDateAndTime.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Net;
using System.Xml;
using HtmlAgilityPack;
using System.ComponentModel;
namespace SatelliteImages
{
class ExtractImages
{
static WebClient client;
static string htmltoextract;
public static List<string> countriescodes = new List<string>();
public static List<string> countriesnames = new List<string>();
public static List<string> DatesAndTimes = new List<string>();
public static List<string> imagesUrls = new List<string>();
static string firstUrlPart = "http://www.sat24.com/image2.ashx?region=";
static string secondUrlPart = "&time=";
static string thirdUrlPart = "&ir=";
public class ProgressEventArgs : EventArgs
{
public int Percentage { get; set; }
public string StateText { get; set; }
}
public event EventHandler<ProgressEventArgs> ProgressChanged;
public void Init()
{
object obj = null;
int index = 0;
ExtractCountires();
foreach (string cc in countriescodes)
{
// raise event here
ProgressChanged?.Invoke(obj,new ProgressEventArgs{ Percentage = 100 * index / countriescodes.Count, StateText = cc });
ExtractDateAndTime("http://www.sat24.com/image2.ashx?region=" + cc);
index +=1;
}
ImagesLinks();
}
public void ExtractCountires()
{
try
{
htmltoextract = "http://sat24.com/en/?ir=true";//"http://sat24.com/en/";// + regions;
client = new WebClient();
client.DownloadFile(htmltoextract, #"c:\temp\sat24.html");
client.Dispose();
string tag1 = "<li><a href=\"/en/";
string tag2 = "</a></li>";
string s = System.IO.File.ReadAllText(#"c:\temp\sat24.html");
s = s.Substring(s.IndexOf(tag1));
s = s.Substring(0, s.LastIndexOf(tag2) + tag2.ToCharArray().Length);
s = s.Replace("\r", "").Replace("\n", "").Replace(" ", "");
string[] parts = s.Split(new string[] { tag1, tag2 }, StringSplitOptions.RemoveEmptyEntries);
string tag3 = "<li><ahref=\"/en/";
for (int i = 0; i < parts.Length; i++)
{
if (i == 17)
{
//break;
}
string l = "";
if (parts[i].Contains(tag3))
l = parts[i].Replace(tag3, "");
string z1 = l.Substring(0, l.IndexOf('"'));
if (z1.Contains("</ul></li><liclass="))
{
z1 = z1.Replace("</ul></li><liclass=", "af");
}
countriescodes.Add(z1);
countriescodes.GroupBy(n => n).Any(c => c.Count() > 1);
string z2 = parts[i].Substring(parts[i].LastIndexOf('>') + 1);
if (z2.Contains("&"))
{
z2 = z2.Replace("&", " & ");
}
countriesnames.Add(z2);
countriesnames.GroupBy(n => n).Any(c => c.Count() > 1);
}
}
catch (Exception e)
{
if (countriescodes.Count == 0)
{
countriescodes = new List<string>();
countriesnames = new List<string>();
DatesAndTimes = new List<string>();
imagesUrls = new List<string>();
Init();
}
}
}
public void ExtractDateAndTime(string baseAddress)
{
try
{
var wc = new WebClient();
wc.BaseAddress = baseAddress;
HtmlDocument doc = new HtmlDocument();
var temp = wc.DownloadData("/en");
doc.Load(new MemoryStream(temp));
var secTokenScript = doc.DocumentNode.Descendants()
.Where(e =>
String.Compare(e.Name, "script", true) == 0 &&
String.Compare(e.ParentNode.Name, "div", true) == 0 &&
e.InnerText.Length > 0 &&
e.InnerText.Trim().StartsWith("var region")
).FirstOrDefault().InnerText;
var securityToken = secTokenScript;
securityToken = securityToken.Substring(0, securityToken.IndexOf("arrayImageTimes.push"));
securityToken = secTokenScript.Substring(securityToken.Length).Replace("arrayImageTimes.push('", "").Replace("')", "");
var dates = securityToken.Trim().Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
var scriptDates = dates.Select(x => new ScriptDate { DateString = x });
foreach (var date in scriptDates)
{
DatesAndTimes.Add(date.DateString);
}
}
catch(WebException wex)
{
if (wex.Response != null)
{
using (var errorResponse = (HttpWebResponse)wex.Response)
{
using (var reader = new StreamReader(errorResponse.GetResponseStream()))
{
string error = reader.ReadToEnd();
}
}
}
countriescodes = new List<string>();
countriesnames = new List<string>();
DatesAndTimes = new List<string>();
imagesUrls = new List<string>();
this.Init();
}
}
public class ScriptDate
{
public string DateString { get; set; }
public int Year
{
get
{
return Convert.ToInt32(this.DateString.Substring(0, 4));
}
}
public int Month
{
get
{
return Convert.ToInt32(this.DateString.Substring(4, 2));
}
}
public int Day
{
get
{
return Convert.ToInt32(this.DateString.Substring(6, 2));
}
}
public int Hours
{
get
{
return Convert.ToInt32(this.DateString.Substring(8, 2));
}
}
public int Minutes
{
get
{
return Convert.ToInt32(this.DateString.Substring(10, 2));
}
}
}
public void ImagesLinks()
{
int cnt = 0;
foreach (string countryCode in countriescodes)
{
cnt++;
for (; cnt < DatesAndTimes.Count(); cnt++)
{
string imageUrl = firstUrlPart + countryCode + secondUrlPart + DatesAndTimes[cnt] + thirdUrlPart + "true";
imagesUrls.Add(imageUrl);
if (cnt % 10 == 0) break;
}
}
}
}
}
What i want is in case of the exception happen to start over clean over again the whole class operation.
In Form1 i start the class operation first time once:
In top:
ExtractImages ei = new ExtractImages();
Then in constructor:
ei.Init();
The problem is this exception that sometimes happen.
You could go with something like Polly or the Transient Fault Handling Application Block to apply a retry strategy to your code.
Both packages provide multiple out-of-the-box components for various scenarios and you can always develop you own. Some of the included retry policies:
Incremental
Fixed interval
Exponential back-off
Retry
Retry for ever
Retry and wait
Wait and retry for ever
...
I have some sql commands that are separated by an additional newline character:
ALTER TABLE XXX
ALTER COLUMN xxx real
ALTER TABLE YYY
ALTER COLUMN yyy real
ALTER TABLE ZZZ
ALTER COLUMN zzz real
I've tried reading the file by using an array of character separators such as the following,
new char[] { '\n', '\r'}
inside this method:
private static List<string> ReadFile(string FileName, char[] seps)
{
if (!File.Exists(FileName))
{
Console.WriteLine("File not found");
return null;
}
using (StreamReader sr = new StreamReader(FileName, Encoding.Default))
{
string content = sr.ReadToEnd();
return content.Split(seps, StringSplitOptions.RemoveEmptyEntries).ToList();
}
}
However, this doesn't seem to be working. I would like to have each command represented by a separate string. How can I do this?
Why not use File.ReadAllLines()?
private static List<string> ReadFile(string FileName)
{
if (!File.Exists(FileName))
{
Console.WriteLine("File not found");
return null;
}
var lines = File.ReadAllLines(FileName);
return lines.ToList();
}
This will automatically read and split your file by newlines.
If you want to filter out empty lines, do this:
var nonEmpty = ReadFile(path).Where(x => !string.IsNullOrEmpty(x)).ToList();
Side note, I would change your if statement to throw an exception if the file cannot be found.
if (!File.Exists(FileName))
{
throw new FileNotFoundException("Can't find file");
}
You can filter the examples. When I read them in, the empty lines had a length 1 and its char value said 131 for some reason. So I just filtered by length > 1
void Main()
{
var results = ReadFile(#"C:\temp\sql.txt", new char[]{'\n'});
Console.WriteLine(results.Count);
foreach (var result in results)
{
Console.WriteLine(result);
}
}
private static List<string> ReadFile(string FileName, char[] seps)
{
if (!File.Exists(FileName))
{
Console.WriteLine("File not found");
return null;
}
using (StreamReader sr = new StreamReader(FileName, Encoding.Default))
{
string content = sr.ReadToEnd();
return content.Split(seps, StringSplitOptions.RemoveEmptyEntries).Where (c => c.Length > 1).ToList();
}
}
Try This:
private static List<string> ReadFile(string FileName)
{
List<string> commands = new List<string>();
StringBuilder command = new StringBuilder();
if (!File.Exists(FileName))
{
Console.WriteLine("File not found");
return null;
}
foreach (var line in File.ReadLines(FileName))
{
if (!String.IsNullOrEmpty(line))
{
command.Append(line + "\n");
}
else
{
commands.Add(command.ToString());
command.Clear();
}
}
commands.Add(command.ToString());
return commands;
}
If you are sure you'll always have \r\n line endings, you can use:
var commands = content.Split(new []{"\r\n\r\n"}, StringSplitOptions.RemoveEmptyEntries);
Otherwise, try using regex:
var commands = Regex.Split(content, #"\r?\n\r?\n")
Thank you everyone for your answers. I ended up going with this helper method:
private static List<string> GetCommands(string location)
{
List<string> ret = new List<string>();
List<string> tmp = ReadFile(location, new string[] { "\r\n\r\n"});
for (int i = 0; i < tmp.Count; i++)
{
string rem = tmp[i].Replace("\r", "");
ret.Add(rem);
}
return ret;
}
As an aside, the equivalent is so much easier in Python. For example, what I'm trying to do can be expressed in these three lines:
with open('commands.txt', 'r') as f:
content = f.read()
commands = [ command for command in content.split('\n\n') ]
My file named as test.txt contains
This document is divided into about 5 logical sections starting with a feature and structure overview, followed by an overview of built in column and cell types. Next is an overview of working with data, followed by an overview of specific major features. Lastly, a “best practice” section concludes the main part of this document.
Now i want to delete 2nd line of the file.
How to do it using c#?
Thanks in advance.
Naveenkumar
List<string> lines = File.ReadAllLines(#"filename.txt").ToList();
if(lines.Count>lineNum){
lines.RemoveAt(lineNum);
}
File.WriteAllLines(#"filename.txt",lines.ToArray());
You can acheive this by splitting the text by \n and then using LINQ to select the lines you want to keep, and re-joining them.
var lineNum=5;
var lines=File
.ReadAllText(#"src.txt")
.Split('\n');
var outTxt=String
.Join(
"\n",
lines
.Take(lineNum)
.Concat(lines.Skip(lineNum+1))
.ToArray()
);
Here's a pretty efficient way to do it.
FileInfo x = new FileInfo(#"path\to\original");
string xpath = x.FullName;
FileInfo y = new FileInfo(#"path\to\temporary\new\file");
using (var reader = x.OpenText())
using (var writer = y.AppendText())
{
// write 1st line
writer.WriteLine(reader.ReadLine());
reader.ReadLine(); // skip 2nd line
// write all remaining lines
while (!reader.EndOfStream)
{
writer.WriteLine(reader.ReadLine());
}
}
x.Delete();
y.MoveTo(xpath);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace rem2ndline
{
class Program
{
static void Main(string[] args)
{
string inPath = #"c:\rem2ndline.txt";
string outPath = #"c:\rem2ndlineresult.txt";
StringBuilder builder = new StringBuilder();
using (FileStream fso = new FileStream(inPath, FileMode.Open))
{
using (StreamReader rdr = new StreamReader(fso))
{
int lineCount = 0;
bool canRead = true;
while (canRead)
{
var line = rdr.ReadLine();
lineCount++;
if (line == null)
{
canRead = false;
}
else
{
if (lineCount != 2)
{
builder.AppendLine(line);
}
}
}
}
}
using(FileStream fso2 = new FileStream(outPath, FileMode.OpenOrCreate))
{
using (StreamWriter strw = new StreamWriter(fso2))
{
strw.Write(builder.ToString());
}
}
}
}
}
Here's what I'd do. The advantage is that you don't have to have the file in memory all at once, so memory requirements should be similar for files of varying sizes (as long as the lines contained in each of the files are of similar length). The drawback is that you can't pipe back to the same file - you have to mess around with a Delete and a Move afterwards.
The extension methods may be overkill for your simple example, but those are two extension methods I come to rely on again and again, as well as the ReadFile method, so I'd typically only have to write the code in Main().
class Program
{
static void Main()
{
var file = #"C:\myFile.txt";
var tempFile = Path.ChangeExtension(file, "tmp");
using (var writer = new StreamWriter(tempFile))
{
ReadFile(file)
.FilterI((i, line) => i != 1)
.ForEach(l => writer.WriteLine(l));
}
File.Delete(file);
File.Move(tempFile, file);
}
static IEnumerable<String> ReadFile(String file)
{
using (var reader = new StreamReader(file))
{
while (!reader.EndOfStream)
{
yield return reader.ReadLine();
}
}
}
}
static class IEnumerableExtensions
{
public static IEnumerable<T> FilterI<T>(
this IEnumerable<T> seq,
Func<Int32, T, Boolean> filter)
{
var index = 0;
foreach (var item in seq)
{
if (filter(index, item))
{
yield return item;
}
index++;
}
}
public static void ForEach<T>(
this IEnumerable<T> seq,
Action<T> action)
{
foreach (var item in seq)
{
action(item);
}
}
}