Archive for Luty, 2010

Przegranie filmu z płyty VCD

Chciałem dzisiaj przegrać film z płyty VCD i okazało się to trochę bardziej skomplikowane niż początkowo mi się wydawało.

Początkowo sprawdziłem þlytę, znalazłem na niej pliki z rozszerzeniem dat więc stwierdziłem, że wystarczy przegrać taki plik. Niestety, nie dało się go odtworzyć przy użyciu aplikacji mplayer.

Drugie podejście polegało na użyciu polecenia ffmpeg. Niestety także nie zadziało.

Trzecie podejście do użycie aplikacji k3b w celu skopiowania płyty także nie zadziało (błąd związany z wieloma ścieżkami znajdującymi się na płycie).

Skończyło się łatwe podejście, więc trzeba było teraz trochę poszukać:

$ aptitude search vcd
p   vcdimager     - A VideoCD (VCD) image mastering and ripping tool
p   vcdtools      - Creates Video CD (VCD) filesystem images

Przeszukanie listy dostępnych pakietów w sowich wynikach wskazało na aplikację vcdimager, wiec trzeba ją było zainstalować:

# aptitude install vcdimager

Teraz kolej na sprawdzenie, jaki pliki binarne zostały zainstalowane i co może pomóc w zgraniu płyty:

$ dpkg-query -L vcdimager | grep bin/
/usr/bin/cdxa2mpeg
/usr/bin/vcd-info
/usr/bin/vcdimager
/usr/bin/vcdxbuild
/usr/bin/vcdxgen
/usr/bin/vcdxminfo
/usr/bin/vcdxrip

Najbardziej pomocna wydaje się aplikacji vcdxrip

Tutaj się pojawił problem, bardzo kiepska dokumentacja, zarówno w postaci plików man jak i dostępna na stronie aplikacji. Ale po krótkich poszukiwaniach udało mi się znaleźć rozwiązanie. Aby odczytać film z płyty wystarczy wydać następujące polecenie:

$ vcdxrip --nofiles -p

Spowoduje ono odczytanie zawartości płyty oraz zapisanie znalezionych na niej ścieżek w bieżącym katalogu w formacie MPEG.

Źródła

Tags: , , , , ,

Definicja interfejsu w Javie

Poniżej znajduje się przykładowa definicja interfejsu napisana w Javie. Pierwsze pytanie brzmi, które elementy tej definicji są poprawne? Drugie, jak poszczególne (poprawne) elementy zachowają się podczas implementacji interfejsu?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public interface InterfaceTest {

    // definicje pól
   
    int x1 = 1;
   
    public int x2 = 2;
   
    protected int x3 = 3;
   
    private int x4 = 4;
   
    static int x5 = 5;
   
    public static final int x6 = 6;
   
    final int x7 = 7;
   
   
    // metody
   
    int f1();
   
    public int f2();
   
    private int f3();
   
    protected int f4();
}

Poprawnie są zdefiniowane następujące pola: x1, x2, x5, x6, x7 oraz metody f1() i f2().

Błędne natomiast są definicje dla x3, x4 oraz f3() i f4(). Dlaczego?

Interfejs w praktyce definiuje nam zestaw pewnych publicznych metod, które zapewniają nam możliwość wywoływania określonych akcji na obiekcie. Z tego powodu w definicji interfejsu są dopuszczalne jedynie użycie modyfikatora public lub też jego brak (wtedy definicja także staje się publiczna). Inne przypadki są niedozwolone.

A teraz drugie pytanie, czy są jakieś różnice w dostępie do poszczególnych pól zdefiniowanych w interfejsie? Oto przykładowa klasa implementująca powyższy interfejs:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Test implements InterfaceTest {

    @Override
    public int f1() {
        x1 = 0;
        x2 = 0;
        x5 = 0;
        x6 = 0;
        x7 = 0;
       
        return 0;
    }

    @Override
    public int f2() {
        return 0;
    }
}

Jak widać w klasie Test są zaimplementowane dwie metody f1() oraz f2(). W metodzie f1() następuje przypisanie nowej wartości zmiennym z interfejsu. Które przypisanie jest poprawne?

Odpowiedź: żadne. Dlaczego? Ponieważ definicje pól w interfejsie zawszą są finalne i statyczne.

Podsumowując, zasady jakie panują podczas definicji poszczególnych elementu interfejsu:

Pola interfejsu

  • mogą być tylko publiczne i tak są domyślnie definiowane
  • zawsze są statyczne
  • zawsze są finalne

Metody

  • mogą być tylko publiczne
  • nie mogą byś statyczne
  • nie mogą być finalne

Źródła

Tags: , ,

Blaski i cienie rekrutacji do firmy informatycznej

Filmy mówiące o procesie rekrutacji do firmy informatycznej.

