解码EAN-128(以及其他GS1条形码)

5

有很多组件可以创建/解析条形码图像,但我找不到一个库来解析EAN-128条形码字符串并简单地给我一个Java-POJO对象,从中我可以获取EAN-128组(如果它们包含在条形码中)。

示例伪代码:

EAN128Pojo pojo = EAN128Pojo.parse(some string got from scanner);
Date dueDate = pojo.getDueDate();

或者

Object dueDate = pojo.get("12" /*application identifier for due date*/);

有没有任何库能够做到这一点?
2个回答

7

我不知道有没有相关的内容,Google CodeSearch 也没有找到:http://www.google.com/codesearch?q=getAdditionalProductIdentification

不过,自己编写并不难。以下代码只花费了我不到一个小时:

package so5685964;

import java.util.Map;

import org.joda.time.DateMidnight;

import com.google.common.collect.Maps;

public class GS1Code128Data {

  /** Maps the AI to the corresponding data from the barcode. */
  private final Map<String, String> data = Maps.newHashMap();

  private static final Map<String, AII> aiinfo = Maps.newHashMap();

  static class AII {
    final int minLength;
    final int maxLength;

    public AII(String id, int minLength, int maxLength) {
      this.minLength = minLength;
      this.maxLength = maxLength;
    }
  }

  private static void ai(String id, int minLength, int maxLength) {
    aiinfo.put(id, new AII(id, minLength, maxLength));
  }

  private static void ai(String id, int length) {
    aiinfo.put(id, new AII(id, length, length));
  }

  static {
    ai("00", 18, 18);
    ai("01", 14);
    ai("02", 14);
    ai("10", 1, 20);
    ai("11", 6);
    ai("12", 6);
    // TODO: continue according to http://en.wikipedia.org/wiki/GS1-128
  }

  /**
   * Decodes a Unicode string from a Code128-like encoding.
   *
   * @param fnc1 The character that represents FNC1.
   */
  public GS1Code128Data(String s, char fnc1) {
    StringBuilder ai = new StringBuilder();
    int index = 0;
    while (index < s.length()) {
      ai.append(s.charAt(index++));
      AII info = aiinfo.get(ai.toString());
      if (info != null) {
        StringBuilder value = new StringBuilder();
        for (int i = 0; i < info.maxLength && index < s.length(); i++) {
          char c = s.charAt(index++);
          if (c == fnc1) {
            break;
          }
          value.append(c);
        }
        if (value.length() < info.minLength) {
          throw new IllegalArgumentException("Short field for AI \"" + ai + "\": \"" + value + "\".");
        }
        data.put(ai.toString(), value.toString());
        ai.setLength(0);
      }
    }
    if (ai.length() > 0) {
      throw new IllegalArgumentException("Unknown AI \"" + ai + "\".");
    }
  }

  private static DateMidnight asDate(String s) {
    if (s == null) {
      return null;
    }
    String century = s.compareTo("500000") < 0 ? "20" : "19";
    return new DateMidnight(century + s);
  }

  public DateMidnight getDueDate() {
    return asDate(data.get("12"));
  }
}

以下是一些示例代码:

package so5685964;

public class BarcodeDemo {

  public static void main(String[] args) {
    String barcode = "12110416";

    GS1Code128Data data = new GS1Code128Data(barcode, '\f');

    System.out.println(data.getDueDate());
  }
}

当您假设输入已经是一个String时,请注意编码问题。 FNC1代码没有相应的Unicode代码点,因此必须以其他方式进行编码。


@roland-illig 非常感谢,这对我非常有帮助。但是要知道并不是所有的条形码扫描器都提供FNC1字符,所以我们需要一个更复杂的算法。barcode4j提供的模板(http://barcode4j.cvs.sourceforge.net/viewvc/barcode4j/barcode4j/src/java/org/krysalis/barcode4j/impl/code128/EAN128AIs.properties?revision=1.1&view=markup)可能是一个很好的起点。但是因为我相信肯定有类似的库存在,所以我不想重复造轮子,想在这里问一下。 显然,没有这样的库存在。 - archangle
我不知道你的代码是否有效(我会尝试),但我只是想感谢你抽出时间编写它。 - JDenais
我不知道你的代码是否有效(我会尝试),但我只是想感谢你抽出时间编写它。 - JDenais

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接