marc数据分为三部分:标识区、目次区、数据记录区。详情请仔细查找资料,本文不多介绍,直接上代码
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class JMarc { static Map<String, String> map=new HashMap<String, String>();//解析集合 public Map<String, String> jxMarc(String marc){ originalMap(); String m=marc.split("\\u001D")[0]; String s1=m.split("\\u001E")[0]; String s2=(String) s1.subSequence(5, 6); if(s2.equals("d")){ System.err.println("检测到数据已废除!错误发生在:标识区状态为‘d’"); return map; } int s3=Integer.parseInt(s1.substring(12,17)); String s4=s1.substring(24,s3-1); if(s4.length()%12!=0) { System.err.println("检测到数据格式错误!错误发生在:地址目次区"); return map; } List<String> list1=new ArrayList<String>();//目次区集合 for(int i=0;i<s4.length()/12;i++) { list1.add( s4.substring( 12*i, 12*(i+1) ) ); } int k=m.split("\\u001E").length-1;//第一个数组是标识+目次区 String[] sz=m.split("\\u001E"); List<String> list2=new ArrayList<String>();//记录区集合 for(int i =0;i<k;i++) { list2.add(sz[i+1]); } if(list1.size()!=list2.size()) { System.err.println("检测到目次区与记录区数量不匹配!错误发生在:目次区或数据区," + "目次区:"+list1.size()+"组,记录区:"+list2.size()+"条"); return map; } //匹配 for(int i=0;i<list1.size();i++) { matchingMap(list1.get(i).substring(0,3),list2.get(i)); } return map; } //初始化map public Map<String, String> originalMap() { map.put("isbn", null);//ISBN map.put("title", null);//标题 map.put("divisionname", null);//分册名 map.put("divisionnumber", null);//分册号 map.put("author", null);//作者 map.put("oneprice", null);//价格 map.put("size", null);//尺寸 map.put("page", null);//页数、x册 map.put("published", null);//出版地 map.put("clc", null);//中图分类号 map.put("press", null);//出版社 map.put("pubdate", null);//出版时间 map.put("language", null);//语言 map.put("type", null);//主题 map.put("Remarks", null);//内容、简介 return map; } //匹配并赋值map public void matchingMap(String key1,String key2) { switch (key1) { case "010": if( key2.split("\\u001Fa").length>1 ) {//isbn String f1=key2.split("\\u001Fa")[1]; String f2=f1.split("\\u001F")[0]; map.put("isbn", f2); } if(key2.split("\\u001Fd").length>1) {//价格 String f1=key2.split("\\u001Fd")[1]; String f2=f1.split("\\u001F")[0]; map.put("oneprice", f2); } break; case "101": if(key2.split("\\u001Fa").length>1) {//语言 String f1=key2.split("\\u001Fa")[1]; String f2=f1.split("\\u001F")[0]; map.put("language", f2); } break; case "200": if(key2.split("\\u001Ff").length>1) {//作者 String f1=key2.split("\\u001Ff")[1]; String f2=f1.split("\\u001F")[0]; map.put("author", f2); } if(key2.split("\\u001Fa").length>1) {//题名 String f1=key2.split("\\u001Fa")[1]; String f2=f1.split("\\u001F")[0]; map.put("title", f2); } if(key2.split("\\u001Fh").length>1) {//分册号***可能不止一个'@h' String f1=key2.split("\\u001Fh")[1]; String f2=f1.split("\\u001F")[0]; map.put("divisionnumber", f2); } if(key2.split("\\u001Fi").length>1) {//分册名***可能不止一个'@i' String f1=key2.split("\\u001Fi")[1]; String f2=f1.split("\\u001F")[0]; map.put("divisionname", f2); } break; case "210": if(key2.split("\\u001Fa").length>1) {//出版地 String f1=key2.split("\\u001Fa")[1]; String f2=f1.split("\\u001F")[0]; map.put("published", f2); } if(key2.split("\\u001Fc").length>1) {//出版社 String f1=key2.split("\\u001Fc")[1]; String f2=f1.split("\\u001F")[0]; map.put("press", f2); } if(key2.split("\\u001Fd").length>1) {//出版时间 String f1=key2.split("\\u001Fd")[1]; String f2=f1.split("\\u001F")[0]; map.put("pubdate",f2); } break; case "215": if(key2.split("\\u001Fd").length>1) {//尺寸 String f1=key2.split("\\u001Fd")[1]; String f2=f1.split("\\u001F")[0]; map.put("size", f2); } if(key2.split("\\u001Fa").length>1) {//页数***可能是层数 String f1=key2.split("\\u001Fa")[1]; String f2=f1.split("\\u001F")[0]; map.put("page", f2); } break; case "330": if(key2.split("\\u001Fa").length>1) {//内容 String f1=key2.split("\\u001Fa")[1]; String f2=f1.split("\\u001F")[0]; map.put("Remarks", f2); } break; case "606": if(key2.split("\\u001Fa").length>1) {//主题 String f1=key2.split("\\u001Fa")[1]; String f2=f1.split("\\u001F")[0]; map.put("type", f2); } break; case "690": if(key2.split("\\u001Fa").length>1) {//分类号 String f1=key2.split("\\u001Fa")[1]; String f2=f1.split("\\u001F")[0]; map.put("clc", f2); } break; default: break; } } }将结果放到了map数组里。解析的数据都是规定好的,因为这是本人项目的一小部分,需要其他部分解析的可以参考资料添加解析。匹配类是单独的
会解析自然会拼接拉。直接上代码了。自己看吧:
public class PMarc { String marc1 = null;//第一段标识 String marc2 = null;//第二段目次 String marc3 = null;//第三段记录 String marc =null;//marc数据 char _RecordSplitChar = '\u001D'; // 区间分隔符 char _FieldSplitChar = '\u001E'; // 字段分割符 char _SubFieldSplitChar = '\u001F'; // 子字段分隔符 public String pjMarc( String isbn,String oneprice,String title,String author,String press,String clc) { //记录区 String s1=" "+_SubFieldSplitChar+"a"+isbn+_SubFieldSplitChar+"d"+oneprice; //010 isbn+价格 String s2=_FieldSplitChar+"1 "+_SubFieldSplitChar+"a"+title+_SubFieldSplitChar+"f"+author; //200 题名+作者 String s3=_FieldSplitChar+" "+_SubFieldSplitChar+"c"+press; //210 出版社 String s4=_FieldSplitChar+" "+_SubFieldSplitChar+"a"+clc ; //690 中图分类号 marc3=s1+s2+s3+s4; marc2="010"+String.format("%04d", s1.length())+String.format("%05d", 0) +"200"+String.format("%04d", s2.length())+String.format("%05d", 0+s1.length()) +"210"+String.format("%04d", s3.length())+String.format("%05d", 0+s1.length()+s2.length()) +"690"+String.format("%04d", s4.length())+String.format("%05d", 0+s1.length()+s2.length()+s3.length()) ; marc1=String.format("%05d", marc3.length()+marc2.length()+1) +"pam0"+" 22"+String.format("%05d",marc2.length()+1+24)+" "+"450 " ; marc=marc1+marc2+_FieldSplitChar+marc3+_RecordSplitChar; return marc; } }拼接类拼接的比较简单,可以自行添加复杂,注意的是分隔符,很容易出错。
s2字符串中的marc数据乱码了。编码格式不同,建议自己去找一条marc数据去测试,可以去:中国国家图书馆找。 还有关于用z39.50协议套取mar数据的java方法可以去看我的另一篇yaz4j获取marc数据 套取marc方法类下载 -------------------------------------------------2019-11-01记载日志
