I have a problem with my code. I want to download some files (I'm currently doing a patcher), but there are so many files, and I don't want to create a string for all of them.
I want to store the links in an array. But the debugger says there's and exception in WebClient. Here's my code (fájlNév means fileName and fájlNévAlap means baseFileName): UPDATED CODE:
<!-- language: lang-c# -->
WebClient myWebClient = new WebClient();
string[] remoteUrl = new string[2] { "https://www.dropbox.com/s/62tt9w194xefk7t/", " https://www.dropbox.com/s/spni307vmk4zng9/" };
string[] fájlNév = new string[2] { "alut.dll", "DevIL.dll" };
string fájlNévAlap = "BlackBox.dll", WebResource = null;
for(int i = 0; i < remoteUrl.Length; i++) {
for(int x = 0; x < fájlNév.Length; x++) {
WebResource = remoteUrl[i] + fájlNév[x];
MessageBox.Show(WebResource);
myWebClient.DownloadFile(WebResource,fájlNév[x]);
}
}
What can I do? What is wrong?
Many comments but not one mentioned this,
check out MSDN
public void DownloadFile(
string address,
string fileName
)
DownloadFile expect a file-name and not a folder.
Try changing to:
myWebClient.DownloadFile(WebResource,"C://" + fájlNév[x])
Moreover, writing directly to root folder might cause security exception, might be a good practice to write to a specific folder.
In addition, Xantham noted the loop will cause array out of bound exception.
Ofiris gave the main answer that a file-name is necessary, however there is a more mundane problem as well that I thought should be brought to attention.
The initial calls to the for loop:
for(int i = 0; i <= remoteUrl.Length; i++)
and
for(int x = 0; x <= fájlNév.Length; x++)
They will cause an array out of bounds exception as well, when it will try to look at remoteUrl[2], in an array of only 2 objects (0 and 1).
Related
I have a for loop, and four webbrowsers. They are called:
Web1
Web2
Web3
Web4
I have a for loop:
for (int i = 1; i <= 4; i++)
I want to write the code once, and have it execute on all four browsers. I thought it was something like this:
web[i.toString()]
However that outputs:
The name "web" does not exist in the current context
How would I do it?
Use an array
var webBrowsers = new[] { Web1, Web2, Web3, Web4 };
for(int i = 0; i < webBrowsers.Length; i++)
{
webBrowsers[i]... // Do something with each
}
In general, whenever you have variables with serial names (like Web1..Web4) that's a good indication that you should probably use an array instead. Personally, I'd refactor the code so that you remove all references to the individual webBrowser controls, and use an array exclusively. However, that's probably beyond the scope of this question.
Further Reading:
Arrays Tutorial (C#)
You would need to recover the control by name, not statically, but dynamically:
var matches = this.Controls.Find(string.Format("Web{0}", i), true);
// this means you can't find that control
if (matches.Length == 0) { continue; }
// now you can cast the first control if you'd like
var web = matches[0] as WebBrowser;
Problem is that after Randomize func, array forcombo equals random_for_combo, but I do not equate them anywhere. Please help.
private void button1_Click(object sender, EventArgs e)
{
string sub = "1#2#3#4#5#6#7#8#9#10";
string[] split = sub.Split('#');
string[] forcombo = new string[split.Length / 2];
int s = 0;
for (int j = 1; j <= split.Length - 1; j += 2)
{
forcombo[s] = split[j];
s++;
}
string[] random_for_combo = new string[forcombo.Length];
random_for_combo = forcombo;
MessageBox.Show(forcombo[0] + forcombo[1] + forcombo[2] + forcombo[3] + forcombo[4], "Before random");
random_for_combo = RandomizeStrings(random_for_combo);
MessageBox.Show(forcombo[0]+forcombo[1]+forcombo[2]+forcombo[3]+forcombo[4], "After random");
}
public static string[] RandomizeStrings(string[] arr)
{
ArrayList l1 = new ArrayList(arr.Length);
ArrayList l2 = new ArrayList(arr.Length);
foreach (object k in arr)
{
l1.Add(k.ToString());
}
while (l1.Count > 0)
{
Random rnd = new Random();
int rand = rnd.Next(l1.Count);
l2.Add(l1[rand]);
l1.RemoveAt(rand);
Thread.Sleep(rnd.Next(50));
}
for (int i = 0; i < l2.Count; i++)
{
arr[i] = l2[i].ToString();
}
return arr;
}
Some helpless info to complete question..
There's a couple of problems with this code:
You're copying the reference from one array variable into another:
random_for_combo = forcombo;
This does not make the two variables contain two arrays that contain the same values, the two values now refer to the same one array in memory. Change one, and it will appear the other one changed as well. Think of the two variables as postit notes with the address of a house on them, the same address. If you go to the house and rearrange the furniture, "both houses" will appear to be changed. There is only one house however.
When you pass the array to the randomize method, you're passing a reference to the array, not a copy of the array, which means that if you change the contents of the array, you're not working on a copy, you're working on the original. This means that the array you get passed, and the array you return, is the same one array in memory
Probably not the source of the bugs in your question, but you shouldn't construct new Random objects every time you use it in a loop, instead construct it once and reuse, otherwise you risk getting back just a few distinct values.
Lastly, if your gut reaction is "this is a bug in visual studio or C#", then it almost never is, always work on the presumption that it is your own code that is faulty. By "almost never" I would say that the chance of you hitting a bug in C# or Visual Studio by chance is none.
To make a new array with the same contents of another, you have a few options:
Explicitly make an array and copy over the elements one by one:
random_for_combo = new string[forcombo.Length];
for (int i = 0; i < forcombo.Length; i++)
random_for_combo[i] = forcombo[i];
Use Array.Copy instead of the for-loop:
random_for_combo = new string[forcombo.Length];
Array.Copy(forcombo, random_for_combo, forcombo.Length);
Use the new Linq ToArray extension method:
random_for_combo = forcombo.ToArray();
Note that even though this looks like a no-op (since forcombo is an array), you'll actually get a new array with the same contents.
but you did here :
random_for_combo = forcombo;
you set random_for_combo so it point to forcombo.
if you want to use the original array than you need to copy it to new array
something like this (instead of the above line)
string[] random_for_combo = new string[forcombo.Length];
for (int i = 0; i < forcombo.Length; i++)
{
random_for_combo[i] = forcombo[i];
}
I was just shocked when my application fired an IndexOutOfRanage exception now. I opened the Debugger Locals Pane and discovered that my integer crossed it's boundary? Basically I have something like this in my code:
string folder = Extender.GetSetting<string>("textFolder");
string mlink = folder + "\\" + filename + ".txt";
if(File.Exists(mlink))
{
string fContent = File.ReadAllText(mlink);
rtbLearnGuide.Text = fContent;
string[] strings = fContent.Split(' ');
for (int i = 0; i < strings.Length; i++, words.Enqueue(strings[i]));
}
The problem here is that i reaches the length of strings[], I have attached a picture below.
What's even more weird is that I failed to reproduce this behavior a second time.
NB: I experienced something similar earlier today with this.CreateGraphics(); My code was something like:
var dc = this.CreateGraphics();//and some other stuff
The result was that it failed to draw it even after trying to rerun like 4 times, then I went back to the code and defined dc explicitly, voila it was working. Then I changed it back to var, it was still working :/?
What might be wrong?
EDIT:
I just discovered that changing the order works. For instance:
for (int i = 0; i < strings.Length; words.Enqueue(strings[i]), i++);
doesn't fire any errors.
To answer the first part of your question, you are executing the Enqueue before the for loop's test condition. So
for (int i = 0; i < strings.Length; i++, words.Enqueue(strings[i]));
should be:
for (int i = 0; i < strings.Length; i++) words.Enqueue(strings[i]);
Basically, the "increment" portion will always execute before the "test" portion.
Format your for loop logically and you will not have that error.
for (int i = 0; i < strings.Length; i++)
words.Enqueue(strings[i]);
In your code, "i" is incremented past the condition (strings.Length) you are THEN running the word.Enqueue on an out of bounds "i".
Your loop (in pseudo code):
i = 0
Loop_Label:
IF i >= strings.Length THEN GoTo End_Label
... where the for loop body should go ...
i = i + 1
words.Enqueue strings[i]
GoTo Loop_Label
End_Label:
I'm currently coding a project that can take up to 200 entries of a specific product, as determined by user input. Basically, my GUI loads, and I use jQuery to dynamically build the entries whenever there is a change to the amount field. When using jQuery, I simply give each of them ids in the form of variable1, variable2, ...., variableX (where X is the amount of entries indicated). Small snippet of code to clarify:
for(var i = 1;i <= amount_selected; i++) {
$('table_name tr:last').after('<tr><td><input type="text" id="variable' + i + '"></td></tr>');
}
Now when I try to move to the back end, I'm trying to reference these variable names by putting them in a list. I went ahead and put them in a list of HtmlInputText, to call the Variable names from the list itself. (This would save having to call all (up to 200) methods manually, which is really not an option).
So what I did (in C#) was:
List<HtmlInputText> listvar = new List<HtmlInputText>();
for(int i = 1; i <= amount_selected; i++) {
string j = "variable" + Convert.ToString(i);
HtmlInputText x = j;
listvar.Add((x));
samplemethod(listvar[i]);
}
But it's not working at all. Does anyone have any ideas as to how this would be done, without doing so manually? I know my logic might be completely off, but hopefully this illustrates at least what I'm attempting to do.
I'm assuming these inputs are in a form? If you're submitting then you can access the text boxes from the Request object:
List<string> results = new List<string>();
for (int i = 1; i <= amount_selected; i++)
{
string s = String.Format("{0}", Request.Form["variable" + Convert.ToString(i)]);
results.Add(s);
}
you could do $("#variable" + Convert.ToString(i)).val()
Ok, so hopefully I can explain this in enough detail for somebody to be able to help me.. I am writing a program in C# that is supposed to take a text file and replace specific text, which happen to be names of files, and print a new text file for every single combination of the given filenames. The specific places to change the text of filenames have their own set of possible filenames, listed as an array described below. The program should run regardless of how many filenames are available for each location as well as how many total locations for the filenames. If you really wanted to make it awesome, it can be slightly optimized knowing that no filenames should be duplicated throughout any single text file.
text is an array of lines that make up the base of the total file.
lineNum holds an array of the line locations of the filename entries.
previousFiles is an array of previously used filenames, starting with what is already in the file.
files is a jagged 2-dimensional array of possible filenames where files[1] would be an array of all the possible filenames for the 2nd location
Here is an example of how it would work with 3 separate filename locations, the first one given 3 possible filenames, the second given 8 possible filenames, and the third given 3 possible filenames.
Oh and assume buildNewFile works.
int iterator = 0;
for (int a = 0; a < 3; a++)
{
for (int b = 0; b < 8; b++)
{
for (int c = 0; c < 3; c++)
{
iterator++;
text[lineNums[0]] = text[lineNums[0]].Replace(previousFiles[0], files[0][a]);
text[lineNums[1]] = text[lineNums[1]].Replace(previousFiles[0], files[0][a]);
text[lineNums[2]] = text[lineNums[2]].Replace(previousFiles[1], files[1][b]);
text[lineNums[3]] = text[lineNums[3]].Replace(previousFiles[1], files[1][b]);
text[lineNums[4]] = text[lineNums[4]].Replace(previousFiles[2], files[2][c]);
text[lineNums[5]] = text[lineNums[5]].Replace(previousFiles[2], files[2][c]);
previousFiles = new string[] { files[0][a], files[1][b], files[2][c] };
buildNewFile(text, Info.baseFolder + "networks\\" + Info.dsnFilename + iterator + ".dsn");
}
}
}
If you guys can help me, thank you so much, I just can't figure out how to do it recursively or anything. If you have any questions I'll answer them and edit up here to reflect that.
It took me a little while to figure out what you really wanted to do. This problem can be solved without recursion, the trick is to look at the data you have and get it into a more usable format.
Your "files" array is the one that is the most inconvenient. The trick is to transform the data into usable permutations. To do that, I suggest taking advantage of yield and using a method that returns IEnumerable. The code for it is here:
public IEnumerable<string[]> GenerateFileNameStream(string[][] files)
{
int[] current_indices = new int[files.Length];
current_indices.Initialize();
List<string> file_names = new List<string>();
while (current_indices[0] < files[0].Length)
{
file_names.Clear();
for (var index_index = 0; index_index < current_indices.Length; index_index++)
{
file_names.Add(files[index_index][current_indices[index_index]]);
}
yield return file_names.ToArray();
// increment the indices, trickle down as needed
for (var check_index = 0; check_index < current_indices.Length; check_index++)
{
current_indices[check_index]++;
// if the index hasn't rolled over, we're done here
if (current_indices[check_index] < files[check_index].Length) break;
// if the last location rolls over, then we are totally done
if (check_index == current_indices.Length - 1) yield break;
// reset this index, increment the next one in the next iteration
current_indices[check_index] = 0;
}
}
}
Basically, it keeps track of the current index for each row of the files 2D array and returns the file name at each current index. Then it increments the first index. If the first index rolls over, then it resets to 0 and increments the next index instead. This way we can iterate through every permutation of the file names.
Now, looking at the relationship between lineNum and files, I assume that each location in the file is copied to two lines. The rest of the code is here:
public void MakeItWork(string[][] files, int[] lineNum, string[] text, string[] previousFiles)
{
var iterator = 0;
var filenames = GenerateFileNameStream(files);
// work a copy of the text, assume the "previousFiles" are in this text
var text_copy = new string[text.Length];
foreach (var filenameset in filenames)
{
iterator++;
Array.Copy(text, text_copy, text.Length);
for (var line_index = 0; line_index < lineNum.Length; line_index++)
{
var line_number = lineNum[line_index];
text[line_number] = text[line_number].Replace(previousFiles[line_index], filenameset[line_index / 2]);
}
buildNewFile(text_copy, Info.baseFolder + "networks\\" + Info.dsnFilename + iterator + ".dsn");
}
}
This code just takes the results from the enumerator and generates the files for you. The assumption based on your sample code is that each filename location is used twice per file (since the lineNum array was twice as long as the files location count.
I haven't fully tested all the code, but the crux of the algorithm is there. The key is to transform your data into a more usable form, then process it. The other suggestion I have when asking a question here is to describe the problem more as a "problem" and not in the terms of your current solution. If you detailed the goal you are trying to achieve instead of showing code, you can get more insights into the problem.