Tags: , ,

Wielokrotne rzutowanie typów prostych

Poniżej znajduje się prosta aplikacja, która rzutuje jedną liczbę między różnymi typami, tak że na wejściu mamy typ int, na wyjściu także.

1
2
3
4
5
public class Multicast {
    public static void main(String[] args) {
        System.out.println((int) (char) (byte) -1);
    }
}

I pytanie, co zostanie wydrukowane?.

Program jest dosyć prosty. Konwersja rozpoczyna się od cyfry -1, będącej typu int (domyślny typ dla liczb całkowitych). Następnie zostaje dokonana konwersja zawężająca do typu byte (8 bitów), potem do char (16 bitów) a na końcu z powrotem do typu int (32 bity). A na końcu drukuje liczbę 65535. I teraz pytanie brzmi, dlaczego nie -1?

Java wykorzystuje do prowadzenia obliczeń tzw. kod uzupełnień do dwóch:

Kod uzupełnień do dwóch (w skrócie U2 lub ZU2) – system reprezentacji liczb całkowitych w dwójkowym systemie pozycyjnym. Jest obecnie najpopularniejszym sposobem zapisu liczb całkowitych w systemach cyfrowych. Jego popularność wynika z faktu, że operacje dodawania i odejmowania są w nim wykonywane tak samo jak dla liczb binarnych bez znaku.

Z tej reprezentacji wynika, że liczba -1 w reprezentacji dwójkowej składa się z 32 jedynek. Rzutowanie z typu int to typu byte jest prosta i nie sprawia problemów. W wyniku tej konwersji zostają usunięte wszystkie bity oprócz tych najmniej znaczących. Czyli koniec końców także otrzymujemy liczbę -1 zapisane w 8 bitach (8 jedynek).

Natomiast rzutowanie na tym char sprawia więcej problemów. Typ char jest typem, w kŧórym można zapisać tylko liczby dodatnie, więc nie można zapisać w nim wartości ujemnej. Z tego powodu konwersja z typu char do byte nie jest uważana za konwersję rozszerzającą, tylko jest konwersja zawężająca. To powoduje, że najpierw nasŧępuje niejawna konwersja do typu int a dopiero teraz do typu char.

Więc najpierw następuje konwersja z typu byte na int, co powoduje, że uzyskujemy liczbę -1, która w zapisie dwójkowym składa się z 32 jedynek. Następnie dokonana zostaje konwersja do typu char, czyli zostają zachowane najmniej znaczące 16 bitów, czyli same jedynki czyli 65535.

Źródła

Tags: ,

Konwersja typów prymitywnych

W Javie można rozróżnić kilka typów prymitywnych. Każdy z tych typów charakteryzuje się pewnymi właściwościami, które można zobaczyć w poniższej tabeli. Należny pamiętać, że typy prymitywne są takie same w każdej implementacji Javy, nieżalenie od sprzętu na którym działa. Małe podsumowanie:

Nazwa Rozmiar
w bitach
Minimalna
wielkość
Maksymalna
wielkość
Klasa wrappera
byte 8 -128 127 Byte
char 16 0 216-1 Character
short 16 -215 215-1 Short
int 32 -231 231-1 Integer
long 64 -263 263-1 Long
Nazwa Rozmiar
w bitach
Minimalna
liczba
Maksymalna
liczba
Klasa wrappera
float 32 1.4e-45 3.4028235e+38 Float
double 64 4.9e-324 1.797e+308 Double
boolean 1 Boolean
void Void

Możemy rozróżnić dwa typy konwersji: rozszerzającą i zawężającą. Konwersja rozszerzająca ma miejsce wtedy, gdy rzutujemy daną wartość na typ o szerszym zakresie danych. Odbywa się ona automatycznie w razie potrzeby. Zgodnie z poniższą konwencją:

Rzutowanie typów prostych

W przypadku typu char następuje rzutowanie do typu int, pomimo tego że typ short ma taką samą wielkość. Jest spowodowane tym, że typ char jako jedyne nie pozwala na zapisanie liczb ujemnych, i tym samym reprezentuje większy zakres liczb.

Podczas konwersji z typu long do typu float może mieć miejsce utrata danych.

Natomiast konwersja zawężająca ma miejsce wtedy, gdy podczas konwersji możemy część danych lub też precyzje obliczeń.

Konwersje zawężające zwykle wymagają odpowiedniego rzutowania. Jeżeli ma miejsce rzutowanie to niezależnie od tego czy tracimy jakieś informacje czy też dane ulegną niespodziewanej zmianie to kompilator nigdy nie wyrzuci żadnego wyjątku w trakcie działania aplikacji. Konwersja zostanie dokonana bez zgłaszania błędów.

Źródła

Tags: , , , , , , , , ,