图书ISBN编码概述及java工具类校验

前言:系统用图书的ISBN编码作为查询条件,由于套装书或其它情况导致ISBN编码可能重复,针对这种情况图书馆自定义了一批ISBN编码,因此需要区分是否为自定义的ISBN编码。

由于ISBN编码有一套对应的生成规则,并且各个图书馆的自定义编码不相同,所以准备利用ISBN编码生成规则使用java程序处理

直接上代码有兴趣的可以看看下边的内容:

package com.isbn.core.common.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.UnknownFormatConversionException;
import java.util.regex.Pattern;

/**
 * @author ruqiang
 * @version 1.0.0
 * @className: IsbnUtil
 * @Description ISBN编码校验工具类
 * @create 2019/11/26
 */
@Slf4j
public class IsbnUtil {
    /**
     * 所需值
     */
    private static final String FORMAT_TEN = "^[0-9]{%s}[0-9X]{1}$";
    private static final String FORMAT_THIRTEEN = "^[0-9]{%s}$";
    private static final Integer ZERO = 0;
    private static final Integer ONE = 1;
    private static final Integer TWO = 2;
    private static final Integer THREE = 3;
    private static final Integer NINE = 9;
    private static final Integer TEN = 10;
    private static final Integer ELEVEN = 11;
    private static final Integer THIRTEEN = 13;
    private static final String X = "X";


    public static Boolean checkIsbn(String isbn) {
        //获取计算加权和所需要的值
        String substring = isbn.substring(ZERO, isbn.length() - ONE);
        //加权和S
        Integer s = ZERO;
        //由于ISBN,10位和13位校验方法不相同,先进行区分
        if (Pattern.matches(String.format(FORMAT_TEN, NINE), isbn)) {
            //获取比较值并转化为Integer
            Integer comparison = null;
            String comparisonStr = null;
            try {
                comparison = Integer.parseInt(isbn.substring(isbn.length() - 1));
            } catch (NumberFormatException e) {
                comparisonStr = X;
            }
            //转化为Integer数组
            Integer[] isbnArr;
            try {
                isbnArr = (Integer[]) ConvertUtils.convert(substring.split(""), Integer.class);
            } catch (UnknownFormatConversionException e) {
                log.error("ISBN编码转化Integer数组失败:{}", e);
                return false;
            }
            //递减值j
            Integer j = TEN;
            //计算加权和:即将ISBN号码前9位数字分别乘以10, 9, 8, 7, 6, 5, 4, 3, 2,然将它们相加,得到加权和
            for (int i = ZERO; i < isbnArr.length; i++, j--) {
                s = isbnArr[i] * j + s;
            }
            //取余数M
            Integer m = s % ELEVEN;
            //计算校验码N
            Integer N = ELEVEN - m;
            if (StringUtils.isNotEmpty(comparisonStr)) {
                return N.equals(TEN) ? true : false;
            } else {
                return ONE.equals(N) ? ZERO.equals(comparison) ? true : false : comparison.equals(N) ? true : false;
            }
        }
        if (Pattern.matches(String.format(FORMAT_THIRTEEN, THIRTEEN), isbn)) {
            //获取比较值并转化为Integer
            Integer comparison = Integer.parseInt(isbn.substring(isbn.length() - 1));
            //转化为Integer数组
            Integer[] isbnArr = (Integer[]) ConvertUtils.convert(substring.split(""), Integer.class);
            //计算加权和:用1分别乘ISBN的前12位中的奇数位,用3乘以偶数位,然后将两者相加,即得到加权和
            for (int i = ZERO; i < isbnArr.length; i++) {
                s=i%TWO==ZERO?isbnArr[i]*ONE+s:isbnArr[i]*THREE+s;
            }
            //取余数M
            Integer m = s % TEN;
            //计算校验码N
            Integer N = TEN - m;
            return N.equals(TEN) ? comparison.equals(ZERO) ? true : false : comparison.equals(N) ? true : false;
        }
        return false;
    }

    public static void main(String[] args) {
        System.out.println(String.format("10位测试结果:%s", checkIsbn("7309045475")));
        System.out.println(String.format("13位测试结果:%s", checkIsbn("9787115275790")));
    }
}

计算方式

