Hej!
Piszę w Javie modyfikator schowka systemowego.
Potrafię już rozpoznać jego typ (czy schowek jest dostępny w postaci plaintext).
Chciałbym sprawdzić czy tekst schowka prowadzi do jakiejkolwiek strony internetowej (czy jest linkiem).
Nie interesuje mnie strona a wynikami wyszukiwań w Google (tekst "forum" wpisany w pasku przeglądarki prowadzi do niej).
Wyrażenia regularne nie chcą działać, gdyż pojawiają się też różne dziwne linki.
Pozdrawiam!
Nie pisałem nic sieciowego jeszcze ale może po prostu spróbuj wywołać na danym tekście metodę ping
. Wtedy po otrzymanej odpowiedzi z serwera nie tylko dowiesz się czy tekst jest linkiem ale też możesz sprawdzić czy serwer odpowiada czy nie.
Dzięki! Wpadłem właśnie na taki pomysł jakieś 10 minut temu.
Coś w stylu:
public static boolean isItValidLink (String linkCadidate) {
HttpURLConnection connection = null;
try {
/*
* The next line can throw a MalformedURLException.
*/
URL u = new URL(linkCadidate);
/*
* The next two lines can throw many kinds of exceptions.
*/
connection = (HttpURLConnection) u.openConnection();
connection.setRequestMethod("HEAD");
/*
* Returns -1 if no code can be discerned from the response (i.e., the response is not valid HTTP).
*/
if (connection.getResponseCode() == -1)
return false;
} catch (Exception e) {
return false;
}
return true;
}
Czekam na konstruktywną krytykę tego kodu.
Niestety dla: wp.pl wyrzuca wyjątek... tzn. nie jest to uznawane za URL przez Javę.
Pokaż cały kod
Przecież wp.pl nie jest linkiem.
Dla wp.pl czy też www.wp.pl nie działa opakowanie w javowego URLa.
Dla zdjęcia na facebooku - plik JPG (String rozpoczynający się od https://scontent.fwaw3-1.fna.fbcdn.net/hprofile-xpa1/v/t1.0-1/12105886...) nie działa z kolei ping.
Dlaczego tak się dzieje?
String linkCandidate = "www.wp.pl";
URL u = new URL(linkCadidate);
Wyrzuca wyjątek MalformedURLException. To samo dla "wp.pl".
Ping zależny od systemu:
public static boolean isReachableByPing(String host) {
try{
String cmd = "";
if(System.getProperty("os.name").startsWith("Windows")) {
// For Windows
cmd = "ping -n 1 " + host;
} else {
// For Linux and OSX
cmd = "ping -c 1 " + host;
}
Process myProcess = Runtime.getRuntime().exec(cmd);
myProcess.waitFor();
if(myProcess.exitValue() == 0) {
return true;
} else {
return false;
}
} catch( Exception e ) {
e.printStackTrace();
return false;
}
}
Nie działa dla zdjęcia na facebooku.
Z debuggera wiem, że myProcess.exitValue() wyrzuca 1.
Why?
Z góry dziękuję.
Zapomniałem dodać. Jest to publicznie dostępne zdjęcie.
Klikam prawym i daję na Copy Image Location w Mozilli Firefox.
Sorry, że rozpisałem kilka postów, powinien być jeden :p
www.wp.pl też nie jest linkiem, umieść w pliku html
<a href="www.wp.pl">Wirtualna Polska</a>
i spróbuj się połączyć.
Dokładniej, to jest link, ale nie do serwera tylko do pliku o nazwie www.wp.pl, który musi się znajdować obok pliku html z tym linkiem.
Poprawny URL rozpoczyna się od protokołu, np.
new URL("file://www.wp.pl");
new URL("http://www.wp.pl");
new URL("https://www.wp.pl");
Jeśli chodzi o ping, to nie wiem jaka jest wartość zmiennej host.
Polecenie
Process p = Runtime.getRuntime().exec("ping scontent.fwaw3-1.fna.fbcdn.net");
działa poprawnie. Być może Ty pingujesz do zdjęcia :P, a nie do serwera.
www.wp.pl też nie jest linkiem, umieść w pliku html
Dziękuję za odpowiedź!
Nie rozumiemy się, bo źle napisałem. Chodzi mi o "link" podany jako String w Javie.
Celem mojego programu (podprogramu) jest sprawdzenie dostępności danego adresu.
Prościej: co stanie się, jeśli wpiszemy ten String do paska adresu w przeglądarce.
Nie interesuje mnie strona Google z wynikami wyszukiwań (od kiedy większość przeglądarek ma taką funkcję, że z paska adresu możemy wyszukiwać jak w Google).
Interesuje mnie dostępność zarówno zdjęć czy innych plików, jak i innych nazw (np. wp.pl), z którymi można nawiązać połączenie.
Dlatego ani **ping **ani połączenie po próbie utworzenia URLa niezawsze działa... :(
Jeśli chodzi o ping, to nie wiem jaka jest wartość zmiennej host.
PolecenieProcess p = Runtime.getRuntime().exec("ping scontent.fwaw3-1.fna.fbcdn.net");
działa poprawnie. Być może Ty pingujesz do zdjęcia :P, a nie do serwera.
Tak pingowałem do zdjęcia.
Zauważyłem, że jeśli sprawdzę czy conajmniej jedna metoda (ping albo URL) nawiąże połączenie i zwróci true, można się połączyć, ale nie wiem czy jest to w pełni poprawne rozwiązanie.
Z góry dziękuję!
Ty czegoś nie rozumiesz, jeśli wpiszesz w pasku przeglądarki ciąg znaków np. jasna.dupa
, to przeglądarka dopisze z przodu protokół (http://
) oraz ciąg www
i spróbuje się połączyć z adresem http://www.jasna.dupa
. Natomiast konstruktor w klasie URL niczego nie dopisuje z przodu, Ty musisz podać poprawny adres, łącznie z protokołem.
Dziękuję za odpowiedź.
U mnie dopisuje z przodu tylko www.
Program ma być na tyle inteligentny, że rozpozna również skrócone nazwy :)
nietylko ładnie sformatowane URLe.
Za wiki:
Dzięki DNS nazwa mnemoniczna, np. pl.wikipedia.org jest tłumaczona na odpowiadający jej adres IP, czyli 91.198.174.192.
Pokusiło mnie to o trzecią metodę...
Podsumuję.
- Metoda sprawdza czy da się utworzyć na podstawie danego Stringu URLa oraz czy strona o tym URLu jest dostępna:
public static boolean isItValidLink (String linkCadidate) {
HttpURLConnection connection = null;
try {
/*
* The next line can throw a MalformedURLException.
*/
URL u = new URL(linkCadidate);
/*
* The next two lines can throw many kinds of exceptions.
*/
connection = (HttpURLConnection) u.openConnection();
connection.setRequestMethod("HEAD");
/*
* Returns -1 if no code can be discerned from the response (i.e., the response is not valid HTTP).
*/
if (connection.getResponseCode() == -1)
return false;
} catch (Exception e) {
return false;
}
return true;
}
- Metoda pinguje dany String.
public static boolean isReachableByPing(String host) {
try{
String cmd = "";
if(System.getProperty("os.name").startsWith("Windows")) {
// For Windows
cmd = "ping -n 1 " + host;
} else {
// For Linux and OSX
cmd = "ping -c 1 " + host;
}
Process myProcess = Runtime.getRuntime().exec(cmd);
myProcess.waitFor();
if(myProcess.exitValue() == 0) {
return true;
} else {
return false;
}
} catch (Exception e ) {
e.printStackTrace();
return false;
}
}
- Po trzecie klasa InetAdress.
import java.net.InetAddress;
W metodzie main:
System.out.println(ClipboardLinkShortener.isReachableByPing("www.wp.pl"));
System.out.println(ClipboardLinkShortener.isReachableByPing("wp.pl"));
System.out.println(ClipboardLinkShortener.isReachableByPing
("https://scontent-waw1-1.xx.fbcdn.net/hphotos-xft1/t31.0-8/1614068_820991184585112_155787083_o.jpg"));
System.out.println();
System.out.println(ClipboardLinkShortener.isItValidLink("www.wp.pl"));
System.out.println(ClipboardLinkShortener.isItValidLink("wp.pl"));
System.out.println(ClipboardLinkShortener.isItValidLink
("https://scontent-waw1-1.xx.fbcdn.net/hphotos-xft1/t31.0-8/1614068_820991184585112_155787083_o.jpg"));
System.out.println();
System.out.println(InetAddress.getByName("wp.pl").isReachable(5000));
System.out.println(InetAddress.getByName("www.wp.pl").isReachable(5000));
System.out.println(InetAddress.getByName("https://scontent-waw1-1.xx.fbcdn.net/hphotos-xft1/t31.0-8/1614068_820991184585112_155787083_o.jpg").isReachable(5000));
Co daje mi:
true
true
false
false
false
true
false
false
Exception in thread "main" java.net.UnknownHostException: https://scontent-waw1-1.xx.fbcdn.net/hphotos-xft1/t31.0-8/1614068_820991184585112_155787083_o.jpg
at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
at java.net.InetAddress$1.lookupAllHostAddr(Unknown Source)
at java.net.InetAddress.getAddressesFromNameService(Unknown Source)
at java.net.InetAddress.getAllByName0(Unknown Source)
at java.net.InetAddress.getAllByName(Unknown Source)
at java.net.InetAddress.getAllByName(Unknown Source)
at java.net.InetAddress.getByName(Unknown Source)
at ClipboardLinkShortener.main(ClipboardLinkShortener.java:167)
Wniosek: alternatywa pierwszej oraz drugiej metody to może być rozwiązanie, ale czy na pewno poprawne?
U mnie dopisuje z przodu tylko www.
Mylisz się, dopisuje również protokół, ale go nie wyświetla. Skopiuj adres z paska przeglądarki do schowka i wklej do jakiegoś edytora.
Co Cię powstrzymuje przed najbardziej naturalnym rozwiązaniem: samemu uzupełniać kandydata na link protokołem z przodu? Coś w rodzaju
import java.net.*;
public class Test
{
public static void main(String[] args)
{
System.out.println(isItValidLink("wp.pl"));
System.out.println(isItValidLink("www.wp.pl"));
System.out.println(isItValidLink("http://www.wp.pl"));
System.out.println(isItValidLink("https://www.wp.pl"));
System.out.println(isItValidLink("http://jasna.dupa"));
}
public static boolean isItValidLink (String linkCandidate)
{
String[] urls;
if(linkCandidate.toLowerCase().startsWith("https:"))
{
urls = new String[]{linkCandidate,linkCandidate.replace("https:","http:")};
}
else if(linkCandidate.toLowerCase().startsWith("http:"))
{
urls = new String[]{linkCandidate,linkCandidate.replace("http:","https:")};
}
else
{
urls = new String[]{"http://"+linkCandidate,"https://"+linkCandidate};
}
String protocol = "";
HttpURLConnection connection = null;
for(String url:urls)
{
try
{
if(protocol.isEmpty())
{
URL u = new URL(url);
connection = (HttpURLConnection) u.openConnection();
connection.setRequestMethod("HEAD");
if (connection.getResponseCode() != -1)
{
if(url.toLowerCase().startsWith("http:"))
{
protocol = "http";
}
else
{
protocol = "https";
}
}
}
}
catch (Exception e)
{
System.out.println(e);
}
}
System.out.println("Kandydat: "+linkCandidate+" Protokol: "+protocol);
return !protocol.isEmpty();
}
}
Wyjście
Kandydat: wp.pl Protokol: http
true
Kandydat: www.wp.pl Protokol: http
true
Kandydat: http://www.wp.pl Protokol: http
true
java.net.ConnectException: Connection timed out: connect
Kandydat: https://www.wp.pl Protokol: http
true
java.net.UnknownHostException: jasna.dupa
java.net.UnknownHostException: jasna.dupa
false
Działanie tej funkcji jest trochę mylące, zwraca true
dla niepoprawnego adresu "https://www.wp.pl" - poprawia błędny protokół.
Przydatna byłaby też funkcja o sygnaturze
String createValidLink(String condidateLink)
Skopiuj adres z paska przeglądarki do schowka i wklej do jakiegoś edytora.
Tak, rzeczywiście dopisuje http.
Przydatna byłaby też funkcja o sygnaturze
String createValidLink(String condidateLink)
W dużej mierze byłoby to wydzielenie napisanego przez Ciebie kodu do tej metody.
Podoba mi się przedstawione przez Ciebie rozwiązanie, ale zastanawiam się jeszcze nad jakimiś kontrprzykładami.
Np. URLami z innych protokołów niż HTTP czy HTTPS, które również coś sobą reprezentują w przeglądarce.
Takie coś istnieje?
Z góry dzięki.
Generalnie celem programu jest wykrycie długiego adresu zapisanego w schowku systemowym oraz automatyczne skrócenie go.