docs: @SuppressWarnings({"checkstyle:cyclomaticcomplexity", "checkstyle:npathcomplexity", "checkstyle:magicnumber"})
  	private DBaseFileRecord readDBFRecord(int recordNumber) throws IOException {
  		if (this.finished) {
  			throw new EOFDBaseFileException();
  		}
  		if (this.fields == null) {
  			throw new MustCallReadHeaderFunctionException();
  		}
  
  		//
  		//-----------------------------------------------------------
  		// Bytes       Size   Content
  		//-----------------------------------------------------------
  		//     0    1 byte    deleted flag:
  		//                    '*' (star) if deleted
  		//                    ' ' (space) if not deleted
  		//  1..m    n bytes   contents of fields, for n see
  		//                    the bytes 10..11 of the dBASE header
  
  		// Compute the offset
  		final long offset = this.readingPosition * this.recordSize + this.firstRecordOffset;
  
  		// Read the record
  		final byte[] rawData = new byte[this.recordSize];
  		this.stream.readFully(rawData);
  
  		// Read the deleted flag
  		final int deletedFlag = rawData[0] & 0xFF;
  		if (deletedFlag == 0x1A) {
  			// END-OF-FILE character
  			throw new EOFException();
  		}
  		if (deletedFlag != '*' && deletedFlag != ' ') {
  			throw new InvalidDeletionFlagFormatException(recordNumber, deletedFlag);
  		}
  		if (deletedFlag == '*') {
  			return null;
  		}
  
  		int rawOffset = 1;
  
  		final DBaseFileRecord record = new DBaseFileRecord(recordNumber, offset);
  		for (int i = 0; i < this.fieldCount; ++i) {
  
  			final DBaseFileField field = this.fields.get(i);
  			if (field != null) {
  
  				Object value = null;
  
  				// Read the content of the record
  				switch (field.getType()) {
  				//
  				// Read a list of characters
  				case STRING:
  					final OutputParameter<String> strvalue = new OutputParameter<>();
  					rawOffset += readStringRecordValue(
  							field,
  							recordNumber, i + 1,
  							rawData, rawOffset,
  							strvalue);
  					value = strvalue.get();
  					break;
  				//
  				// Read a date
  				case DATE:
  					final OutputParameter<Date> datevalue = new OutputParameter<>();
  					rawOffset += readDateRecordValue(field, recordNumber, i + 1, rawData, rawOffset, datevalue);
  					value = datevalue.get();
  					break;
  				//
  				// Read a number
  				case NUMBER:
  				case FLOATING_NUMBER:
  					final OutputParameter<Double> dblvalue = new OutputParameter<>();
  					rawOffset += readNumberRecordValue(field, recordNumber, i + 1, rawData, rawOffset, dblvalue);
  					value = dblvalue.get();
  					break;
  				//
  				// Read a boolean
  				case BOOLEAN:
  					final OutputParameter<Boolean> boolvalue = new OutputParameter<>();
  					rawOffset += readBooleanRecordValue(field, recordNumber, i + 1, rawData, rawOffset, boolvalue);
  					value = boolvalue.get();
  					break;
  				//
  				// Read a 2 byte integer
  				case INTEGER_2BYTES:
  					final OutputParameter<Integer> intvalue = new OutputParameter<>();
  					rawOffset += read2ByteIntegerRecordValue(field, recordNumber, i + 1, rawData, rawOffset, intvalue);
  					value = intvalue.get();
  					break;
  				//
  				// Read a 4 byte integer
  				case INTEGER_4BYTES:
  					final OutputParameter<Long> longvalue = new OutputParameter<>();
  					rawOffset += read4ByteIntegerRecordValue(field, recordNumber, i + 1, rawData, rawOffset, longvalue);
  					value = longvalue.get();
  					break;
  				//
  				// Read a 8 byte double
  				case DOUBLE:
  					final OutputParameter<Double> dblvalue2 = new OutputParameter<>();
  					rawOffset += read8ByteDoubleRecordValue(field, recordNumber, i + 1, rawData, rawOffset, dblvalue2);
  					value = dblvalue2.get();
  					break;
  					//$CASES-OMITTED$
  				default:
  				}
  
  				if (value != null) {
  					record.add(value);
  				} else {
  					record.add(null);
  				}
  			}
  
  		}
  
  		return record;
  	}