class MARC::Writer

A class for writing MARC records as MARC21.

However, if you set `allow_oversized` to true, then the Writer will write these records out anyway, filling in any binary length/offset slots with all 0's, if they are not wide enough to hold the true value. While these records are illegal, they can still be read back in using the MARC::ForgivingReader, as well as other platform MARC readers in tolerant mode.

If you set `allow_oversized` to false on the Writer, a MARC::Exception will be raised instead, if you try to write an oversized record.

writer = Writer.new(some_path)
writer.allow_oversized = true

Attributes

allow_oversized[RW]

Public Class Methods

encode(record) click to toggle source

a static method that accepts a MARC::Record object and returns the record encoded as MARC21 in transmission format

# File lib/marc/writer-NEW.rb, line 38
def self.encode(record)
  directory = ''
  fields = ''
  offset = 0
  for field in record.fields

    # encode the field
    field_data = ''
    if field.class == MARC::DataField 
      warn("Warn:  Missing indicator") unless field.indicator1 && field.indicator2
      field_data = (field.indicator1 || " ") + (field.indicator2 || " ")
      for s in field.subfields
        field_data += SUBFIELD_INDICATOR + s.code + s.value
      end
    elsif field.class == MARC::ControlField
      field_data = field.value
    end
    field_data += END_OF_FIELD

    # calculate directory entry for the field
    field_length = (field_data.respond_to?(:bytesize) ?
      field_data.bytesize() :
      field_data.length())        
    directory += sprintf("%03s", field.tag) + format_byte_count(field_length, 4) + format_byte_count(offset)


    # add field to data for other fields
    fields += field_data 

    # update offset for next field
    offset += field_length
  end

  # determine the base (leader + directory)
  base = record.leader + directory + END_OF_FIELD

  # determine complete record
  marc = base + fields + END_OF_RECORD

  # update leader with the byte offest to the end of the directory
  marc[12..16] = format_byte_count(base.respond_to?(:bytesize) ?
    base.bytesize() :
    base.length() 
  )

  # update the record length
  marc[0..4] = format_byte_count(marc.respond_to?(:bytesize) ?
    marc.bytesize() :
    marc.length()
  )      
  
  # store updated leader in the record that was passed in
  record.leader = marc[0..LEADER_LENGTH-1]

  # return encoded marc
  return marc
end
format_byte_count(number, num_digits=5) click to toggle source
# File lib/marc/writer-NEW.rb, line 96
def self.format_byte_count(number, num_digits=5)
  formatted = sprintf("%0#{num_digits}i", number)
  if formatted.length > num_digits
    # uh, oh, we've exceeded our max. Either zero out
    # or raise, depending on settings.
    #formatted = sprintf("%0#{num_digits}i", "")
    formatted = "9" * num_digits
  end
  return formatted
end
new(file) click to toggle source

the constructor which you must pass a file path or an object that responds to a write message

# File lib/marc/writer-NEW.rb, line 10
def initialize(file)
  if file.class == String
    @fh = File.new(file,"w")
  elsif file.respond_to?('write')
    @fh = file
  else
    throw "must pass in file name or handle"
  end
end

Public Instance Methods

close() click to toggle source

close underlying filehandle

# File lib/marc/writer-NEW.rb, line 30
def close
  @fh.close
end
write(record) click to toggle source

write a record to the file or handle

# File lib/marc/writer-NEW.rb, line 23
def write(record)
  @fh.write(MARC::Writer.encode(record))
end