public Map<String, Object> getNextRow(Collection<String> columnNames) throws IOException { if (!positionAtNextRow()) { return null; } if (LOG.isDebugEnabled()) { LOG.debug("Data block at position " + Integer.toHexString(_buffer.position()) + ":\n" + ByteUtil.toHexString(_buffer, _buffer.position(), _buffer.limit() - _buffer.position())); } short columnCount = _buffer.getShort(); Map<String, Object> rtn = new LinkedHashMap<String, Object>(columnCount); NullMask nullMask = new NullMask(columnCount); _buffer.position(_buffer.limit() - nullMask.byteSize()); nullMask.read(_buffer); _buffer.position(_buffer.limit() - nullMask.byteSize() - 2); short varColumnCount = _buffer.getShort(); byte[][] varColumnData = new byte[varColumnCount][];   short[] varColumnOffsets = new short[varColumnCount]; _buffer.position(_buffer.position() - 2 - (varColumnCount * 2) - 2); short lastVarColumnStart = _buffer.getShort(); for (short i = 0; i < varColumnCount; i++) { varColumnOffsets[i] = _buffer.getShort(); }   for (short i = 0; i < varColumnCount; i++) { _buffer.position(_rowStart + varColumnOffsets[i]); varColumnData[i] = new byte[lastVarColumnStart - varColumnOffsets[i]]; _buffer.get(varColumnData[i]); lastVarColumnStart = varColumnOffsets[i]; } int columnNumber = 0; int varColumnDataIndex = varColumnCount - 1;  _buffer.position(_rowStart + 2);    byte[] columnData = null; for (Iterator iter = _columns.iterator(); iter.hasNext(); columnNumber++) { Column column = (Column) iter.next(); boolean isNull = nullMask.isNull(columnNumber); Object value = null; if (column.getType() == DataType.BOOLEAN) { value = new Boolean(!isNull); } else { if (!column.isVariableLength()) {  columnData = new byte[column.getLength()]; _buffer.get(columnData); } else { if (!isNull) {  columnData = varColumnData[varColumnDataIndex]; } --varColumnDataIndex; } if (!isNull && columnData != null && (columnNames == null || columnNames.contains(column.getName()))) {  value = column.read(columnData); } } rtn.put(column.getName(), value); } return rtn;
public Map<String, Object> getNextRow() throws IOException { return getNextRow(null);
  public Map<String, Object> getNextRow(Collection<String> columnNames)   throws IOException  {    if (!positionAtNextRow()) {      return null;    }    if (LOG.isDebugEnabled()) {      LOG.debug("Data block at position " + Integer.toHexString(_buffer.position()) +          ":\n" + ByteUtil.toHexString(_buffer, _buffer.position(),          _buffer.limit() - _buffer.position()));    }    short columnCount = _buffer.getShort(); //Number of columns in this table    Map<String, Object> rtn = new LinkedHashMap<String, Object>(columnCount);    NullMask nullMask = new NullMask(columnCount);    _buffer.position(_buffer.limit() - nullMask.byteSize());  //Null mask at end    nullMask.read(_buffer);    _buffer.position(_buffer.limit() - nullMask.byteSize() - 2);    short varColumnCount = _buffer.getShort();  //Number of variable length columns    byte[][] varColumnData = new byte[varColumnCount][];  //Holds variable length column data        //Read in the offsets of each of the variable length columns    short[] varColumnOffsets = new short[varColumnCount];    _buffer.position(_buffer.position() - 2 - (varColumnCount * 2) - 2);    short lastVarColumnStart = _buffer.getShort();    for (short i = 0; i < varColumnCount; i++) {      varColumnOffsets[i] = _buffer.getShort();    }        //Read in the actual data for each of the variable length columns    for (short i = 0; i < varColumnCount; i++) {      _buffer.position(_rowStart + varColumnOffsets[i]);      varColumnData[i] = new byte[lastVarColumnStart - varColumnOffsets[i]];      _buffer.get(varColumnData[i]);      lastVarColumnStart = varColumnOffsets[i];    }    int columnNumber = 0;    int varColumnDataIndex = varColumnCount - 1;        _buffer.position(_rowStart + 2);  //Move back to the front of the buffer        //Now read in the fixed length columns and populate the columnData array    //with the combination of fixed length and variable length data.    byte[] columnData = null;    for (Iterator iter = _columns.iterator(); iter.hasNext(); columnNumber++) {      Column column = (Column) iter.next();      boolean isNull = nullMask.isNull(columnNumber);      Object value = null;      if (column.getType() == DataType.BOOLEAN) {        value = new Boolean(!isNull);  //Boolean values are stored in the null mask      } else {        if (!column.isVariableLength())         {          //Read in fixed length column data          columnData = new byte[column.getLength()];          _buffer.get(columnData);        }         else        {           if (!isNull)            {             //Refer to already-read-in variable length data             columnData = varColumnData[varColumnDataIndex];           }           --varColumnDataIndex;        }        if (!isNull && columnData != null &&            (columnNames == null || columnNames.contains(column.getName())))        {          //Add the value if we are interested in it.          value = column.read(columnData);        }      }      rtn.put(column.getName(), value);    }    return rtn;  }