J'ai un fichier binaire qui utilise des ensembles de 4 caractères pour former des entiers qui ont "signification". Par exemple, les 4 octets Je préférerais les représenter dans mon code Java comme en C ++, je peux faire ce qui suit: P> '0005' code>, qui équivaut à 808464437 sous forme d'entier.
'0005' code> plutôt que 808464437. Je ne veux pas non plus définir des constantes comme
finale int v0005 = 808464437 code>. P>
fileStream->read((byte*) &version, 4); //Get the next bytes and stuff them into the uint32 version
switch (version) {
case '0005':
//do something
case '0006':
//do something
case '0007':
//do something
}
7 Réponses :
cherchez-vous quelque chose comme value1.IntValue () == Value2.IntValue () code>? Ou vous pouvez simplement taper de moulage.
int myInt = 6;
char myChar = (char) myInt;
C'est la bonne façon de taper, mais je pense qu'il a besoin de jeter dans les bits les plus hauts ...
Oui, un seul Char CODE> semble être capable de ne pas poser de problème, ce qui est en quelque sorte pourquoi je suis confus qu'un
char [] code> de taille 4 ne peut pas être distribué dans un
int code>. Je suppose que c'est juste à cause de la façon dont les matrices sont manipulées à Java.
Un tableau de charme en Java n'est rien de plus qu'un Parce que seul le dernier élément de votre tableau de caractères semble avoir une signification, vous pouvez faire un cas de commutation avec elle. Quelque chose comme p> edit fort>
Plus Version orientée objet. P> String code> en Java. Vous pouvez utiliser une chaîne dans des cas de commutation dans Java7, mais je ne connais pas l'efficacité des comparaisons.
public interface Command {
void execute();
}
public class Version {
private final Integer versionRepresentation;
private Version (Integer versionRep) {
this.versionRepresentation = versionRep;
}
public static Version get(char[] version) {
return new Version(Integer.valueOf(new String(version, "US-ASCII")));
}
@Override
public int hashCode() {
return this.versionRepresentation.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Version) {
Version that = (Version) obj;
return that.versionRepresentation.equals(this.versionRepresentation);
}
return false;
}
}
public class VersionOrientedCommandSet {
private final Command EMPTY_COMMAND = new Command() { public void execute() {}};
private final Map<Version, Command> versionOrientedCommands;
private class VersionOrientedCommandSet() {
this.versionOrientedCommands = new HashMap<Version, Command>();
}
public void add(Version version, Command command) {
this.versionOrientedCommands.put(version, command);
}
public void execute(Version version) throw CommandNotFoundException {
Command command = this.versionOrientedCommands.get(version);
if (command != null) {
command.execute();
} else {
throw new CommandNotFoundException("No command registered for version " + version);
}
}
}
// register you commands to VersionOrientedCommandSet
char[] versionChar = // got it from somewhere
Version version = Version.get(versionChar);
versionOrientedCommandSet.execute(version);
Jusqu'à présent, c'est la chose la plus proche que vous semblez être la seule personne à comprendre que 0x0005 code> n'est pas le même que
'0005' code>. Malheureusement, que se passe-t-il lorsque les versions deviennent
'0010' CODE>.
Ouais, j'ai vu un problème, mais c'est la seule solution rapide que j'ai vue à votre problème maintenant. Vous pouvez traiter la gamme de caractères et la transformer en int. Va éditer et le poster.
Je pensais que c'était fini et ce ne sera pas très efficace. Ce serait quelque chose de similaire à la solution VikingSteve.
Je vais écrire quelque chose pas si très efficace, mais vous pouvez utiliser plus tard afin que vous n'ayez pas besoin d'avoir un étui de commutation.
Fait, mais je ne pense pas que vous gagnez du temps avec ma solution hehe. Juste un peu plus d'objet orienté maintenant.
Merci d'avoir expliqué votre réponse.
Voici comment convertir de 4 octets à un Int, que vous pouvez ensuite comparer à l'INT en question: p>
public static final int V0005 = ByteBuffer.wrap("0005".getBytes()).asIntBuffer().get(); public static final int V0006 = ByteBuffer.wrap("0006".getBytes()).asIntBuffer().get(); public static final int V0007 = ByteBuffer.wrap("0007".getBytes()).asIntBuffer().get(); public static final int V0008 = ByteBuffer.wrap("0008".getBytes()).asIntBuffer().get();
'0005' est la représentation ASCII des 4 octets. Remarquez ce sont des personnages. J'utilise la petite commande d'octet d'Endian et je mappe au 808464437.
OK, je comprends. Je pense avoir une solution ... éditer ma réponse.
Je pense que vous êtes peut-être raison qu'il n'y ait pas d'autre choix que d'utiliser un finale statique int code>, même si ce n'est pas ce que je veux. Dans ce cas, j'utiliserais simplement l'approche 0x30303035 qu'une autre réponse a montré. +1
Le seul moyen serait un octet très inefficace [] à la conversion de chaîne.
switch (new String(version, "US-ASCII")) { case "0005": break; ... }
Alors, qu'est-ce que vous dites vraiment, c'est qu'il n'y a pas une telle chose en Cons-maquette en Java, comme '0005' code>? Et que je devrais utiliser un objet de chaîne pour le comparer à moins que je voulais stocker la valeur de dans un int dans un
final int code>?
Je ne semble pas avoir ce constructeur que vous montrez pour la chaîne. Êtes-vous sûr que c'est le format valide?
Il existe une chaîne de constructeur (données d'octet [], codage de chaîne) code>. Et oui, les 4 octets Char 'xxxx' (à l'origine par MacOS) n'ont pas de pendentif. Seuls les joueurs comme 0xcafafafababe (Java Magic Cookie).
C'est cool, mais je ne pense pas que ce soit efficace comme j'ai besoin. Je suppose que je vais aller avec l'après-vente de la finale statique. Merci pour l'information!
La manière la plus efficace serait de travailler avec des entiers - quelque chose comme finale int V0005 = 0x30303035 (une combinaison de quelques idées différentes vues ici) serait gérable. Java n'a tout simplement pas le genre de littéraux entier que vous recherchez. P>
Si vous voulez vraiment travailler avec des chaînes, vous devez d'abord lire les caractères d'un tableau d'octets, puis convertir en une chaîne (le charert par défaut fonctionne normalement car il s'agit d'un surset d'ASCII). Cependant, il serait moins efficace. P>
Vous pouvez écrire une fonction pour calculer les valeurs constantes des numéros simples (comme 5) pour une meilleure lisibilité, mais c'est probablement trop excédentaire. P>
Ce n'est pas une chaîne en C ++. C'est un tableau de caractères const qui évalue à un entier parce qu'il s'agit d'une séquence de 4 octets. C'est un littéral valide en C ++.
Je suis corrigé - il génère un avertissement mais fonctionne. J'ai édité la réponse.
Cela ne fonctionne pas si INT est 16 bits au lieu de 32 bits, car vous ne pouvez pas convenir à 4 octets en 2 octets bien sûr. Il y a donc un avertissement au cas où vous seriez sur une architecture de 16 bits - cela ne fait pas partie de la norme, mais est une pratique courante.
Je suis sur une arche de 64 bits, mais l'avertissement consiste à utiliser une "constante de caractère multi-caractères"
Jamais vu cet avertissement avant. Quel compilateur utilisez-vous?
GCC 4.6.3 (en cours d'exécution g ++ sans options spéciales)
Intéressant, je ne reçois pas cet avertissement. Utilisez également GCC / G ++ sur Debian 64 bits. Je pense que j'aime votre idée de les exprimer dans final int V0005 = 0x30303035 code> Formulaire le mieux car je ne trouve pas de solution utilisant la constante de caractère réelle
'0005' code>. Merci pour l'information.
étant donné que cela semble être une chaîne de version dans un paquet ou quelque chose, le nombre de valeurs est fini et d'un montant raisonnable. Afin qu'ils puissent être encapsulés dans un énumé. L'ENUM peut encapsuler un code efficace pour convertir des quatre octets dans les données d'entrée à l'énumération représentative. (Mon code pour effectuer cette conversion n'est pas nécessairement le plus efficace. Peut-être, étant donné un petit nombre de versions, un joli tableau interne ou une cartographie d'INTS à Enums fonctionnerait.)
String s = methodThatReadsFourChars(...); switch (Version.valueOf(s)) { case V0005 : doV0005Stuff(); break; case V0006 : doV0006Stuff(); break; default : throw new UnknownVersionException();
Vous pouvez améliorer cette méthode d'ajout d'un Dostuff () code> sur l'ENUM directement, comme: `v0005 (0x803030d2) {VOID Dostuff () {... ...}}` Pour que vous encapsulez l'action avec la valeur . De cette façon, vous pouvez vous enregistrer le commutateur et appeler simplement
version.valueof (s) .Dostuff () code>
J'aimerais voir un exemple de cela. Je ne suis pas familier avec cette syntaxe.
J'ai ajouté une réponse avec un exemple de cela, vérifiez-le si vous êtes intéressé.
Obtenir un peu de certaines des autres réponses (@marvo et @vingingsteve), je suis sorti avec ceci:
int code = readFromSomewhere(); Version.valueOf(i).doStuff();
J'aime aussi la solution de la carte. J'ai pensé à ajouter ça à ma réponse mais j'ai été paresseux. N'aurait pas fait cela aussi élégamment que votre réponse, non plus.
Le fait qu'il fonctionne du nom de l'énum est magnifique.
"Je préférerais les représenter dans mon code Java comme" 0005 "plutôt que 808464437. Je ne veux pas non plus mettre des constantes comme finale int V0005 = 808464437." Soit ceux-ci sont des phrases contradictoires ou je ne comprends pas ce que vous voulez dire. Ou peut-être avez-vous besoin de regarder Java enums?
Le seul moyen efficace est d'utiliser un int, 0x30303035 ou peut-être 0x0005.
@Joopeggen '0005'! = 0x0005. '0005' est ASCII.
Bien que 0x30 == '0' et si seulement avoir des chiffres, effectuez un
Court ConvertBleTESTOBCD (octet []) code>
'0005' est un int qui est équivalent à:
0x30 << 24 + 0x30 << 16 + 0x30 << 8 + 0x35 Code>
@Marvo Pouvez-vous expliquer à propos de Enums? Merci.
docs.oracle.com/javase/tatuly/java/javaoo/enum. HTML
@Marvo, qui ne semble pas que ce soit beaucoup différent de la définition
finale statique int v0005 = 808464437 code>. Au lieu de cela, j'aurais une énumération comme
publique énumversion {v0005 (808464437)} code>?
Peut-être. Je n'étais pas clair sur ce que tu voulais quand je l'ai mentionné. Mais Java Enums fournit une certaine encapsulation des données et fournit une certaine logique à utiliser. Personnellement, je ne suis pas enthousiasmé par l'utilisation des littéraux de caractère dans mon code comme votre proposition, alors j'étais personnellement à la recherche d'une telle solution.
Si vous utilisez ceci comme faisant partie de quelque chose (paquets, peut-être), vous auriez un nombre fini de versions, et quelque chose comme Enums fonctionnerait bien pour cela.
Ce sont un format de fichier archaïque utilisé par Sony. Je ne sais pas que toutes les versions existent. J'ai jusqu'à présent seulement rencontré "0005" et "0006". Le type de fichier est défini par les quatre premiers octets et est égal à la "arborescence". Si vous êtes familier, oui, il s'agit de l'archive des fichiers Tre Sony utilisée pour les patchs, ce que j'ai analysé avec succès en C ++. Juste essayer de faire un équivalent Java. Je vais juste rester avec
finale statique publique Int code> après. Merci tout le monde.