Diskuze: Kódování textu
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.

Tvůrce

Zobrazeno 50 zpráv z 59.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
Myslím, že rychlost bude vždy stejná, záleží na tom webu, ze kterého to stahuješ. Pokud je kódování UTF8, naměl by to být problém. Pokud ne, musí se převést. Zkus webklientovi nastavit Encoding na System.Text.Encoding.UTF8.
JJ - jede to - děkuji. Mám ale menší zápletku - dělám html parser - tedy encoding se dozvím až po stáhnutí html z url. Jak bych to tedy měl řešit? Děkuji.
Zde jsou:
X-AspNetMvc-Version, Content-Length, Cache-Control, Content-Type, Date, Server, X-AspNet-Version, X-Powered-By
Proto sem píši...
To netuším - jak na to - já mám k dispozici jen stringové pole, které jsem vložil hoře...
Content-Type
je jen klíč, ke kterému bývá i hodnota.
Například
text/html; charset=UTF-8
.
Ano - to vím, ale mě to ukazuje prázdný string...
HttpWebRequest.Create(new Uri("http://www.devbook.cz")).ContentType
Vyřešeno - zatím nemohu ověřit - někde budu mít asi botu - jen není hlášen žádný error.
private void GetHtml(string urlWithCode)
{
var charSet = ((HttpWebResponse)((HttpWebRequest)WebRequest.Create(urlWithCode)).GetResponse()).CharacterSet;
Encoding pageEncoding;
if (String.IsNullOrEmpty(charSet))
pageEncoding = Encoding.Default;
else
pageEncoding = Encoding.GetEncoding(charSet);
htmlCode = new WebClient() { Encoding = pageEncoding } .DownloadString(urlWithCode);
}
Kód se zdá být OK - do poslední chvíle dostávám odezvu - co jsem zadal se stalo. Ovšem když má dojít na stáhnutí html, najednou se vše zastaví...
První metodu máte o něco výše, hlavní činitel:
private void SetUrl(string adjustmentUrl = null)
{
var valid = true;
var index = tabControl1.SelectedIndex;
string url = tabControl1.TabPages[index].Controls[0].Text;
if (url != "" || adjustmentUrl != null)
{
if (adjustmentUrl == null)
adjustmentUrl = url;
if (!UrlExist(adjustmentUrl))
if (UrlExist("http://www." + adjustmentUrl))
adjustmentUrl = "http://www." + adjustmentUrl;
else if (UrlExist("https://www." + adjustmentUrl))
adjustmentUrl = "https://www." + adjustmentUrl;
else if (UrlExist("http://" + adjustmentUrl))
adjustmentUrl = "http://" + adjustmentUrl;
else if (UrlExist("https://" + adjustmentUrl))
adjustmentUrl = "https://" + adjustmentUrl;
else valid = false;
if (valid)
{
GetHtml(adjustmentUrl);
textboxes[index].Text = htmlCode;
MessageBox.Show(htmlCode);
}
else
MessageBox.Show("Stránka nenalezena!");
}
}
Podotýkám, že url se mi skutečně daří dát dohromady - v to problém
není...
Pokud není problém v URL, pak nechápu, proč nám dáváš tu 2. metodu.
No protože toto není jediný způsob získání URL - tedy někdy znám přesnou URL - tak dám rovnou GetHtml... Jak píši - do poslední chvíle vše běží jak má - jakmile dojde na stáhnutí stringu, tak se to zasekne... Zkoušel jsem i nastavit kódování pevně...
No tak to zkus s pevnými URL. Koukal bych se tam, kde to padá, vůbec bych neřešil generování URL.
No toto funguje:
new WebClient() { Encoding = Encoding.UTF8 } .DownloadString(urlWithCode)
Ale GetHtml již ne... A proměnná pageEncoding má správný obsah... Jak píši - do poslední chvíle je to OK...
Psal jsem abys zkusil pevné URL, tedy dát je přímo té GetHtml("pevneurl.cz")
Aha - je to tak - posílá se mi špatná URL - děkuji.
Tak ne - dal jsem si pomocí MessageBox vyjet URL a byla OK...
Toto mi vyjelo v GetHtml - z parametru urlWithCode:
MessageBox? Používej BreakPointy, potom jen najedeš na proměnnou a vidíš její obsah. Zkus tu funkci s pevnými URL po jednom, takhle se nikam nedostaneš, když to budeš ladit jako celek.
Je třeba uzavřít spojení...
private void GetHtml(string urlWithCode)
{
var response = ((HttpWebResponse) HttpWebRequest.Create(urlWithCode).GetResponse());
var charSet = response.CharacterSet;
response.Close();
Encoding pageEncoding;
if (String.IsNullOrEmpty(charSet))
pageEncoding = Encoding.Default;
else
pageEncoding = Encoding.GetEncoding(charSet);
htmlCode = new WebClient() { Encoding = Encoding.UTF8 } .DownloadString(urlWithCode);
}
Jakto, že se mi zobrazuje, že devbook je na ISO-8859-1. Jako zobrazuje se to správně - české znaky - ale němělo by to být UTF-8?
Tak je to problém - v tom kódu nahoře pavně nastavuji encoding - i s proměnnou pageEncoding to jede - ale zde se jak jsem psal zobazuje ISO-8859-1 a české znaky nejdou... Jiné stránky jdou.
Pokud česká www stránka používá ISO-8859-1, je to chybně. Toto kódování je určeno pro západní Evropu a neobsahuje písmena s háčky.
Pochopil bych ISO-8859-2, Windows-1250 nebo UTF-8. Jiná kódování nejsou doporučována. Dnes bych použil už jen UTF-8. Nemám důvod používat něco jiného, protože celé PC mi jede na UTF-8, takže nemusím nic konvertovat.
No ale mě to hlásí toto... Jak píši, třeba youtube jede bez problému - s českými znaky.
Zatím jsem toho moc nezkoušel - ale vše šlapalo... Vím, jakou má devbook
znakovou sadu - proto se divím - a ptám se, co s tím...
Zdá se, že na mé straně chyba není... Ale pokud se to může utnout - nedá se nějak otestovat správnost výsledku? Děkuji.
Napadá mě načíst to vždy jako UTF a případně to potom převést,
když bude v hlavičce CP1250. Ale nevím, proč zrovna nás to nemá rádo
No mě jde o to, aby na stránce nebyly nečitelné znaky - když dám utf-8 - půjde to všem?
Jo a z toho co bylo v popisu toho kódování - toho nahoře - jsem pochopil, že to bere znaky zapsané v číselném tvaru - možná to je ten problém. Jak tyto kódy zobrazit jako znaky? Tedy aby mi to dalo nejméně práce. Děkuji.
Protože v hlavičce HTTP z devbooku není uvedeno použité kódování. Je tam jen
Content-Type: text/html
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
?
Jako jak jsem psal, na mé straně již žádná chyba není, ale právě že
se mi zdá vše vpořádku i zde...
Tím lépe pro matesax, že to už nemusí ladit Ono http-equiv stejně není
vhodné pro zadání kódování, již je novější způsob:
<meta charset="UTF-8" />
To není hlavička z HTTP, ale z HTML.
Do té hlavičky Content-Type
je potřebné vpašovat
kódování. V PHP to vypadá takto:
header('Content-Type: text/html; charset=UTF-8');
V hlavičce HTML to pak už nemusí být.
Jo takhle, čili prohlížeč to pochopí, ale tyhle parsery už ne. A dělá se to? Nikdy jsem to neviděl.
Dělá se to. Dokonce bylo na jednom serveru nastaveno kódování na
Windows-1250
a bez této "finty" se mi text napsaný v UTF-8
rozhodil, i když jsem to v http-equiv
měl správně.
Dále to úspěšně využívám, pokud potřebuji prezentovat prostý text, třeba logy. Jiný způsob pro uvedení kódování prostého textu už není. Ta hlavička pak samozřejmě vypadá trochu jinak.
header('Content-Type: text/plain; charset=UTF-8');
kod je dobre, oboji, jen bych vice pouzival switch()... ale to je asi jen zvyk, ze me driv jebali za prehlednost
Já switch používám všude, kde to má smysl - kam by jsi ho jako chtěl
dát zde??
Tady bych raději v GetHtml použil ternární operátor a v SetUrl bych se
snažil vyhnout použití proměnné valid
. Také netuším, kam
bych dal switch.
private void GetHtml(string urlWithCode)
{
var response = ((HttpWebResponse) HttpWebRequest.Create(urlWithCode).GetResponse());
var charSet = response.CharacterSet;
response.Close();
Encoding pageEncoding = String.IsNullOrEmpty(charSet) ? Encoding.Default : Encoding.GetEncoding(charSet);
htmlCode = new WebClient() { Encoding = pageEncoding } .DownloadString(urlWithCode);
}
private void SetUrl(string adjustmentUrl = null)
{
var index = tabControl1.SelectedIndex;
var actualUrls = new AutoCompleteStringCollection();
foreach (Database1DataSet.UrlsMemberRow umr in urlsMemberTableAdapter.GetData().Rows)
actualUrls.Add(umr.url);
urlsCollection = actualUrls;
string url = tabControl1.TabPages[index].Controls[0].Text;
if (url != "" || adjustmentUrl != null)
{
if (adjustmentUrl == null)
adjustmentUrl = url;
if (!UrlExist(adjustmentUrl))
adjustmentUrl = UrlExist("http://www." + adjustmentUrl) ? "http://www." + adjustmentUrl :
UrlExist("https://www." + adjustmentUrl) ? "https://www." + adjustmentUrl :
UrlExist("http://" + adjustmentUrl) ? "http://" + adjustmentUrl :
UrlExist("https://" + adjustmentUrl) ? "https://" + adjustmentUrl :
null;
if (adjustmentUrl != null)
{
GetHtml(adjustmentUrl);
textboxes[index].Text = htmlCode;
}
else
MessageBox.Show("Stránka nenalezena!");
}
}
To vypadá zajímavě.
Přemýšlel jsem, jak tu nudli s UrlExist() udělat ještě čistěji.
Napadlo mě z těch různých pokusů udělat seznam, ten projít
foreach
, při úspěšném testu UrlExist()
provést
GetHtml()
a returnem opustit cyklus s návratem výsledku.
Pokud proběhne celý cyklus, hledání bylo neúspěšné. Tím odpadne poslední podmíněný příkaz. Stačí pak už jen vyvolat výjimku, kterou si vyšší vrstvy zachytí dle potřeby.
S tím cyklem mne napadlo lepší řešení:
private string[] testing = new string[5] { "http://", "https://", "http://www.", "https://www.", "" };
if (!UrlExist(adjustmentUrl))
for (int Sindex = 0; Sindex < 6; Sindex++)
if (UrlExist(testing[Sindex] + adjustmentUrl))
{
GetHtml(adjustmentUrl = testing[Sindex] + adjustmentUrl);
textboxes[index].Text = htmlCode;
break;
}
if (adjustmentUrl == "")
MessageBox.Show("Stránka nenalezena!");
Jak jsi myslel - "To vypadá zajímavě." ?
Ironii v tom nehledej.
Ten první if
se mi jeví jako zbytečný, místo
for
bych určitě použil foreach
.
Coo? Jak bys tam chtěl použít foreach? Přece to nebudu dělat přes list. Toto mi přijde jako dobré řešení. Proč by byl zbytečný? Ať udělám co udělám, kratší to už nebude - maximálně v řádu zanedbatelném...
Však testing
v principu není pole, ale seznam. Proto by se s
ním mělo zacházet jako se seznamem. Řídící proměnnou Sindex
přece k ničemu nepotřebuješ. Nebo snad ano?
Teď už nejde o to, aby to bylo ještě kratší, ale aby to bylo správně. Aby se používaly správné datové struktury pro správné účely. Psal jsem, že hledám čisté řešení.
Bude to ještě kratší.
C# neznám, ale napadlo mě, že by se to možná dalo udělat nějak takhle:
foreach (string Prefix in {"", "http://", "https://", "http://www.", "https://www."}) {
if (UrlExist(Prefix + adjustmentUrl)) {
GetHtml(Prefix + adjustmentUrl);
return htmlCode;
}
}
throw new Exception("Stránka nenalezena!");
Známou část posílám do testování hned po inicializování. Testuji pouze počáteční string. Dále SetUrl vrací bool, zda se vše povedlo.
private bool SetUrl(string adjustmentUrl = null)
{
var index = tabControl1.SelectedIndex;
var actualUrls = new AutoCompleteStringCollection();
foreach (Database1DataSet.UrlsMemberRow umr in urlsMemberTableAdapter.GetData().Rows)
actualUrls.Add(umr.url);
urlsCollection = actualUrls;
relative = adjustmentUrl == null ? tabControl1.TabPages[index].Controls[0].Text : adjustmentUrl;
foreach (string part in new string[5] { "", "http://", "https://", "http://www.", "https://www."})
if (UrlExist(part))
{
GetHtml(relative);
textboxes[index].Text = htmlCode;
return true;
}
throw new Exception("Stránka nenalezena!");
return false;
}
Pardon již nemohu editovat - return false jsem vymazal...
Pokud vracíš true nebo false, tak throw nepotřebuješ.
Naučil jsem se používat výjimky vždy, když dojde k nějaké
nestandardní situaci. Můj původní záměr totiž byl volat funkci
SetUrl()
takto:
try {
var index = tabControl1.SelectedIndex;
textboxes[index].Text=SetUrl(adjustmentUrl);
// další příkazy
}catch (Exception ex){
MessageBox.Show(ex);
}
Tímto způsobem se vyhneš použití globální proměnné
textboxes
uvnitř funkce.
Našel jsem i správný zápis inline seznamu:
foreach (string Prefix in new string[] {"", "http://", "https://", "http://www.", "https://www."}) { ... }
Tak jsem uložení url do doplňovacího listu dal do testování URL - pokud se nepovede, nemá smysl ukládat zkaženou URL...
No myslím, že bool je lepší než vyvolání vyjímky...:
private bool SetUrl(string adjustmentUrl = null)
{
relative = adjustmentUrl == null ? tabControl1.SelectedTab.Controls[0].Text : adjustmentUrl;
foreach (string part in new string[5] { "", "http://", "https://", "http://www.", "https://www."})
if (UrlExist(part))
{
GetHtml(relative);
return true;
}
return false;
}
Použití:
textboxes[tabControl1.SelectedIndex].Text = SetUrl() ? htmlCode : "Error 404" + Environment.NewLine + "Page no found!" + Environment.NewLine + "Stránka nenalezena!";
BTW: Kvůli experimentům jsem si před chvílí nainstaloval
Mono
, abych si mohl předem vyzkoušet, než sem něco pošlu. Ten
inline seznam jsem totiž v této podobě nikde nenašel. Teprve po několika
pokusech jsem přišel na to, jak to má správně vypadat.
Zobrazeno 50 zpráv z 59.