ISBN书号校验码的计算方法
  一、10位书号校验码的计算方法
  10位书号校验码只有一位,从0到10,10由X代替。其计算方法为:
  第一步 计算加权和:即将ISBN号码前9位数字分别乘以10, 9, 8, 7, 6, 5, 4, 3, 2,然将它们相加,得到加权和(设该加权和为S);
  第二步 计算余数:即将第一步得到的和(S)除以11,取其余数(设该余数为M);
  第三步 计算校验码:用11减去第二步得到的余数(M),所得之差就是计算校验码的基础(N)。
  【说明】如果所得之差N为10,校验码是字母X;如果所得之差N为1,校验码是数字0;如果所得之差N为其他数字,则校验码就是该数字。
  【举例】假设某ISBN号码前9位是:7-309-04547,其校验码计算方法如下:
  第一步:计算加权和(S):S=7×10+3×9+0×8+9×7+0×6+4×5+5×4+4×3+7×2 = 226
  第二步:计算余数(M):M = 226÷11余6
  第三步:计算校验码(N):N = 11 ? 6 = 5
  校验码为5。
  二、13位书号校验码的计算方法
  13位ISBN的最后一位校验位的加权算法与10位ISBN的算法不同。具体计算方法为:
  第一步 计算加权和:用1分别乘ISBN的前12位中的奇数位,用3乘以偶数位,然后将两者相加,即得到加权和(设该加权和为S);
  第二步 计算余数:即将第一步得到的加权和除以10,取其余数(设该余数为M);
  第三步 计算校验码:即用10减去第二步得到的余数,所得之差就是计算校验码的基础(N)。
  【说明】如果所得之差N为10,则校验码取0。
  【举例】假设某13位ISBN号码前12位是:987-7-309-04547
  第一步:计算加权和(S):S=9×1+8×3+7×1+7×3+3×1+0×3+9×1+0×3+4×1+5×3+4×1+7×3 = 117
  第二步:计算余数(M):M = 117÷10 余数为7
  第三步:计算校验码(N):N = 10 ? 7 = 3
  故本书的第13位ISBN的校验码是3。

ISBN图书编码简介:

国际标准书号(International Standard Book Number),简称ISBN,是专门为识别图书等文献而设计的国际编号。
采用ISBN编码系统的出版物有:图书、小册子、缩微出版物、盲文印刷品等。
2007年1月1日前,ISBN由10位数字组成,分四个部分:

  1. 组号(国家、地区、语言的代号)
  2. 出版者号
  3. 书序号
  4. 检验码

2007年1月1日起,实行新版ISBN,新版ISBN由13位数字组成,分为5段,即在原来的10位数字前加上3位EAN(欧洲商品编号)图书产品代码“978”。在联机书目中ISBN可以作为一个检索字段,从而为用户增加了一种检索途径。

旧版,即2007年1月1日前

第一组号码段,组号(国家、地区、语言的代号)

最短的是一位数字,最长的达五位数字如不丹:99936。

代码 含义 代表国家
0和1 代表英语 英国、美国、澳大利亚、加拿大等
2 代表法语 法国、瑞士、比利时等
3 代表德语 德国、奥地利等
4 代表日本 日本
5 代表俄语 俄罗斯
7 代表中国 中国

图书ISBN编码概述及java工具类校验_第1张图片

第二组号码段,是出版社代码,由其隶属的国家或地区ISBN中心分配,允许取值范围为2-5位数字。

第三组号码是书序码,由出版社自己给出,书序号是定长的数字9,减去组号、出版社代码所占的位数,就是书序码的位数。最短的一位,最长的六位。

第四组号码段,是校验码,其数值由前九位数字依次以10~2加权之和并以11为模计算得到。

校验方式

将ISBN前九位数字依序分别乘以从10到2的数目,将其乘积相加,总和用11去除;若无余数则检查号码为“0”;若有余数,则以11减去余数,所得差数即为检查号,若差数为10,则以代表罗马数字10的“X”来表示。

新版,即2007年1月1日起,在最前面多了一组EAN

EAN:European Article Number(欧洲商品号),国际标准书号中心于2004年决定在国际标准书号的基础上再添加一组三位数字在最前,即将现有的10位书号前面加上前缀号“978”或“979”及重新计算稽核号,以转换为新的13位格式,与13位欧洲商品编码相同。该计划于2007年1月1日实施。

转化:

ISBN-10与ISBN-13之间的相互转换算法
1.从ISBN-10转换为ISBN-13
下面以ISBN 7-302-12260-1为例,介绍从ISBN-10转换为ISBN-13的具体步骤。
(1)从ISBN-10中去除校验码(即最后一位),得到一个9位数字7-302-12260
(2)在这个9位数字之前添加前缀978,得到12位数字978-7-302-12260
(3)使用模为10的校验码计算方法重新计算校验码。使用从第2步得到的12位数字,每位乘以相应的加权因子。将结果相加,得和为81将这个和除以模数10,得余数为1,用标准模数减去余数就可以得出校验码。这里10减1得9把校验码添加到由第2步生成的12位数字后,于是,转换成的ISBN-13就是978-7-302-12260-9
具体算法如下:91+73+81+73+31+03+21+13+21+23+61+03=81
81/10=8,余数为1,10-1=9
注意:这个公式有一个例外,当余数为0时,校验码即为0。
2.从以978打头的ISBN-13转换成ISBN-10
  注意:只有前级为978的ISBN-13才有对应的ISBN-10。
下面以转换成的ISBN 978-7-302-12260-9为例,转换回ISBN-10。
(1)从ISBN-13中删除前缀978和校验码,得到一个9位数字,即为7-302-12260
(2)重新计算校验码。使用从上面第1步中得到的9位数字,将每位数字与表2中相应的加权因子相乘。
将乘积相加,得和为153将这个和除以11,得余数为10,用11减去这个余数,结果就是校验码。这里,11减去10得1,把校验码添加到从第1步中得到的9位数字的后面,于是,转换成的ISBN-10就是7-302-12260-1
具体算法如下:710+39+08+27+16+25+24+63+0*2=153
153/11=13,余数为10,11-10=1
  注意:如果校验码的值为10,则应用罗马数字X表示

你可能感兴趣的:(java)