Using .net core to download a file from internet - c#

I'm trying to download a file from internet to local folder with .net core, although it compiles without warnings or errors when executed it shows an error
using System;
namespace download_file
{
class Program
{
static void Main(string[] args)
{
string zip_url = #"https://www.python.org/ftp/python/3.9.5/python-3.9.5-embed-amd64.zip";
string current_directory = System.IO.Directory.GetCurrentDirectory();
string dl_path = System.IO.Directory.CreateDirectory(System.String.Format(#"{0}\DL", current_directory)).FullName;
string[] zip_url_words = zip_url.Split('/', 1);
string downloaded_file_path = System.String.Format(#"{0}\{1}", dl_path, zip_url_words[zip_url_words.Length - 1]);
// downloading the embedded python zip file
file_download(zip_url, downloaded_file_path);
void file_download(string url, string save_path)
{
if (url is null)
{
return;
}
string[] url_word_array = url.Split('/', 1);
if (save_path is null)
{
save_path = System.IO.Directory.GetCurrentDirectory() + #"\" + url_word_array[url_word_array.Length - 1]; //rsplit
}
System.Net.WebClient client = new System.Net.WebClient();
client.DownloadFile(url, save_path);
//System.Console.WriteLine("Press any key...")
//System.Console.ReadLine()
}
}
}
}

The problem is in this line:
string[] zip_url_words = zip_url.Split('/', 1);
From the documentation:
public String[] Split(char[]? separator, int count);
//
// Summary:
// Splits a string into a maximum number substrings based on the provided character
// separator.
If you add 1 as the second parameter, then you're asking the function to split the string with the separator but return "only one" value in the resulting array. The function then returns an array with only the original string because that is only way it can think to split the array with exactly-one element in the array!
Therefore the above code returns ["https://www.python.org/ftp/python/3.9.5/python-3.9.5-embed-amd64.zip"] as the value for the variable zip_url_words. Change the above code like so:
string[] zip_url_words = zip_url.Split('/');
When you make this change, then the function returns an array with the split that you expect ['https:','','www.python.org','ftp','python','3.9.5','python-3.9.5-embed-amd64.zip']
I made the change and the code works for me.

I changed
string[] zip_url_words = zip_url.Split('/', 1);
to
string[] zip_url_words = zip_url.Split('/', '1');
and
string[] url_word_array = url.Split('/', 1);
to
string[] url_word_array = url.Split('/', '1');
I downloaded
Could you try one more time?

Related

Writing a certain amount of lines in a file C#

I am currently writing a program that takes in a file, loops through all of the lines.
The file contains a lot of variables + values in this format:
Message =
"alfjawejf1ij4l2jr183fhaalfjawejf1ij4l2jr183fhahalfjawejf1ij4l2jr183fhahalfjawejf1ij4l2jr183fhahalfjawejf1ij4l2jr183fhahh" //the string will encompass multiple
lines of length
Answer = ?
My program will modify the value within message and write it in a new file.
How do I store multiple lines of the value into one string (so I can modify it)?
I need it so that it recognizes "message", starts storing the next few lines, detects "answer" and stops.
For the string holding the message value, I believe some sort of concatenation will be used (concatenating multiple lines).
string[] file = System.IO.File.ReadAllLines(#path); //file is read
string pathNew = Path.GetDirectoryName(path) + "\\completed_" + Path.GetFileName(path);
using (StreamWriter writer = File.CreateText(#pathNew))
{
foreach (string line in file)
{
for (int i = 0; i < line.Length; i++)
{
if (line.Substring(0,6).Equals("Msg = "))
{
foreach (string msg in file)
{
}
}
}
}
}
You could create it pretty easily, if you would provide a method that returns an IEnumerable<string>, and then use the File.WriteAllLines( string, IEnumerable<string> ) utility method
A way you could do it could be
private IEnumerable<string> ReturnAllMessages( IEnumerable<string> lines )
{
bool isMessage = false;
foreach (var line in lines)
{
if (line.StartsWith('Msg ='))
{
isMessage = true;
// set a flag that the next lines are part of the message
// this would exclude the rest of the line from the results
// if you want it, you could use:
// yield return line.Substring('Msg ='.Length));
continue;
}
if (line.StartsWith('Answer ='))
{
// remove the flag
isMessage = false;
continue;
}
if (isMessage)
{
// yield a line that is a message
yield return line;
}
}
}
and then use the method in the following way
File.WriteAllLines( #newPath, ReturnAllMessages( File.ReadAllLines( #path ) ) );
(didn't really test the code though, so just use it as a reference ;) )
One way to do this would be to read all the text as a single string using File.ReadAllText, and then split it on "Message =" to get all the messages, and then split each message on "Answer = " to get the answer for each message (assuming the format is "Message = some message Answer = some answer Message = some other message Answer = some other answer").
It would be helpful if you included an actual sample from the file, since your code clearly was not written for the sample you've provided (there is no line where line.Substring(0,6).Equals("Msg = ") is true).
I've included a method in my sample below that creates a text file with a multi-line message, and then showed how you can read the message into a variable and display it in the console window.
Hope this helps:
private static void CreateFile(string filePath)
{
if (File.Exists(filePath)) File.Delete(filePath);
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
var fileLines = new List<string>
{
"Message = ",
"I weigh nothing, but you can still see me.",
"If you put me in a bucket, I make the bucket lighter.",
"What am I?",
"Answer = A hole",
"Message = ",
"What’s the difference between",
"a hippo and a Zippo?",
"Answer = ",
"A hippo is really heavy, ",
"and a Zippo is a little lighter."
};
File.WriteAllLines(filePath, fileLines);
}
private static void Main()
{
// Set this to a file that doesn't exist or that you don't care about
var filePath = #"f:\private\temp\temp.txt";
// Create a file with multi-line messages
CreateFile(filePath);
// Read all the file text
var fileText = File.ReadAllText(filePath);
// Split it into the message/answers
var messageAnswers = fileText.Split(new[] {"Message ="},
StringSplitOptions.RemoveEmptyEntries);
// Split each message into a message/answer array
foreach (var messageAnswer in messageAnswers)
{
var parts = messageAnswer.Split(new[] {"Answer ="},
StringSplitOptions.RemoveEmptyEntries);
var message = parts[0].Trim();
var answer = parts.Length > 1 ? parts[1].Trim() : "";
Console.WriteLine(message);
var userResponse = Console.ReadLine().Trim();
if (userResponse.Equals(answer, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("Correct!");
}
else
{
Console.WriteLine("The actual answer is: " + answer);
}
}
GetKeyFromUser("\nDone! Press any key to exit...");
}

Parsing a String With Multiple Lines (C#)

I new with C# and in and I have some questions.
I'm writing some program that get the following output from remote machine (using SSH):
wwn = 5001248018b6d7af
node_wwn = 5001248018b6d7ae
wwn = 5001248118b6d7af
node_wwn = 5001248118b6d7ae
wwn = 5001248218b6d7af
node_wwn = 5001248218b6d7ae
wwn = 5001248318b6d7af
node_wwn = 5001248318b6d7ae
The output above save into string...
I need to extract from this output List or Array in the following format:
50:01:24:80:18:b6:d7:af:50:01:24:80:18:b6:d7:ae
each two lines are couple (wwn and node_wwn)
I worth the following function
public void OutPutParse (string output)
{
string wwnn = null;
string wwpn = null;
string[] test = output.Split('\n');
test = test.Where(item => !string.IsNullOrEmpty(item)).ToArray();
//run all over the test array and exrract the wwns and wwpn
for (int i = 0; i < test.Length; i++)
{
}
}
this function create an array (test) of wwns and node_wwn
the expected results is an array or list the will include wwn + node_wwn like this
50:01:24:80:18:b6:d7:af:50:01:24:80:18:b6:d7:ae
The easiest way to achieve this is:
string www = "5001248018b6d7af";
string wwwn = "5001248018b6d7ae";
string myString = "";
// Implemenet loop here.
// www = "number" // the next number you get
// wwwn = "number" // the next number you get
myString = www + myString + wwwn;
You just have to do it with a loop when you have a list of strings or something.
If you want to have it in the same order you can either do it with a character between the strings like a ";" and split all numbers or you just do two strings and combine them at the end like that:
string www = "5001248018b6d7af";
string wwwn = "5001248018b6d7ae";
string mywwwString = "";
string mywwwnString = "";
// Implement the loop to add strings here
// www = "number" // the next number you get
// wwwn = "number" // the next number you get
mywwwString += www;
mywwwnString += wwwn;
string myString = www + wwwn;

How to incorporate a text qualifier in a file name used as a variable?

I have a C# script which takes in two CSV files as input, combines the two files, performs numerous calculations on them, and writes the result in a new CSV file.
These two input CSV file names are declared as variables and are used in the C# script by accessing those variable names.
The data in the input CSV files looks like this:
Since the data has values in thousands and millions, line splits in the C# code are truncating the data incorrectly. For instance a value of 11,861 appears only as 11 and 681 goes in the next columns.
Is there any way in C#, by which I can specify a text qualifier (" in this case) for the two files ?
Here is the C# code snippet:
string[,] filesToProcess = new string[2, 2] { {(String)Dts.Variables["csvFileNameUSD"].Value,"USD" }, {(String)Dts.Variables["csvFileNameCAD"].Value,"CAD" } };
string headline = "CustType,CategoryType,CategoryValue,DataType,Stock QTY,Stock Value,Floor QTY,Floor Value,Order Count,Currency";
string outPutFile = Dts.Variables["outputFile"].Value.ToString();
//Declare Output files to write to
FileStream sw = new System.IO.FileStream(outPutFile, System.IO.FileMode.Create);
StreamWriter w = new StreamWriter(sw);
w.WriteLine(headline);
//Loop Through the files one by one and write to output Files
for (int x = 0; x < filesToProcess.GetLength(1); x++)
{
if (System.IO.File.Exists(filesToProcess[x, 0]))
{
string categoryType = "";
string custType = "";
string dataType = "";
string categoryValue = "";
//Read the input file in memory and close after done
StreamReader sr = new StreamReader(filesToProcess[x, 0]);
string fileText = sr.ReadToEnd();
string[] lines = fileText.Split(Convert.ToString(System.Environment.NewLine).ToCharArray());
sr.Close();
where csvFileNameUSD and csvFileNameCAD are variables with values pointing to their locations.
Well, based on the questions you have answered, this ought to do what you want to do:
public void SomeMethodInYourCodeSnippet()
{
string[] lines;
using (StreamReader sr = new StreamReader(filesToProcess[x, 0]))
{
//Read the input file in memory and close after done
string fileText = sr.ReadToEnd();
lines = fileText.Split(Convert.ToString(System.Environment.NewLine).ToCharArray());
sr.Close(); // redundant due to using, but just to be safe...
}
foreach (var line in lines)
{
string[] columnValues = GetColumnValuesFromLine(line);
// Do whatever with your column values here...
}
}
private string[] GetColumnValuesFromLine(string line)
{
// Split on ","
var values = line.Split(new string [] {"\",\""}, StringSplitOptions.None);
if (values.Count() > 0)
{
// Trim leading double quote from first value
var firstValue = values[0];
if (firstValue.Length > 0)
values[0] = firstValue.Substring(1);
// Trim the trailing double quote from the last value
var lastValue = values[values.Length - 1];
if (lastValue.Length > 0)
values[values.Length - 1] = lastValue.Substring(0, lastValue.Length - 1);
}
return values;
}
Give that a try and let me know how it works!
You posted a very similar looking question few days ago. Did that solution not help you?
If so, what issues are you facing on that. We can probably help you troubleshoot that as well.

Update string at a specific line so it doesn't update duplicates in string?

I know how to go to a specific line but I don't know how to update that specific line in the string. I have tried the Replace functionality but it overwrites the duplicates as well. Any ideas?
static string GetLine(string text, int lineNo)
{
string[] lines = text.Replace("\r", "").Split('\n');
return lines.Length >= lineNo ? lines[lineNo - 1] : null;
}
static void Main(string[] args)
{
string file = "D:\\random.text";
string contents = "";
string text="random";
contents = File.ReadAllText(file);
finale=GetLine(contents,lines);
// Console.ReadLine();
if(finale.Contains(text))
{
finale.Replace(text,"Random");
System.Console.WriteLine(finale);
Console.ReadLine();
}
}
Strings are immutable type which means you cant alter an existing string. string.Replace returns the replaced string and you need to assign it back.
if(finale.Contains(text))
{
finale = finale.Replace(text,"Random"); //<- note here
System.Console.WriteLine(finale);
Console.ReadLine();
}
From there you need to rebuild the string from the string array as noted by Philippe. A complete example (but untested):
static string[] GetLines(string text)
{
return text.Replace("\r", "").Split('\n');
}
static string GetLine(string[] lines, int lineNo)
{
return lines.Length >= lineNo ? lines[lineNo - 1] : null;
}
static void Main(string[] args)
{
string file = "D:\\random.text";
string contents = "";
string text="random";
contents = File.ReadAllText(file);
var lines = GetLines(contents);
finale = GetLine(lines, lineNo);
//Console.ReadLine();
if (finale == null)
return;
if(finale.Contains(text))
{
finale = finale.Replace(text, "Random");
System.Console.WriteLine(finale);
Console.ReadLine();
}
lines[lineNo] = finale;
contents = string.Join('\n', lines);
}
And best of all, you don't need all that split function at all. .NET has that functionality and it does lazily (on demand) which is a bonus.
See for File.ReadLines if you're using .NET 4.0 and above.
The quickest solution would be to keep the array returned by Split and then use String.Join to rebuild what you started with.
Just rebuild the string with string builder as you read the file.
static void Main(string[] args)
{
string file = "D:\\random.txt";
string find = "random";
string replace = "Random";
StringBuilder resultList = new StringBuilder();
using (var stream = File.OpenText(file))
{
while (stream.Peek() >= 0)
{
string line = stream.ReadLine();
if(line == find)
{
line = replace;
}
resultList.AppendLine(line);
}
}
string result = resultList.ToString();
Console.WriteLine(result);
Console.Read();
}

C# complicated regex

Hey guys, thanks for all the help that you can provide. I need a little bit of regex help thats far beyond my knowledge.
I have a listbox with a file name in it, example 3123~101, a delimited file that has 1 line of text in it. I need to Regex everything after the last "\" before the last "-" in the text file. The ending will could contain a prefix then ###{####-004587}.txt The ~ formula is {### + ~# -1.
File name:
3123~101
So Example 1:
3123|X:directory\Path\Directory|Pre0{0442-0500}.txt
Result:
X:\directory\Path\Directory\Pre00542.txt
File name:
3123~101
So Example 1:
3123|X:directory\Path\Directory|0{0442-0500}.txt
Result:
X:\directory\Path\Directory\00542.txt
According your example I've created the following regexp:
\|(.)(.*)\|(.*)\{\d{2}(\d{2})\-(\d{2}).*(\..*)
The result should be as following:
group1 + "\\" + group2 + "\\" + group3 + group5 + group4 + group6
If you ain't satisfied, you can always give it a spin yourself here.
EDIT:
After remembering me about named groups:
\|(?<drive>.)(?<path>.*)\|(?<prefix>.*)\{\d{2}(?<number2>\d{2})\-(?<number1>\d{2}).*(?<extension>\..*)
drive + "\\" + path + "\\" + prefix + number1 + number2 + extension
public static string AdjustPath(string filename, string line)
{
int tilde = GetTilde(filename);
string[] fields = Regex.Split(line, #"\|");
var addbackslash = new MatchEvaluator(
m => m.Groups[1].Value + "\\" + m.Groups[2].Value);
string dir = Regex.Replace(fields[1], #"^([A-Z]:)([^\\])", addbackslash);
var addtilde = new MatchEvaluator(
m => (tilde + Int32.Parse(m.Groups[1].Value) - 1).
ToString().
PadLeft(m.Groups[1].Value.Length, '0'));
return Path.Combine(dir, Regex.Replace(fields[2], #"\{(\d+)-.+}", addtilde));
}
private static int GetTilde(string filename)
{
Match m = Regex.Match(filename, #"^.+~(\d+)$");
if (!m.Success)
throw new ArgumentException("Invalid filename", "filename");
return Int32.Parse(m.Groups[1].Value);
}
Call AdjustPath as in the following:
public static void Main(string[] args)
{
Console.WriteLine(AdjustPath("3123~101", #"3123|X:directory\Path\Directory|Pre0{0442-0500}.txt"));
Console.WriteLine(AdjustPath("3123~101", #"3123|X:directory\Path\Directory|0{0442-0500}.txt"));
}
Output:
X:\directory\Path\Directory\Pre00542.txt
X:\directory\Path\Directory\00542.txt
If instead you want to write the output to a file, use
public static void WriteAdjustedPaths(string inpath, string outpath)
{
using (var w = new StreamWriter(outpath))
{
var r = new StreamReader(inpath);
string line;
while ((line = r.ReadLine()) != null)
w.WriteLine("{0}", AdjustPath(inpath, line));
}
}
You might call it with
WriteAdjustedPaths("3123~101", "output.txt");
If you want a List<String> instead
public static List<String> AdjustedPaths(string inpath)
{
var paths = new List<String>();
var r = new StreamReader(inpath);
string line;
while ((line = r.ReadLine()) != null)
paths.Add(AdjustPath(inpath, line));
return paths;
}
To avoid repeated logic, we should define WriteAdjustedPaths in terms of the new function:
public static void WriteAdjustedPaths(string inpath, string outpath)
{
using (var w = new StreamWriter(outpath))
{
foreach (var p in AdjustedPaths(inpath))
w.WriteLine("{0}", p);
}
}
The syntax could be streamlined with Linq. See C# File Handling.
A slight variation on gbacon's answer that will also work in older versions of .Net:
static void Main(string[] args)
{
Console.WriteLine(Adjust("3123~101", #"3123|X:directory\Path\Directory|Pre0{0442-0500}.txt"));
Console.WriteLine(Adjust("3123~101", #"3123|X:directory\Path\Directory|0{0442-0500}.txt"));
}
private static string Adjust(string name, string file)
{
Regex nameParse = new Regex(#"\d*~(?<value>\d*)");
Regex fileParse = new Regex(#"\d*\|(?<drive>[A-Za-z]):(?<path>[^\|]*)\|(?<prefix>[^{]*){(?<code>\d*)");
Match nameMatch = nameParse.Match(name);
Match fileMatch = fileParse.Match(file);
int value = Convert.ToInt32(nameMatch.Groups["value"].Value);
int code = Convert.ToInt32(fileMatch.Groups["code"].Value);
code = code + value - 1;
string drive = fileMatch.Groups["drive"].Value;
string path = fileMatch.Groups["path"].Value;
string prefix = fileMatch.Groups["prefix"].Value;
string result = string.Format(#"{0}:\{1}\{2}{3:0000}.txt",
drive,
path,
prefix,
code);
return result;
}
You don't seem to be very clear in your examples.
That said,
/.*\\(.*)-[^-]*$/
will capture all text between the last backslash and the last hyphen in whatever it's matched against.

Categories

Resources