将int与Java中的字符常量进行比较

时间:2013-02-22 19:36:44

标签: java comparison binary-data

我有一个二进制文件,它使用4个字符集来形成具有"含义"的整数。例如,4个字节'0005',等于整数形式的808464437。

我宁愿在我的Java代码中将它们表示为'0005'而不是808464437.我也不想设置final int V0005 = 808464437之类的常量。

在C ++中,我可以执行以下操作:

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
}

在Java中,我的问题是没有读取4个字节并将它们放入某种数据类型。我的问题是将一些数据类型与const char数组'0005'进行比较。

如何将int或其他形式与Java中的'0005'等const字符数组进行比较? 我需要尽可能高效地完成这项工作!

7 个答案:

答案 0 :(得分:4)

感谢您解答答案。

以下是如何将4个字节转换为int,然后可以将其与所讨论的int进行比较:

    int v0005 = ByteBuffer.wrap("0005".getBytes()).asIntBuffer().get();

遗憾的是,这是我能看到的唯一方式......可能没有您想要的那么高效,但也许这就是您所需要的。

我建议在其中一个类中将其中一些设置为“常量”,如下所示:

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();

然后打开V0005等,因为打开基本类型(int)是有效的。

答案 1 :(得分:3)

java中的char数组只不过是java中的String。您可以在Java7中使用switch-cases中的字符串,但我不知道比较的效率。

因为只有你char数组的最后一个元素似乎有意义,你可以用它做一个switch case。像

这样的东西
private static final int VERSION_INDEX = 3;

...
    char[] version = // get it somehow

    switch (version[VERSION_INDEX]) {
         case '5': 
            break;
         // etc
    }
...

修改 更多面向对象的版本。

  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);

很多代码hehe你会有一点预热成本,但如果你的程序执行多次,你将获得地图的效率:P

答案 2 :(得分:2)

从其他一些答案中得到一些答案(@marvo和@vikingsteve),我出来了:

public enum Version {

  V0005 {

    @Override
    public void doStuff() {
      // do something
    }
  },
  V0006 {
  @Override
    public void doStuff() {
    // do something else
    }

  };

private final int value;
private static final Map<Integer, Version> versions = new HashMap<>();

private Version() {
    final byte[] bytes = name().substring(1).getBytes(); //remove the initial 'V'
    this.value = ByteBuffer.wrap(bytes).asIntBuffer().get();
}

static {
    for (Version v : values()) {
        versions.put(v.value, v);
    }
}

public abstract void doStuff();


public Version valueOf(int i){
    return versions.get(i);
}
}

这提供了一种良好的面向对象方法,因为动作是用数据表示封装的。每个常量决定在调用doStuff时要做什么,避免切换客户端代码。用法是:

int code = readFromSomewhere();
Version.valueOf(i).doStuff();

valueOf方法在加载类时填充的地图中找到Version。我不知道这是否有效,因为int被设置为Integer只会在您分析时找到,其他一切是纯粹的猜测。 另请注意,在构造函数中为您计算整数值,因此您只需要使用正确的名称定义enums,它将自动完成。

答案 3 :(得分:1)

你在找value1.intValue() == value2.intValue()之类的东西吗?或者你可以输入演员。

char myChar = 'A';
int myInt = (int) myChar;

相同的手杖反过来。

int myInt = 6;
char myChar = (char) myInt;

答案 4 :(得分:1)

唯一的方法是字节[]到字符串转换非常低效。

switch (new String(version, "US-ASCII")) {
case "0005":
    break;
...
}

使用(哈希)地图会使其再次变快。

但我认为你不会满意这个解决方案。

答案 5 :(得分:1)

最有效的方法是使用整数 - 比如final int V0005 = 0x30303035(这里看到的几个不同想法的组合)是可管理的。 Java只是没有你想要的那种整数文字。

如果你真的想使用字符串,你需要首先读取字节数组中的字符,然后将其转换为字符串(默认字符集通常可以工作,因为它是ASCII的超集)。但是,效率会降低。

您可以编写一个函数来计算简单数字(如5)中的常量值,以获得更好的可读性,但这可能有点过分。

答案 6 :(得分:1)

鉴于这似乎是数据包中的版本字符串或其他东西,那么值的数量是有限的并且是合理的数量。所以它们可以封装在枚举中。枚举可以封装有效的代码,用于将输入数据中的四个字节转换为代表枚举。 (我执行转换的代码不一定是最有效的。也许,给定少量版本,一个不错的内部数组或内联到枚举的映射都可以。)

class enum Version {

    UNKNOWN(0),
    V0005(0x30303035),  // whatever the int value is
    V0006(0x30303036);

    private int id;
    private Version(int value) {
        id = value;
    }

    public static Version valueOf(int id) {
        for (Version version : values()) {
            if (version.getId() == id) {
                return version;
            }
        }
        return UNKNOWN;
    }

    public static Version valueOf(String sId) {
        return valueOf(computeId(sId));
    }

    public static int computeId(String sId) {
        // efficiently convert from your string to its int value
    }
}

然后在我的开关中:

String s = methodThatReadsFourChars(...);
switch (Version.valueOf(s)) {
case V0005 : doV0005Stuff(); break;
case V0006 : doV0006Stuff(); break;
default :
    throw new UnknownVersionException();