public void writeData(DataOutput strm) throws IOException {

    /* Work out the length of each row in bytes. */
    int rowBytes = 0;
    int ncol = table.getColumnCount();
    for (int icol = 0; icol < ncol; icol++) {
      ColumnWriter writer = colWriters[icol];
      if (writer != null) {
        rowBytes += writer.getLength();
      }
    }

    /* Write the data cells, delegating the item in each column to
     * the writer that knows how to handle it. */
    long nWritten = 0L;
    RowSequence rseq = table.getRowSequence();
    try {
      while (rseq.next()) {
        Object[] row = rseq.getRow();
        for (int icol = 0; icol < ncol; icol++) {
          ColumnWriter writer = colWriters[icol];
          if (writer != null) {
            writer.writeValue(strm, row[icol]);
          }
        }
        nWritten += rowBytes;
      }
    } finally {
      rseq.close();
    }

    /* Write padding. */
    int extra = (int) (nWritten % (long) 2880);
    if (extra > 0) {
      strm.write(new byte[2880 - extra]);
    }
  }
  public Header getHeader() throws HeaderCardException {

    /* Work out the dimensions in columns and bytes of the table. */
    int rowLength = 0;
    int nUseCol = 0;
    int ncol = table.getColumnCount();
    for (int icol = 0; icol < ncol; icol++) {
      ColumnWriter writer = colWriters[icol];
      if (writer != null) {
        nUseCol++;
        rowLength += writer.getLength();
      }
    }

    /* Prepare a FITS header block. */
    Header hdr = new Header();

    /* Add HDU layout metadata. */
    hdr.addValue("XTENSION", "BINTABLE", "binary table extension");
    hdr.addValue("BITPIX", 8, "8-bit bytes");
    hdr.addValue("NAXIS", 2, "2-dimensional table");
    hdr.addValue("NAXIS1", rowLength, "width of table in bytes");
    hdr.addValue("NAXIS2", rowCount, "number of rows in table");
    hdr.addValue("PCOUNT", 0, "size of special data area");
    hdr.addValue("GCOUNT", 1, "one data group");
    hdr.addValue("TFIELDS", nUseCol, "number of columns");

    /* Add EXTNAME record containing table name. */
    String tname = table.getName();
    if (tname != null && tname.trim().length() > 0) {
      FitsConstants.addTrimmedValue(hdr, "EXTNAME", tname, "table name");
    }

    /* Add HDU metadata describing columns. */
    int jcol = 0;
    for (int icol = 0; icol < ncol; icol++) {
      ColumnWriter colwriter = colWriters[icol];
      if (colwriter != null) {
        jcol++;
        String forcol = " for column " + jcol;
        ColumnInfo colinfo = colInfos[icol];

        /* Name. */
        String name = colinfo.getName();
        if (name != null && name.trim().length() > 0) {
          FitsConstants.addTrimmedValue(hdr, "TTYPE" + jcol, name, "label" + forcol);
        }

        /* Format. */
        String form = colwriter.getFormat();
        hdr.addValue("TFORM" + jcol, form, "format" + forcol);

        /* Units. */
        String unit = colinfo.getUnitString();
        if (unit != null && unit.trim().length() > 0) {
          FitsConstants.addTrimmedValue(hdr, "TUNIT" + jcol, unit, "units" + forcol);
        }

        /* Blank. */
        Number bad = colwriter.getBadNumber();
        if (bad != null) {
          hdr.addValue("TNULL" + jcol, bad.longValue(), "blank value" + forcol);
        }

        /* Shape. */
        int[] dims = colwriter.getDims();
        if (dims != null && dims.length > 1) {
          StringBuffer sbuf = new StringBuffer();
          for (int i = 0; i < dims.length; i++) {
            sbuf.append(i == 0 ? '(' : ',');
            sbuf.append(dims[i]);
          }
          sbuf.append(')');
          hdr.addValue("TDIM" + jcol, sbuf.toString(), "dimensions" + forcol);
        }

        /* Scaling. */
        double zero = colwriter.getZero();
        double scale = colwriter.getScale();
        if (zero != 0.0) {
          hdr.addValue("TZERO" + jcol, zero, "base" + forcol);
        }
        if (scale != 1.0) {
          hdr.addValue("TSCALE" + jcol, scale, "factor" + forcol);
        }

        /* Comment (non-standard). */
        String comm = colinfo.getDescription();
        if (comm != null && comm.trim().length() > 0) {
          try {
            hdr.addValue("TCOMM" + jcol, comm, null);
          } catch (HeaderCardException e) {
            // never mind.
          }
        }

        /* UCD (non-standard). */
        String ucd = colinfo.getUCD();
        if (ucd != null && ucd.trim().length() > 0 && ucd.length() < 68) {
          try {
            hdr.addValue("TUCD" + jcol, ucd, null);
          } catch (HeaderCardException e) {
            // never mind.
          }
        }

        /* Utype (non-standard). */
        String utype = colinfo.getUtype();
        if (utype != null && utype.trim().length() > 0 && utype.trim().length() < 68) {
          try {
            hdr.addValue("TUTYP" + jcol, utype, null);
          } catch (HeaderCardException e) {
            // never mind.
          }
        }
      }
    }
    return hdr;
  }