J'essaie de convertir un octet signé en non signé. Le problème est que les données que je reçois ne sont pas signées et que Java ne prend pas en charge l'octet non signé, donc quand il lit les données, il les traite comme signées.
J'ai essayé de le convertir par la solution suivante que j'ai obtenue de Stack Overflow.
public static int unsignedToBytes(byte a)
{
int b = a & 0xFF;
return b;
}
Mais quand il est à nouveau converti en octet, j'obtiens les mêmes données signées. J'essaie d'utiliser ces données comme paramètre d'une fonction de Java qui n'accepte qu'un octet comme paramètre, je ne peux donc pas utiliser d'autre type de données. Comment puis-je résoudre ce problème?
Réponses:
Je ne suis pas sûr de comprendre votre question.
Je viens d'essayer ceci et pour l'octet -12 (valeur signée), il a renvoyé l'entier 244 (équivalent à la valeur d'octet non signé mais tapé comme un
int
):public static int unsignedToBytes(byte b) { return b & 0xFF; } public static void main(String[] args) { System.out.println(unsignedToBytes((byte) -12)); }
Est-ce ce que tu veux faire?
Java ne permet pas d'exprimer 244 sous forme de
byte
valeur, comme le ferait C. Pour exprimer des entiers positifs au-dessus deByte.MAX_VALUE
(127), vous devez utiliser un type d'intégrale différent, commeshort
,int
oulong
.la source
byte b = (byte)unsignedToBytes((byte) -12);
essayez maintenant d'imprimer bLe fait que les primitives soient signées en Java n'a pas d'importance pour la façon dont elles sont représentées en mémoire / transit - un octet est simplement 8 bits et que vous l'interprétiez comme une plage signée ou non, c'est à vous de décider. Il n'y a pas de drapeau magique pour dire "ceci est signé" ou "ceci n'est pas signé".
Lorsque les primitives sont signées, le compilateur Java vous empêchera d'attribuer une valeur supérieure à +127 à un octet (ou inférieure à -128). Cependant, rien ne vous empêche de baisser un int (ou un court) pour y parvenir:
int i = 200; // 0000 0000 0000 0000 0000 0000 1100 1000 (200) byte b = (byte) 200; // 1100 1000 (-56 by Java specification, 200 by convention) /* * Will print a negative int -56 because upcasting byte to int does * so called "sign extension" which yields those bits: * 1111 1111 1111 1111 1111 1111 1100 1000 (-56) * * But you could still choose to interpret this as +200. */ System.out.println(b); // "-56" /* * Will print a positive int 200 because bitwise AND with 0xFF will * zero all the 24 most significant bits that: * a) were added during upcasting to int which took place silently * just before evaluating the bitwise AND operator. * So the `b & 0xFF` is equivalent with `((int) b) & 0xFF`. * b) were set to 1s because of "sign extension" during the upcasting * * 1111 1111 1111 1111 1111 1111 1100 1000 (the int) * & * 0000 0000 0000 0000 0000 0000 1111 1111 (the 0xFF) * ======================================= * 0000 0000 0000 0000 0000 0000 1100 1000 (200) */ System.out.println(b & 0xFF); // "200" /* * You would typically do this *within* the method that expected an * unsigned byte and the advantage is you apply `0xFF` only once * and than you use the `unsignedByte` variable in all your bitwise * operations. * * You could use any integer type longer than `byte` for the `unsignedByte` variable, * i.e. `short`, `int`, `long` and even `char`, but during bitwise operations * it would get casted to `int` anyway. */ void printUnsignedByte(byte b) { int unsignedByte = b & 0xFF; System.out.println(unsignedByte); // "200" }
la source
Guide complet pour travailler avec des octets non signés en Java:
Octet non signé en Java
(Source de cette réponse.)
Le langage Java ne fournit rien de tel que le
unsigned
mot - clé. Abyte
selon la spécification de la langue représente une valeur comprise entre -128 - 127. Par exemple, si unbyte
est castéeint
Java interprétera le premier bit comme le signe et l' utilisation extension de signe .Cela étant dit, rien ne vous empêche de visualiser
byte
simplement 8 bits et d'interpréter ces bits comme une valeur comprise entre 0 et 255. Gardez simplement à l'esprit que vous ne pouvez rien faire pour forcer votre interprétation sur la méthode de quelqu'un d'autre. Si une méthode accepte abyte
, alors cette méthode accepte une valeur entre −128 et 127 sauf indication contraire explicite.Voici quelques conversions / manipulations utiles pour votre commodité:
Conversions vers / depuis int
// From int to unsigned byte int i = 200; // some value between 0 and 255 byte b = (byte) i; // 8 bits representing that value
// From unsigned byte to int byte b = 123; // 8 bits representing a value between 0 and 255 int i = b & 0xFF; // an int representing the same value
(Ou, si vous utilisez Java 8+, utilisez
Byte.toUnsignedInt
.)Analyse / formatage
Le meilleur moyen est d'utiliser les conversions ci-dessus:
// Parse an unsigned byte byte b = (byte) Integer.parseInt("200");
// Print an unsigned byte System.out.println("Value of my unsigned byte: " + (b & 0xFF));
Arithmétique
La représentation à 2 compléments "fonctionne juste" pour l'addition, la soustraction et la multiplication:
// two unsigned bytes byte b1 = (byte) 200; byte b2 = (byte) 15; byte sum = (byte) (b1 + b2); // 215 byte diff = (byte) (b1 - b2); // 185 byte prod = (byte) (b2 * b2); // 225
La division nécessite une conversion manuelle des opérandes:
byte ratio = (byte) ((b1 & 0xFF) / (b2 & 0xFF));
la source
Il n'y a pas d'octets primitifs non signés en Java. La chose habituelle est de le convertir en un type plus grand:
int anUnsignedByte = (int) aSignedByte & 0xff;
la source
Je pense que les autres réponses ont couvert la représentation de la mémoire et la façon dont vous les gérez dépend du contexte dans lequel vous prévoyez de l'utiliser. J'ajouterai que Java 8 a ajouté un support pour traiter les types non signés . Dans ce cas, vous pouvez utiliser
Byte.toUnsignedInt
int unsignedInt = Byte.toUnsignedInt(myByte);
la source
Une note latérale, si vous voulez l'imprimer, vous pouvez simplement dire
byte b = 255; System.out.println((b < 0 ? 256 + b : b));
la source
println(b & 0xff)
est assezBien que cela puisse sembler ennuyeux (venant de C) que Java n'inclue pas d'octet non signé dans le langage, ce n'est vraiment pas grave car une simple opération "b & 0xFF" donne la valeur non signée pour l'octet (signé) b dans le (rare) situations où il est réellement nécessaire. Les bits ne changent pas réellement - juste l'interprétation (ce qui n'est important que lorsque vous effectuez par exemple des opérations mathématiques sur les valeurs).
la source
x & 0xFF
partout où vous en avez besoin, soit vous répétez quelque chose commebehaveLikeAnUnsignedByte(x)
partout. Ceci est nécessaire pour chaque endroit où vous utilisez une valeur d'octet ou un tableau d'octets qui doit être non signé, il n'y a aucun moyen concevable d'éviter cette répétition. Vous ne pouvez pas écrire l'implémentation d'un protocole qui lit et écrit des valeurs d'octet avec une seule référence à une variable d'octet. Votre vision simpliste pourrait expliquer pourquoi ils ne se sont jamais souciés de le réparer.Si vous pensez que vous cherchez quelque chose comme ça.
public static char toUnsigned(byte b) { return (char) (b >= 0 ? b : 256 + b); }
la source
Adamski a fourni la meilleure réponse, mais elle n'est pas tout à fait complète, alors lisez sa réponse, car elle explique les détails que je ne suis pas.
Si vous avez une fonction système qui nécessite qu'un octet non signé lui soit transmis, vous pouvez transmettre un octet signé car il le traitera automatiquement comme un octet non signé.
Donc, si une fonction système nécessite quatre octets, par exemple, 192 168 0 1 en tant qu'octets non signés, vous pouvez passer -64-88 0 1, et la fonction fonctionnera toujours, car le fait de les passer à la fonction les dé-signera .
Cependant, il est peu probable que vous rencontriez ce problème car les fonctions système sont cachées derrière des classes pour une compatibilité multiplateforme, bien que certaines des méthodes de lecture java.io renvoient des octets non mesurés sous forme d'int.
Si vous voulez que cela fonctionne, essayez d'écrire des octets signés dans un fichier et de les relire en tant qu'octets non signés.
la source
Vous pouvez aussi:
public static int unsignedToBytes(byte a) { return (int) ( ( a << 24) >>> 24); }
Explication:
Disons
a = (byte) 133;
En mémoire, il est stocké sous le nom: "1000 0101" (0x85 en hexadécimal)
Donc sa représentation traduit unsigned = 133, signé = -123 (comme complément à 2)
Lorsque le décalage gauche est effectué de 24 bits vers la gauche, le résultat est maintenant un entier de 4 octets qui est représenté par:
"10000101 00000000 00000000 00000000" (ou "0x85000000" en hexadécimal)
ensuite nous avons
et il décale à nouveau sur les 24 bits de droite mais se remplit de zéros non significatifs. Il en résulte donc:
"00000000 00000000 00000000 10000101" (ou "0x00000085" en hexadécimal)
et c'est la représentation non signée qui vaut 133.
Si vous essayez de lancer un cast,
a = (int) a;
ce qui se passerait, c'est qu'il conserve la représentation du complément à 2 de byte et le stocke sous la forme int également en tant que complément à 2:(entier) "10000101" ---> "11111111 11111111 11111111 10000101"
Et cela se traduit par: -123
la source
java.lang.Byte.toUnsignedInt(byte value)
. Et si vous n'utilisez pas encore Java 8, mettez à niveau dès que possible. Java 7 et les versions antérieures sont en fin de vie.Ce n'est pas sensiblement différent d'une fonction acceptant un entier auquel vous voulez passer une valeur supérieure à 2 ^ 32-1.
Cela semble dépendre de la façon dont la fonction est définie et documentée; Je vois trois possibilités:
Il peut explicitement documenter que la fonction traite l'octet comme une valeur non signée, auquel cas la fonction devrait probablement faire ce que vous attendez mais semblerait être mal implémentée. Pour le cas des nombres entiers, la fonction déclarerait probablement le paramètre comme un entier non signé, mais ce n'est pas possible pour le cas des octets.
Il peut documenter que la valeur de cet argument doit être supérieure (ou peut-être égale à) zéro, auquel cas vous utilisez mal la fonction (en passant un paramètre hors limites), en vous attendez à ce qu'elle fasse plus que ce pour quoi elle a été conçue faire. Avec un certain niveau de prise en charge du débogage, vous pouvez vous attendre à ce que la fonction lève une exception ou échoue une assertion.
La documentation peut ne rien dire, auquel cas un paramètre négatif est, eh bien, un paramètre négatif et si cela a une signification dépend de ce que fait la fonction. Si cela n'a pas de sens, alors peut-être que la fonction devrait vraiment être définie / documentée comme (2). Si cela est significatif d'une manière non évidente (par exemple, des valeurs non négatives sont utilisées pour indexer dans un tableau, et des valeurs négatives sont utilisées pour indexer à partir de la fin du tableau donc -1 signifie le dernier élément), la documentation devrait dire ce qu'elle signifie et je m'attendrais à ce que ce ne soit pas ce que vous voulez qu'il fasse de toute façon.
la source
Il n'y a pas d'octet non signé en Java, mais si vous voulez afficher un octet, vous pouvez faire,
int myInt = 144; byte myByte = (byte) myInt; char myChar = (char) (myByte & 0xFF); System.out.println("myChar :" + Integer.toHexString(myChar));
Production:
myChar : 90
Pour plus d'informations, veuillez vérifier, Comment afficher une valeur hexadécimale / octet en Java .
la source
java.lang.Byte.toUnsignedInt(byte value);
existe pour cela.Si vous avez une fonction qui doit recevoir un octet signé, que voulez-vous qu'elle fasse si vous passez un octet non signé?
Pourquoi ne pouvez-vous utiliser aucun autre type de données?
Exceptionnellement, vous pouvez utiliser un octet comme un octet non signé avec des traductions simples ou sans traduction. Tout dépend de la manière dont il est utilisé. Vous auriez besoin de clarifier ce que vous voulez en faire.
la source
Oui et non. J'ai fouillé avec ce problème. Comme je comprends ceci:
Le fait est que java a signé des entiers -128 à 127 .. Il est possible de présenter un unsigned en java avec:
public static int toUnsignedInt(byte x) { return ((int) x) & 0xff; }
Si, par exemple, vous ajoutez -12 numéro signé pour ne pas être signé, vous obtenez 244. Mais vous pouvez à nouveau utiliser ce numéro dans signé, il doit être redéposé à signé et il sera à nouveau -12.
Si vous essayez d'ajouter 244 à l'octet java, vous obtiendrez outOfIndexException.
À votre santé..
la source
java.lang.Byte.toUnsignedInt(byte value);
existe pour cela.Conformément aux limitations de Java, l'octet non signé est presque impossible dans le format de type de données actuel. Vous pouvez choisir d'autres bibliothèques d'une autre langue pour ce que vous implémentez, puis vous pouvez les appeler en utilisant JNI .
la source
Si vous voulez des octets non signés en Java, soustrayez simplement 256 du nombre qui vous intéresse. Cela produira un complément à deux avec une valeur négative, qui est le nombre souhaité en octets non signés.
Exemple:
int speed = 255; //Integer with the desired byte value byte speed_unsigned = (byte)(speed-256); //This will be represented in two's complement so its binary value will be 1111 1111 //which is the unsigned byte we desire.
Vous devez utiliser de tels hacks sales lorsque vous utilisez leJOS pour programmer la brique NXT .
la source
speed_unsigned
est signée. Imprimez-le et voyez. (Et le- 256
ne fait rien ici.)