Java küçük endian veya büyük endian'da tamsayı okur mu?


96

Soruyorum çünkü bir C işleminden Java'ya bir bayt akışı gönderiyorum. C tarafında 32 bitlik tam sayı LSB'ye sahiptir ve ilk bayt, MSB ise 4. bayttır.

Yani sorum şu: Java tarafında, C işleminden gönderilen baytı okuduğumuzda , Java tarafında endian nedir?

Takip eden bir soru: Java tarafındaki endian gönderilenle aynı değilse, aralarında nasıl dönüşüm yapabilirim?


2
İşte bunun için anımsatıcılarım, bu yüzden unutmayacağım: Java'nın donanım değil sanal olması, internetin dilidir. Ağ bayt sırası olan big endian . Bu nedenle, Java büyük bir endian .
eigenfield

Yanıtlar:


67

Java'nın yine de kullandığı ağ bayt sırasını (big endian) kullanın. C'deki farklı çevirmenler için man htons'a bakın.


Şu anda linux kutumda değilim ama htons standart kitaplıklardan biri mi?
hhafez

H30097.www3.hp.com/docs//base_doc/DOCUMENTATION/V51_HTML/MAN/… göre standart c kitaplığının parçası, evet
Egil

1
htons hemen hemen her yerde mevcuttur, ancak ISO C'de değildir.
MSalters

1
Ağ bayt sırasından başka bir şey kullanmanız gerekiyorsa, o zaman ya kendi bit tabanlı operatörlerinizi kullanırsınız ya da java.nio'nun çeşitli sürümlerini kullanırsınız.Buffer
Darron

1
Man sayfasına göre POSIX.1'de tanımlanmıştır, bu nedenle hemen hemen her yerde mevcut olmalıdır. Ve Win32'de kullandığımı hatırlıyorum, bu yüzden sadece POSIX sistemlerinde de değil.
Joachim Sauer

51

Burada Google aracılığıyla tökezledim ve Java'nın büyük endian olduğu cevabımı aldım .

Yanıtları okurken baytların gerçekten de bir endian düzenine sahip olduğunu belirtmek isterim, ancak neyse ki, yalnızca “ana akım” mikroişlemcilerle uğraştıysanız, Intel, Motorola ve Zilog olarak şimdiye kadar karşılaşmış olmanız pek olası değildir. UART yongalarının kayma yönü ve bir baytın MSB'sinin 2**7ve LSB'nin 2**0CPU'larında olacağı konusunda hemfikir oldu (Bu şeyin ne kadar eski olduğunu vurgulamak için FORTRAN güç gösterimini kullandım :)).

Bu sorunla 20+ yıl önce 10.000 $ 'lık arayüz donanımını bir Mac bilgisayarla değiştirdiğimizde bazı Space Shuttle bit seri bağlantı indirme verileriyle karşılaştım. Uzun zaman önce yayınlanan bir NASA Tech brifingi var. table[0x01]=0x80Her bir bayt bit akışından kaydırıldıktan sonra bitleri ters çevrilmiş ( vb.) 256 elemanlı bir arama tablosu kullandım .


Harika fikir! Bu sorum var ve web'de yanıtım yok.
Xolve

Bunlardan herhangi biri halka açıksa, bahsettiğiniz NASA teknik özetini (ve uzay mekiği biti seri bağlantı indirme verilerini) birbirine bağlayabilir misiniz? büyüleyici olurdu, hiç böyle bir şey görmedim.
n611x007

3
Bitsel sonsuzluk, Huffman kodlamasının bir biçimini (yani hepsini) kullanan sıkıştırma biçimleriyle de devreye girer. Ekstra eğlence için, JPEG "bitsel büyük endian" (yani en önemli bit "ilk" bittir) ve LZ "bitsel küçük endian" dır. Bir zamanlar kaputun altında her iki formatı da kullanan özel bir sıkıştırma formatı üzerinde çalıştım. Oh, bu eğlenceliydi ...
user435779

Parçalar halinde başladığımdan, uzun zamandır BUNU sonsuzluk olduğunu düşündüm.
Roy Falk

20

Java'da işaretsiz tamsayı yoktur. Tüm tamsayılar işaretlidir ve büyük endian'dır.

C tarafında her bir baytın başında bir LSB vardır ve solda MSB sondadır.

En az anlamlı bit olarak LSB kullanıyormuşsunuz gibi geliyor, değil mi? LSB genellikle en az anlamlı baytı ifade eder. Aşk bit tabanlı değil bayt tabanlıdır.

İşaretsiz bayttan Java tamsayıya dönüştürmek için:

int i = (int) b & 0xFF;

İmzasız 32-bit little-endian'dan [] bayt cinsinden Java'ya dönüştürmek için (başımın tepesinden, test edilmemiş):

long l = (long)b[0] & 0xFF;
l += ((long)b[1] & 0xFF) << 8;
l += ((long)b[2] & 0xFF) << 16;
l += ((long)b[3] & 0xFF) << 24;

şimdi anladım: $ yani bu imzasız küçük endian'ı doğru okumak için java sürecime nasıl gönderebilirim?
hhafez

başlangıçtan kastım, lsb'nin 4 baytın başlangıcında olması (bu bir işaretsiz 32 bit int) bu yüzden en az önemli baytı kastettim
hhafez

Ayrıca C -> Java'dan Java'dan dönüştürme yapıyorum -> C :)
hhafez

Son üç satırda 0xFF'den sonra noktalı virgülü kaldırdığınız sürece kodunuz iyi çalışır. Kendim düzenlerdim ama bu 6 karakterden daha az bir değişiklik.
Moose Morals

