2009-09-10 7 views

Odpowiedz

9

Właściwie ostatnio trochę pracowałem z bajtami i mogą być denerwujące. Przekształcają się na ints przy najmniejszej prowokacji i nie ma oznaczenia, aby zamienić liczbę w bajt - na przykład 8l da ci długą wartość 8, ale dla bajtu musisz powiedzieć (bajt) 8

Co więcej, będą one (prawie zawsze) przechowywane wewnętrznie jako ints, chyba że używasz tablicy (a może nawet wtedy ... nie wiesz).

Sądzę, że po prostu zakładają one, że jedynym powodem użycia bajtu jest i/o, gdzie faktycznie potrzeba 8 bitów, ale wewnętrznie oczekują, że zawsze będziecie używać ints.

Nawiasem mówiąc, bajt może wykonać gorzej, ponieważ zawsze musi być maskowane ...

Przynajmniej ja pamiętam czytanie że rok temu, mógł zmienić teraz.

Jako przykład odpowiedź na Twoje pytanie, czy funkcja (f) wziął bajt, i trzeba było dwa bajty (B1 i B2), a następnie:

f(b1 & b2) 

nie będzie działać, ponieważ b1 & b2 zostanie przekonwertowany na wartość wyższą niż int, a int nie może być automatycznie konwertowane w dół (utrata precyzji). Więc musisz kodować:

f((byte)(b1 & b2)) 

Który byłby denerwujący.

I nie zawracaj sobie głowy pytaniem DLACZEGO b1 & b2 w górę konwertyty - ostatnio trochę sobie z tym radzę!

+4

Amen - byte manipulacja w Javie jest pełna takich dziur (zwykle typu, który jest prawie niemożliwy do uchwycenia w czasie projektowania). i dlaczego na świecie nie może kompilator dowiedzieć się, że nowy bajt [] {0x01, 0x02} jest tablicą bajtów?Dlaczego muszę napisać nowy bajt [] {(bajt) 0x01, (bajt) 0x02}?

+1

Musisz tylko rzucić wartości większe niż 0x7F, ponieważ bajty są podpisane. Nie ma w tym nic irytującego. To znacznie lepsze niż posiadanie paczki unsigned/signed char. Użyj IDE, sprawdzi on bezpieczeństwo typu i wykona rzut za Ciebie. Operacja maskowania jest jedną instrukcją, nie wpływa na wydajność. –

6

zgodnie z javadoc dla OutputStream, 24 bity wyższego rzędu są ignorowane przez tę funkcję. Myślę, że metoda istnieje ze względu na kompatybilność: dlatego nie musisz konwertować na bajt jako pierwszy i możesz po prostu przekazać liczbę całkowitą.

pozdrowienia

+2

zgodność z czym? – skaffman

+1

cóż, kompatybilność może być złym słowem dla tego ... nazwijmy to raczej prostotą lub przyjazną dla programisty o) – Atmocreations

+0

Nieciągłość pomiędzy 'write (int)' a 'write (byte [])' jest dość uderzająca, chociaż , zwłaszcza gdy widzisz, że domyślna implementacja 'write (byte [])' wywołuje 'write (int)' w pętli. – skaffman

24

Więc można zasygnalizować EOF.

„Uwaga, read() zwraca wartość int Jeśli wejście jest strumień bajtów, dlaczego nie czyta() zwraca wartość bajtu ? Używanie int jako typu zwracanego umożliwia read() do użycia -1, aby wskazać, że dotarł do końca strumienia. "

http://java.sun.com/docs/books/tutorial/essential/io/bytestreams.html

+0

mhm, dobry punkt – Atmocreations

+7

Więc jeśli napiszesz (-1), co się stanie? Czy zamyka strumień? :-) – Ken

+0

Nie. Kończysz pisanie dziwnych znaków Unicode do strumienia wyjściowego. Ale gdyby istniał strumień przyjmujący dla twojego zapisu (-1), wierzę, że to zasygnalizuje koniec strumienia do tego strumienia. Dostępne są 3 możliwości przesyłania strumieniowego: Pierwsze 2 przesyła określoną liczbę bajtów: zapis (bajt [] b, int off, int len) i zapis (bajt b). Trzecia opcja pozwala przenieść nieokreśloną liczbę bajtów za pomocą int. Dlatego używa się int. – sfish

2

Klasy Java IOStream były częścią Java od 1,0. Te klasy zajmują się tylko danymi 8-bitowymi. Domyślam się, że interfejs został zaprojektowany tak, aby jedna metoda zapisu (int b) była wywoływana dla wartości int, short, byte i char. Wszystkie są promowane do int. W rzeczywistości, ponieważ większość maszyn JVM działa na komputerach 32-bitowych, prymityw int jest najbardziej wydajnym typem, z którym można sobie poradzić. Kompilator może dowolnie przechowywać typy, takie jak bajty, używając 32 bitów. Co ciekawe, bajt [] naprawdę jest przechowywany jako sekwencja 8-bitowych bajtów. Ma to sens, ponieważ tablica może być dość duża. Jednak w przypadku pojedynczych wartości pierwotnych, takich jak int lub byte, ostateczna przestrzeń zajmowana w czasie wykonywania nie ma znaczenia, o ile zachowanie jest zgodne ze specyfikacją.

Więcej background:

http://www.java-samples.com/showtutorial.php?tutorialid=260

Założeniem dla klasy iostream jest to, że rozmówca tylko naprawdę troszczy się o najniższe 8 bitów danych, nawet gdy przechodzi w int. Jest to w porządku, o ile osoba dzwoniąca wie, że tak naprawdę zajmuje się bajtami, ale staje się problemem, gdy dane bazowe są w rzeczywistości tekstem, który wykorzystuje inne kodowanie znaków, takie jak wielobajtowy kod Unicode. Właśnie dlatego klasy Reader zostały wprowadzone z powrotem z Java 1.1. Jeśli zależy Ci na danych tekstowych i wydajności, klasy IOStream są szybsze, ale klasy Reader są bardziej przenośne.

2

Może dlatego, że bajty są domyślnie podpisane, a pliki przechowują bajty jako wartości bez znaku. Dlatego read() zwraca int - daje 255 zamiast -1 dla $ FF. To samo z write(int), nie można zapisać $ FF jako 255 w bajcie.

Powiązane problemy