In C#, I want to find a PHP Variable from a URL Code.
Example: I want to find text out of www.domain.com/file.php?var=text
The main reason for this is that I want to parse the output of
youtube.com/get_video_info?video_id=, or System.IO.Path.GetTempPath() + #"\tempytinfo.txt", which is in the format of:
?var=value&var2=value&var3=value& ...
My efforts of trying to figure this out were sitting at Google, debugging other answers and either not working or just not what i'm looking for, and Here's my efforts so far (also with the help of the first awnser):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Paste A YouTube URL/URI to Download:");
string yturlstr = Console.ReadLine();
Uri yturl = new Uri(yturlstr);
Console.WriteLine("Finding ID in YouTube URL...");
string ytid = yturlstr.Split('?')[1];
ytid = ytid.Replace("v=", "");
Console.WriteLine("Found Watch ID.");
Console.WriteLine("The " + '"' + "Watch ID" + '"' + " is " + ytid);
Console.WriteLine("Getting Video Info...");
Download("http://youtube.com/get_video_info?video_id=" + ytid, System.IO.Path.GetTempPath() + #"\tempytinfo.txt");
Console.WriteLine("Got Info.");
Console.WriteLine("Reading Video Info...");
string viddata = System.IO.File.ReadAllText(System.IO.Path.GetTempPath() + #"\tempytinfo.txt");
Console.WriteLine("Parsing Video Info...");
Dictionary<string, string> videodata = new Dictionary<string, string>();
string vdt = viddata;
string[] vdata = vdt.Split('&');
foreach (char param in vdt)
{
string[] paramParts = char.ToString(param).Split('=');
videodata.Add(paramParts[0], paramParts[1]);
}
string uefsm = WebUtility.UrlDecode(videodata["url_encoded_fmt_stream_map"]);
Dictionary<string, string> videosubdata = new Dictionary<string, string>();
string[] vsdata = uefsm.Split('&');
foreach (char param2 in uefsm)
{
string[] paramParts2 = char.ToString(param2).Split('=');
videosubdata.Add(paramParts2[0], paramParts2[1]);
}
Uri downloadlink = new Uri(WebUtility.UrlDecode(videosubdata["url"]));
Console.WriteLine("Download Link: " + '"' + downloadlink + '"');
Console.ReadKey();
}
private static void Download(string URL, string WhereToDownload)
{
var client = new WebClient();
Uri downloadurl = new Uri(URL);
client.DownloadFile(downloadurl, WhereToDownload);
}
}
}
and my error is:
An unhandled exception of type 'System.IndexOutOfRangeException' occurred in ConsoleApplication2.exe
Additional information: Index was outside the bounds of the array.
I would parse all the parameters and store them in a collection to access them easily. Suppose you have the URL in yturl like you do on your code, you can create the collection:
Dictionary<string, string> parameters = new Dictionary<string, string>();
string tmpStr = yturl.Split('?')[1];
string[] params = tmpStr.Split('&');
foreach (string param in params)
{
string[] paramParts = param.Split('=');
parameters.Add(paramParts[0], paramParts[1]);
}
And get, following your example, "text", with:
string var = parameters["var"];
// var == "text"
And any other parameter value by it's name:
string var1 = parameters["var1"];
string var2 = parameters["var2"];
Related
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Newtonsoft.Json;
namespace Rename_Files
{
public partial class Form1 : Form
{
string[] files;
public Form1()
{
InitializeComponent();
files = Directory.GetFiles(#"C:\Program Files (x86)\Steam\steamapps\common\King's Quest\Binaries\Win\Saved Games", "*.*", SearchOption.AllDirectories);
for(int i = 2; i < files.Length; i++)
{
string text = File.ReadAllText(files[i]);
int startPos = text.IndexOf("currentLevelName");
int length = text.IndexOf("currentLevelEntryDirection") - 3;
string sub = text.Substring(startPos, length);
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
The part i want to extract is :
currentLevelName":"E1_WL1_FindBow_M","currentLevelEntryDirection"
This is a part of the file content :
m_ItemsEncodedJsons ArrayProperty None ! m_WhatLevelPlayerIsAtEncodedJson ArrayProperty O G {"currentLevelName":"E1_WL1_FindBow_M","currentLevelEntryDirection":8} & m_WhatCheckPointPlay
the way i'm trying now i'm getting exception because
System.ArgumentOutOfRangeException: 'Index and length must refer to a location within the string.
Parameter name: length'
startPos value is : 1613 and the value of length is 1653
so the exception is logic but i'm not sure yet how to extract the specific string out of the text.
Update :
this is almost working :
int startPos = text.IndexOf("currentLevelName");
int length = text.IndexOf("currentLevelEntryDirection");
string sub = text.Substring(startPos, length - startPos);
the result in sub is :
"currentLevelName\":\"E1_WL1_HangingBedsA_M\",\""
but i want that sub will contain this :
currentLevelName"E1_WL1_HangingBedsA_M\"
optional without the two "" either and maybe to add _
currentLevelName_"E1_WL1_HangingBedsA_M\"
or
currentLevelName_E1_WL1_HangingBedsA_M\
The problem you are facing is indeed this one:
How to extract the content with specific pattern from a String?
In this case, you can use Regular Expression to extract the content you want.
Given the following text:
m_ItemsEncodedJsons ArrayProperty None ! m_WhatLevelPlayerIsAtEncodedJson ArrayProperty O G {"currentLevelName":"E1_WL1_FindBow_M","currentLevelEntryDirection":8} & m_WhatCheckPointPlay
By using this Regex pattern:
string pattern = #"""currentLevelName"":"".*"",""currentLevelEntryDirection"":\d+";
You will be able to extract the following content:
"currentLevelName":"E1_WL1_FindBow_M","currentLevelEntryDirection":8
Here is the code snippet in C#:
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
// this is the original text
string input = #"m_ItemsEncodedJsons ArrayProperty None ! m_WhatLevelPlayerIsAtEncodedJson ArrayProperty O G {""currentLevelName"":""E1_WL1_FindBow_M"",""currentLevelEntryDirection"":8} & m_WhatCheckPointPlay";
// this is the pattern you are looking for
string pattern = #"""currentLevelName"":"".*"",""currentLevelEntryDirection"":\d+";
RegexOptions options = RegexOptions.Multiline;
foreach (Match m in Regex.Matches(input, pattern, options))
{
Console.WriteLine("'{0}' found at index {1}.", m.Value, m.Index);
}
}
}
One of the reasons you should use Regex in this case is that, if the value of currentLevelEntryDirection is not single-digit, e.g. 8123, the above code snippet can still be able to extract the correct value.
You can also find the above example and edit it here: https://regex101.com/r/W4ihuk/3
Furthermore, you can extract the property names and values by using capturing group. For example:
string pattern = #"""(currentLevelName)"":""(.*)"",""(currentLevelEntryDirection)"":(\d+)";
You can extract the following data:
currentLevelName, E1_WL1_FindBow_M, currentLevelEntryDirection, 8 and you can get the values by looping all the Match objects.
it seems the content is separated by a space delimiter. and the positions are fixed.
If so, you could do something like :
var splitted = text.Split(' ');
var json = splitted[8]; // this is the json part in the content;
However, since we don't know wither the content might change or not. You can still use this :
var startPos = text.IndexOf('{');
var endPos = text.IndexOf('}') + 1;
var json = text.Substring(startPos, endPos - startPos);
This would extract the Json part of the file. Now, you can implement a json model that will be used to deserialize this json like this :
using System.Text.Json;
using System.Text.Json.Serialization;
public class JsonModel
{
[JsonPropertyName("currentLevelName")]
public string? CurrentLevelName { get; set; }
[JsonPropertyName("currentLevelEntryDirection")]
public int CurrentLevelEntryDirection { get; set; }
}
With that we can do :
var result = JsonSerializer.Deserialize<JsonModel>(json);
var leveName = result.CurrentLevelName;
private string FindCurrentLevelName(string MyString)
{
var FirstSplit = MyString.Split(new char[] { '{' },
StringSplitOptions.RemoveEmptyEntries);
if (FirstSplit.Length != 2)
{
return "";
}
var SecondSplit = FirstSplit[1].Split(new char[] { '}' },
StringSplitOptions.RemoveEmptyEntries);
if (SecondSplit.Length != 2)
{
return "";
}
var FinalSplit = SecondSplit[0].Split(new char[] { '"' },
StringSplitOptions.RemoveEmptyEntries);
if (FinalSplit.Length != 6)
{
return "";
}
return FinalSplit[2];
}
To get the specific string pattern in a non-JSON format data string
Use the regex to get the stirng and operate it will be good I thought.
By using the regex pattern: "currentLevelName":"\w+"
in your example content, your will get: "currentLevelName":"E1_WL1_HangingBedsA_M"
Then use the result to create or replace your file name.
the code below will get the savedGame001.txt's content and extract the currentLevelName block, then create a new file whcih the name is in this format: [filename]_[theCurrentLevelName]
using System.Text.RegularExpressions;
// your file path
string filePath = #"C:\Users\a0204\Downloads";
// your file name
string fileName = #"savedGame001.txt";
// read file content
string stringContent = string.Empty;
stringContent = System.IO.File.ReadAllText(filePath + "\\" + fileName);
// Get the mathced string By regex => "currentLevelName":"\w+"
var regex = new Regex("\"currentLevelName\":\"\\w+\"");
Match matched = regex.Match(stringContent);
string matchedString = matched.Value;
// Get the string below the colon
int colonPosition = matchedString.IndexOf(":");
string value = matchedString.Substring(colonPosition + 1);
value = value.Replace("\"", string.Empty);
// remove the .txt and add the matched string to file name
fileName = fileName.Remove(fileName.Length - 4, 4);
string newFileName = fileName + "_" + value;
// check the new file name
Console.WriteLine(newFileName);
// write content to new file name
FileStream fileStream = File.Create(filePath + "\\" + newFileName);
fileStream.Dispose();
File.WriteAllText(filePath + "\\" + newFileName, stringContent);
Console.ReadLine();
PS: the code was written by .NET6 console app
I don't know C# or any programming that well at all, but I want to learn. I've been searching online last couple days to put together what is supposed to read from 2 text files and output a file (formatted for a json file that I'll just copy/paste into that file). So I can read from two files, create a dictionary object and write to a file but it's only writing the last item. I believe I'm overwriting over and over until the last part. How do I append to the file rather than overwrite?
My code:
using System.IO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WriteLangFile
{
class Program
{
static void Main(string[] args)
{
try
{
string path1 = #"C:\temp\langVars.txt";
string path2 = #"C:\temp\langValues.txt";
string[] readVars = File.ReadAllLines(path1);
string[] readVals = File.ReadAllLines(path2);
Dictionary<string, string> dictionaryVars = new Dictionary<string, string>();
for (int i = 0; i < readVars.Length; i++)
{
dictionaryVars.Add(readVars[i], readVals[i]);
}
string outputPath = ("C:\\temp\\");
string outputFileName = ("lang.txt");
string constant, value;
foreach (KeyValuePair<string, string> kvp in dictionaryVars)
{
constant = (kvp.Key);
value = (kvp.Value);
string[] lines = { ("\"LANG_\"" + constant + "\"_LANG \"" + " : { "),
("\"translations\" : {"),
("\"Lang.asp\" : {"),
("\"eng\"" + ": \"" + value + "\""),
("}"),
("}"),
("},")
};
using (StreamWriter outFile = new StreamWriter(Path.Combine(outputPath, outputFileName)))
{
foreach (var item in lines)
{
outFile.WriteLine(item.ToString());
}
}
}
}
catch (Exception e)
{
Console.WriteLine("Exception: " + e.Message);
}
finally
{
Console.WriteLine("Executing finally block.");
}
}
}
}
Your issue is that you're opening/closing the file within the loop, and you're not using the constructor of StreamWriter that takes the append option.
The best solution is probably to move StreamWriter creation outside of the loop so that you only open the file once:
using (StreamWriter outFile = new StreamWriter(Path.Combine(outputPath, outputFileName)))
{
foreach (KeyValuePair<string, string> kvp in dictionaryVars)
{
constant = (kvp.Key);
value = (kvp.Value);
string[] lines = { ("\"LANG_\"" + constant + "\"_LANG \"" + " : { "),
("\"translations\" : {"),
("\"Lang.asp\" : {"),
("\"eng\"" + ": \"" + value + "\""),
("}"),
("}"),
("},")
};
foreach (var item in lines)
{
outFile.WriteLine(item.ToString());
}
}
}
For completeness, if you were to keep the StreamWriter creation within the loop, you could construct it like this so that it appends rather than overwriting the file:
using (StreamWriter outFile = new StreamWriter(Path.Combine(outputPath, outputFileName), append: true))
P.S. It looks like you might be trying to generate a file with JSON inside it. At present your code does not generate valid JSON. If you want to generate JSON, you should use a serializer such as JSON.NET rather than building the JSON manually (i.e. in an error-prone way).
I am trying to create text file which should contain a city name and interesting places name of that city. For this, initially I create a text file with City name. My City_list.txt file looks like this-
Flensburg
Kiel
Lübeck
Neumünster
Heide
Geesthacht
Husum
Elmshorn
Pinneberg
Wedel
...... many more
Now My next work is,by using the city name get all external links exist in Wikipedia article. So , I create a list to get all the city name so that it can create place name one after other. But my code is not working.I create the place list for Wedel, for the last one only. But not for flensburg to wedel. I know there is one looping problem, But could not get the point where should I modify my work.
My code is as follows-
public void PoiListFromWiki()
{
var startPath = Application.StartupPath;
string folderName = Path.Combine(startPath, "POI_List");
System.IO.Directory.CreateDirectory(folderName);
string fileName = "POI.txt";
var path = Path.Combine(folderName, fileName);
List<string> ReadFile = File.ReadAllLines(#"I:\TouristPlace\TouristPlace\bin\Debug\CityList\POI_list.txt", Encoding.GetEncoding("windows-1252")).ToList();
foreach (string line in ReadFile)
{
Dictionary<string, string> cities = new Dictionary<string, string>();
using (var client = new HttpClient())
{
var response = client.GetAsync("https://en.wikipedia.org/w/api.php?action=query&list=geosearch&gsradius=10000&gspage=" + WebUtility.UrlEncode(line) + "&gslimit=500&gsprop=type|name|dim|country|region|globe&format=json").Result;
if (response.IsSuccessStatusCode)
{
var responseContent = response.Content;
string responseString = responseContent.ReadAsStringAsync().Result;
var obj = JsonConvert.DeserializeObject<RootObject>(responseString).query.geosearch.Select(a => a.title).ToList(); //NulReferanceException error occurd
List<string> places = new List<string>();
foreach (var item in obj)
{
places.Add(item);
}
cities[line] = string.Join(";", places);
var output = line + ";" + cities[line];
File.WriteAllText(path, output); //here is problem
}
}
}
}
My Expected Result is
Flensburg;place1;place2..
Kiel;Place1;Place2..
Lübeck;Place1;Place2..
But With my code I got only
Lübeck;Place1;Place2..
You write the output file again and again in each loop but WriteAllText overwrite everytime the previous data with the new one. But you could do a lot better than appending to the previous text. Just use a StringBuilder to store the text while you get it and write just one time after the exit from the loop.
Here the significant changes to make to your current code....
public void PoiListFromWiki()
{
StringBuilder results = new StringBuilder();
.....
foreach (string line in ReadFile)
{
Dictionary<string, string> cities = new Dictionary<string, string>();
using (var client = new HttpClient())
{
....
cities[line] = string.Join(";", places);
results.AppendLine(line + ";" + cities[line]);
}
}
File.WriteAllText(path, results.ToString());
}
File.WrtieAllText overwrites the file. You need to use File.AppendAllText.
public void PoiListFromWiki()
{
var startPath = Application.StartupPath;
string folderName = Path.Combine(startPath, "POI_List");
System.IO.Directory.CreateDirectory(folderName);
string fileName = "POI.txt";
var path = Path.Combine(folderName, fileName);
List<string> ReadFile = File.ReadAllLines(#"I:\TouristPlace\TouristPlace\bin\Debug\CityList\POI_list.txt", Encoding.GetEncoding("windows-1252")).ToList();
foreach (string line in ReadFile)
{
Dictionary<string, string> cities = new Dictionary<string, string>();
using (var client = new HttpClient())
{
var response = client.GetAsync("https://en.wikipedia.org/w/api.php?action=query&list=geosearch&gsradius=10000&gspage=" + WebUtility.UrlEncode(line) + "&gslimit=500&gsprop=type|name|dim|country|region|globe&format=json").Result;
if (response.IsSuccessStatusCode)
{
var responseContent = response.Content;
string responseString = responseContent.ReadAsStringAsync().Result;
var obj = JsonConvert.DeserializeObject<RootObject>(responseString).query.geosearch.Select(a => a.title).ToList(); //NulReferanceException error occurd
List<string> places = new List<string>();
foreach (var item in obj)
{
places.Add(item);
}
cities[line] = string.Join(";", places);
var output = line + ";" + cities[line] + "\r\n";
if (!File.Exists(path))
{
File.WriteAllText(path, output); //here is problem
}
else
{
File.AppendAllText(path, output);
}
}
}
}
}
Try it:
public void PoiListFromWiki()
{
var startPath = Application.StartupPath;
string folderName = Path.Combine(startPath, "POI_List");
System.IO.Directory.CreateDirectory(folderName);
string fileName = "POI.txt";
var path = Path.Combine(folderName, fileName);
var output="";
List<string> ReadFile = File.ReadAllLines(#"I:\TouristPlace\TouristPlace\bin\Debug\CityList\POI_list.txt", Encoding.GetEncoding("windows-1252")).ToList();
foreach (string line in ReadFile)
{
Dictionary<string, string> cities = new Dictionary<string, string>();
using (var client = new HttpClient())
{
var response = client.GetAsync("https://en.wikipedia.org/w/api.php?action=query&list=geosearch&gsradius=10000&gspage=" + WebUtility.UrlEncode(line) + "&gslimit=500&gsprop=type|name|dim|country|region|globe&format=json").Result;
if (response.IsSuccessStatusCode)
{
var responseContent = response.Content;
string responseString = responseContent.ReadAsStringAsync().Result;
var obj = JsonConvert.DeserializeObject<RootObject>(responseString).query.geosearch.Select(a => a.title).ToList(); //NulReferanceException error occurd
List<string> places = new List<string>();
foreach (var item in obj)
{
places.Add(item);
}
cities[line] = string.Join(";", places);
output += line + ";" + cities[line]+"/r/n"; //always add new info in string, then write it all in file
File.WriteAllText(path, output);
}
}
}
}
I found this program ( http://support.microsoft.com/kb/304655 ) where i compile the code during runtime, It works for code that uses the reference,
using System;
Following is the the code for the program that compiles code during runtime,
CSharpCodeProvider codeProvider = new CSharpCodeProvider();
ICodeCompiler icc = codeProvider.CreateCompiler();
string Output = "Out.exe";
Button ButtonObject = (Button)sender;
textBox2.Text = "";
System.CodeDom.Compiler.CompilerParameters parameters = new CompilerParameters();
//Make sure we generate an EXE, not a DLL
parameters.GenerateExecutable = true;
parameters.OutputAssembly = Output;
CompilerResults results = icc.CompileAssemblyFromSource(parameters, textBox1.Text);
if (results.Errors.Count > 0)
{
textBox2.ForeColor = Color.Red;
foreach (CompilerError CompErr in results.Errors)
{
textBox2.Text = textBox2.Text +
"Line number " + CompErr.Line +
", Error Number: " + CompErr.ErrorNumber +
", '" + CompErr.ErrorText + ";" +
Environment.NewLine + Environment.NewLine;
}
}
else
{
//Successful Compile
textBox2.ForeColor = Color.Blue;
textBox2.Text = "Success!";
//If we clicked run then launch our EXE
if (ButtonObject.Text == "Run") Process.Start(Output);
}
And Following is the code i need to compile at runtime,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Text.RegularExpressions;
using Newtonsoft.Json.Linq;
namespace Tsubame
{
class Program
{
static void Main(string[] args)
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(#"url");
// Create Client
WebClient client = new WebClient();
// Assign Credentials
client.Credentials = new NetworkCredential("user", "pass");
//Grab Data
var data = client.DownloadString(#"url");
JObject o = JObject.Parse(data);
string getFristRow = Convert.ToString(o["Body"][0]["RowId"]);
string encaplulateStart = "\\\"";
string encaplulateEnd = "\\\":";
List<string> _matches = new List<string>();
_matches = Regex.Matches(getFristRow, #"(?<=" + encaplulateStart + ").*(?=" + encaplulateEnd + ")")
.Cast<Match>()
.Select(m => m.Value)
.ToList();
foreach (string head in _matches)
{
Console.WriteLine(head);
}
Console.ReadLine();
}
}
}
But when I input this gives the error code,
Error Number: CS0234
For the references other than System. May I please know how to add additional references during runtime so that it can compile sucessfully :) Thank you very much :)
You need to add the references in CompilerParameters using CompilerParameters.ReferencedAssemblies:
var parameters = CompilerParameters
{
GenerateExecutable = true,
OutputAssembly = Output,
ReferencedAssemblies = {
"System.dll",
"System.Core.dll",
// etc
}
};
(Of course you don't have to use object initializer syntax to set this up, but it makes it neater IMO.)
I am tring to give an information from friendfeed API.
As you see in code, I am using an HttpRequest to get information. It's ok.
After that I am reading XML just fine with LINQ.
But now I create a "feed" class and I want to create an object for every returned value (i from finaltoclass).
How can I do this?
Can you help me with this?
Thank you.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
class feed { }
public class entry {
string body;
string id;
string url;
public entry(string a, string b, string c)
{
body = a;
id = b;
url = c;
}
}
static void Main(string[] args)
{
string username = "semihmasat";
WebRequest ffreq = WebRequest.Create("http://friendfeed-api.com/v2/feed/" + username + "?format=xml");
WebResponse ffresp = ffreq.GetResponse();
Console.WriteLine(((HttpWebResponse)ffresp).StatusDescription);
Stream stream = ffresp.GetResponseStream();
StreamReader reader = new StreamReader(stream);
string respfinal = reader.ReadToEnd();
reader.Close();
XElement final = XElement.Load("http://friendfeed-api.com/v2/feed/" + username + "?format=xml");
var finaltoclass = from i in final.Elements("entry")
select i;
foreach (XElement i in finaltoclass) {
string body= i.Element("body").Value;
string id= i.Element("id").Value;
string url= i.Element("url").Value;
Console.WriteLine("{0},{1},{2}", body, id, url);
}
Console.ReadLine();
}
}
}
If you think to read it this way (dynamic feed class - without declaring feed, entry, via and from classes ):
dynamic feed = new Uri("http://friendfeed-api.com/v2/feed/" + username + "?format=json").GetDynamicJsonObject();
foreach (var entry in feed.entries)
{
Console.WriteLine(entry.from.name + "> " + entry.body + " " + entry.url);
}
you will need Json.Net and this extension class
Let's try this code
var finaltoclass = from i in final.Elements("entry")
select new entry (i.Element("body").Value, i.Element("id").Value, i.Element("url").Value );
You need to add to an ObservableCollection of entry.