1
Neredeyse 8 yıl sürdü ama sonunda birisi sözdizimi hatasını gördü. Teşekkürler @MooseMorals :)
Jonas Elfström

12

Java'daki bazı baytları doğrudan bir int ile eşlemenin (doğrudan API olmayan) bir yolu olmadığından, bunun Java'daki herhangi bir şeyi etkilemesi mümkün değildir.

Bunu veya benzer bir şeyi yapan her API, davranışı oldukça hassas bir şekilde tanımlar, bu nedenle bu API'nin belgelerine bakmalısınız.


3
Elbette var. İkili matematik (&, |, <<, vb.) Bayt ve ints üzerinde gayet iyi çalışır. Keyfi baytları alıp bir tam sayıya yapıştırmak oldukça kolaydır.
Herms

8
Ancak bunu yaparsanız, JVM'nizin dahili olarak hangi sonsuzluğu kullandığını hala söyleyemezsiniz.
Darron

4
Evet, ama orada bile doğrudan haritalama yapmıyorsunuz. Tam olarak ne söylediğinizi yapan aritmetik kullanıyorsunuz, belirsizlik yok. C'de her zaman bir "bayt *" ı "uzun *" a çevirebilir ve referansını kaldırabilirsiniz. O zaman sonsuzluğu önemsemelisin. Java'da bunu yapmanın doğrudan ve belirsiz bir yolu yoktur.
Joachim Sauer

Ah, anlıyorum. İkili matematikten değil, oyunculardan bahsediyordunuz. Evet, bu durumda haklısın.
Herms

10
"Belgelere bakma" için +1 , ancak NOT: 1. cümle artık doğru değildir çünkü günümüzde NIO paketi baytları ilkellerle eşleştirebilen ve bayt sırasını değiştirebileceğiniz ByteBuffer'ı sunar. ByteBuffer ve ByteOrder'a
user85421

3

Baytları tek tek okuyup uzun bir değerde birleştirirdim . Bu şekilde sonu kontrol edersiniz ve iletişim süreci şeffaftır.


Bana neden olumsuz oy verdiğiniz konusunda yorum yapmak ister misiniz?
Wouter Lievens

çünkü her bir baytı ayrı ayrı nerede okuyacaksam bile, gönderilen baytın sonu yanlış olacağı için onu dönüştürmem gerekecek
hhafez

24
Bir bayt kısırlığı? Bu ne lan? Kelimeler sonsuzluğa duyarlıdır, tek tek baytlar duyarlı değildir.
Wouter Lievens

3
@hhafez Bu doğru değil, baytlar bizim ilgilendiğimiz kadarıyla bitmezler bayt bayt okursanız baytları uygun yere atamaktan siz, programcı sorumludur. DataInputStream'in yaptığı tam olarak budur, yalnızca baytları davlumbazların altında büyük bir endian yolla bir araya getirir.
hayır

2
@WouterLievens: Her ne sebeple olursa olsun verileri bit-ters formatta gönderen bazı I / O cihazlarıyla (örneğin gerçek zamanlı saat çipi) karşılaştım; onlardan veri aldıktan sonra, her bayttaki bitleri tersine çevirmek gerekir. Yine de, baytların sonlu olmasının , tuhaf bir şekilde tasarlanmış donanım parçalarıyla uğraşmak zorunda kalmadıkça, genellikle bir sorun olmadığı konusunda size katılıyorum .
supercat

3

Kullandığınız protokole uyuyorsa, davranışın çok iyi tanımlandığı bir DataInputStream kullanmayı düşünün .


1
Bunu ancak protokolü aynı sonluluğu kullanırsa yapabilir.
Wouter Lievens

Bağlantıyı düzelttim ve mevcut sürüm olan Java 9'u gösterecek şekilde değiştirdim. Ancak söz konusu API, Java 1.0'da tanıtıldı.
Jens Bannmann

2

Java, yukarıda belirtildiği gibi 'Big-endian'dır. Bu, belleği incelerseniz (en azından bir Intel CPU'da) int'in MSB'sinin solda olduğu anlamına gelir. İşaret biti ayrıca tüm Java tamsayı türleri için MSB'dedir.
Bir 'Little-endian' sistemi tarafından depolanan bir ikili dosyadan 4 baytlık işaretsiz bir tamsayı okumak Java'da biraz uyarlama gerektirir. DataInputStream'in readInt () işlevi Big-endian biçimini beklemektedir.
İşte dört baytlık işaretsiz bir değeri (HexEdit tarafından 01 00 00 00 olarak görüntülendiği gibi) 1 değerine sahip bir tam sayıya okuyan bir örnek:

 // Declare an array of 4 shorts to hold the four unsigned bytes
 short[] tempShort = new short[4];
 for (int b = 0; b < 4; b++) {
    tempShort[b] = (short)dIStream.readUnsignedByte();           
 }
 int curVal = convToInt(tempShort);

 // Pass an array of four shorts which convert from LSB first 
 public int convToInt(short[] sb)
 {
   int answer = sb[0];
   answer += sb[1] << 8;
   answer += sb[2] << 16;
   answer += sb[3] << 24;
   return answer;        
 }

"Yukarıda belirtilen" neyi ifade eder? SO yanıtlarının görüntülenme sırası değişebilir.
LarsH

0

3
Bu, bayt kodu talimatlarının bitimiyle ilgilidir, çalışma zamanında verilerin bitimiyle değil.
kaya3

Oy veriyorum. Bu pasaj , benim ürettiklerimin tam tersi byte[] bbb = ByteBuffer.allocate(4).putFloat(0.42f).array();bir bytedizi C/C++üretti. Bu nedenle, Java'nın büyük dayanıklılığı çalışma zamanında verilerde bile etkili olur.
eigenfield
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.