解析marc資料:
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數組裡。解析的資料都是規定好的,因為這是本人項目的一小部分,需要其他部分解析的可以參考資料添加解析。比對類是單獨的
拼接marc資料
會解析自然會拼接拉。直接上代碼了。自己看吧:
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;
}
}
拼接類拼接的比較簡單,可以自行添加複雜,注意的是分隔符,很容易出錯。
測試類
import java.util.HashMap;
import java.util.Map;
public class test {
public static void main(String[] args) {
Map<String, String> map=new HashMap<String, String>();
JMarc j=new JMarc();
PMarc p=new PMarc();
//拼接
String s=p.pjMarc("978-7-5463-4025-4", "CNY79.50", "誅仙", "蕭鼎著", "起點小說網", "D67.475");
map=j.jxMarc(s);//解析測試
System.err.println(s);
System.out.println(map);
//解析
String s2="01141nam0 2200289 450 00100100000000500170001001000390002703500260006603500240009204900490011610000410016510100080020610200150021410500180022910600060024720001570025321000350041021500190044533001600046460700250062469000140064970100490066370200310071271200630074380100220080680100230082800011310320020928000000.0 a7-101-00183-1dCNY332.00(全二十冊) a(A100000NLC)000113139 a(011001)c2001044106 aA100000NLCbUCS01000113103c000113139dNLC01 a20010709e19951956em y0chiy0110 ea0 achi aCNb110000 ay z 000yy ar1 a資治通鑒9zi zhi tong jianh第一冊i卷一至一十二 周威烈王二十三年戊寅起 漢惠帝七年癸醜止b專著f(宋)司馬光編著g(元)胡三省音注g“标點資治通鑒小組”校點 a北京c中華書局d1956h1995重印 a75,418頁d20cm a《資治通鑒》為北宋司馬光所編撰的編年體通史,共294卷。全書記載了上起周威王二十三年(公元前403年),下至五代周世宗顯德六年(公元959年)的一千三百六十二年的曆史。 a中國x古代史j編年體 aK204.3v4 0c(宋)a司馬光f(1019-1086)9si ma guang4編著 0a胡三省9hu san sheng4音注02a标點資治通鑒小組9biao dian zi zhi tong jian xiao zu4校點 0aCNbNLCc20010717 2aCNbOLCCc20100923";
map=j.jxMarc(s2);
System.out.println(map);
}
}
s2字元串中的marc資料亂碼了。編碼格式不同,建議自己去找一條marc資料去測試,可以去:中國國家圖書館找。
還有關于用z39.50協定套取mar資料的java方法可以去看我的另一篇yaz4j擷取marc資料
套取marc方法類下載下傳
-------------------------------------------------2019-11-01記載日志