![JAR search and dependency download from the Maven repository](/logo.png)
org.marc4j.MarcStreamWriter Maven / Gradle / Ivy
/**
* Copyright (C) 2004 Bas Peters
*
* This file is part of MARC4J
*
* MARC4J is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* MARC4J is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with MARC4J; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.marc4j;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.DecimalFormat;
import org.marc4j.converter.CharConverter;
import org.marc4j.marc.ControlField;
import org.marc4j.marc.DataField;
import org.marc4j.marc.Leader;
import org.marc4j.marc.Record;
import org.marc4j.marc.Subfield;
import org.marc4j.util.CustomDecimalFormat;
/**
* Class for writing MARC record objects in ISO 2709 format.
*
* The following example reads a file with MARCXML records and outputs the record set in ISO 2709 format:
*
*
*
* InputStream input = new FileInputStream("marcxml.xml");
* MarcXmlReader reader = new MarcXmlReader(input);
* MarcWriter writer = new MarcStreamWriter(System.out);
* while (reader.hasNext()) {
* Record record = reader.next();
* writer.write(record);
* }
* writer.close();
*
*
* To convert characters like for example from UCS/Unicode to MARC-8 register a
* {@link org.marc4j.converter.CharConverter} implementation:
*
*
*
* InputStream input = new FileInputStream("marcxml.xml");
* MarcXmlReader reader = new MarcXmlReader(input);
* MarcWriter writer = new MarcStreamWriter(System.out);
* writer.setConverter(new UnicodeToAnsel());
* while (reader.hasNext()) {
* Record record = reader.next();
* writer.write(record);
* }
* writer.close();
*
*
* @author Bas Peters
*/
public class MarcStreamWriter implements MarcWriter {
protected OutputStream out = null;
protected String encoding = "ISO8859_1";
private CharConverter converter = null;
protected boolean allowOversizeEntry = false;
protected boolean hasOversizeOffset = false;
protected boolean hasOversizeLength = false;
protected static DecimalFormat format4Use = new CustomDecimalFormat(4);
protected static DecimalFormat format5Use = new CustomDecimalFormat(5);
/**
* Constructs an instance and creates a Writer
object with the specified output stream.
*/
public MarcStreamWriter(final OutputStream out) {
this.out = out;
}
/**
* Constructs an instance and creates a Writer
object with the specified output stream and character
* encoding.
*/
public MarcStreamWriter(final OutputStream out, final String encoding) {
this.encoding = encoding;
this.out = out;
}
/**
* Constructs an instance and creates a Writer
object with the specified output stream.
*/
public MarcStreamWriter(final OutputStream out, final boolean allowOversizeRecord) {
this.out = out;
this.allowOversizeEntry = allowOversizeRecord;
}
/**
* Constructs an instance and creates a Writer
object with the specified output stream and character
* encoding.
*/
public MarcStreamWriter(final OutputStream out, final String encoding, final boolean allowOversizeRecord) {
this.encoding = encoding;
this.out = out;
this.allowOversizeEntry = allowOversizeRecord;
}
/**
* Returns the character converter.
*
* @return CharConverter the character converter
*/
@Override
public CharConverter getConverter() {
return converter;
}
/**
* Sets the character converter.
*
* @param converter the character converter
*/
@Override
public void setConverter(final CharConverter converter) {
this.converter = converter;
}
/**
* Writes a Record
object to the writer.
*
* @param record - the Record
object
*/
@Override
public void write(final Record record) {
int previous = 0;
try {
final ByteArrayOutputStream data = new ByteArrayOutputStream();
final ByteArrayOutputStream dir = new ByteArrayOutputStream();
hasOversizeOffset = false;
hasOversizeLength = false;
// control fields
for (final ControlField cf : record.getControlFields()) {
data.write(getDataElement(cf.getData()));
data.write(Constants.FT);
dir.write(getEntry(cf.getTag(), data.size() - previous, previous));
previous = data.size();
}
// data fields
for (final DataField df : record.getDataFields()) {
data.write(df.getIndicator1());
data.write(df.getIndicator2());
for (final Subfield sf : df.getSubfields()) {
data.write(Constants.US);
data.write(sf.getCode());
data.write(getDataElement(sf.getData()));
}
data.write(Constants.FT);
dir.write(getEntry(df.getTag(), data.size() - previous, previous));
previous = data.size();
}
dir.write(Constants.FT);
// base address of data and logical record length
final Leader ldr = record.getLeader();
final int baseAddress = 24 + dir.size();
ldr.setBaseAddressOfData(baseAddress);
final int recordLength = ldr.getBaseAddressOfData() + data.size() + 1;
ldr.setRecordLength(recordLength);
// write record to output stream
dir.close();
data.close();
if (!allowOversizeEntry && (baseAddress > 99999 || recordLength > 99999 || hasOversizeOffset)) {
throw new MarcException("Record is too long to be a valid MARC binary record, it's length would be " +
recordLength + " which is more thatn 99999 bytes");
}
if (!allowOversizeEntry && (hasOversizeLength)) {
throw new MarcException("Record has field that is too long to be a valid MARC binary record. "
+ "The maximum length for a field counting all of the sub-fields is 9999 bytes.");
}
if (converter != null) {
ldr.setCharCodingScheme(converter.outputsUnicode() ? 'a' : ' ');
}
writeLeader(ldr);
out.write(dir.toByteArray());
out.write(data.toByteArray());
out.write(Constants.RT);
} catch (final IOException e) {
throw new MarcException("IO Error occured while writing record", e);
} catch (final MarcException e) {
throw e;
}
}
protected void writeLeader(final Leader ldr) throws IOException {
out.write(format5Use.format(ldr.getRecordLength()).getBytes(encoding));
out.write(ldr.getRecordStatus());
out.write(ldr.getTypeOfRecord());
out.write(new String(ldr.getImplDefined1()).getBytes(encoding));
out.write(ldr.getCharCodingScheme());
out.write(Integer.toString(ldr.getIndicatorCount()).getBytes(encoding));
out.write(Integer.toString(ldr.getSubfieldCodeLength()).getBytes(encoding));
out.write(format5Use.format(ldr.getBaseAddressOfData()).getBytes(encoding));
out.write(new String(ldr.getImplDefined2()).getBytes(encoding));
out.write(new String(ldr.getEntryMap()).getBytes(encoding));
}
/**
* Closes the writer.
*/
@Override
public void close() {
try {
out.close();
} catch (final IOException e) {
throw new MarcException("IO Error occured on close", e);
}
}
protected byte[] getDataElement(final String data) throws IOException {
if (converter != null) {
return converter.convert(data).getBytes(encoding);
}
return data.getBytes(encoding);
}
protected byte[] getEntry(final String tag, final int length, final int start) throws IOException {
final String entryUse = tag + format4Use.format(length) + format5Use.format(start);
if (length > 99999) {
hasOversizeLength = true;
}
if (start > 99999) {
hasOversizeOffset = true;
}
return (entryUse.getBytes(encoding));
}
/**
* Returns true
if an oversized entry is allowed; else, false
.
*
* @return
*/
public boolean allowsOversizeEntry() {
return allowOversizeEntry;
}
/**
* Sets whether an oversized entry is allowed.
*
* @param allowOversizeEntry
*/
public void setAllowOversizeEntry(final boolean allowOversizeEntry) {
this.allowOversizeEntry = allowOversizeEntry;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy