/// <summary> /// Creates a new RDY file object. /// </summary> public static RdyFile Create(char tableType, int tableId, int recordSize, int keyLength = 0, int keyOffset = 0, bool sorted = false, bool packed = false, char tableVersion = 'A') { if (recordSize < 0 || recordSize > 99) { throw new ArgumentOutOfRangeException("recordSize", "Invalid record size for RDY file."); } var header = RdyHeader.Create(tableType, tableId, recordSize, keyLength, keyOffset, sorted, packed, tableVersion); var rdy = new RdyFile { Header = header, _records = new List <RdyRecord>() }; return(rdy); }
/// <summary> /// Returns an awaitable task that reads an RDY file from an input stream. /// </summary> internal static async Task <RdyFile> ReadAsync(Stream stream, bool force = false) { if (stream == null) { throw new ArgumentNullException("stream", "The input stream cannot be null."); } if (!stream.CanRead) { throw new InvalidOperationException("Could not read from the input stream."); } var rdy = new RdyFile(); using (var reader = new StreamReader(stream)) { // Read and parse the header var header = await rdy.ReadHeaderAsync(reader); rdy.Header = RdyHeader.Parse(header, force); // See if we are working with a directory file if (rdy.Header.TableType == 'z') { rdy.IsDirectoryFile = true; // Put data back in the buffer rdy._buffer.Insert(0, header.Substring(9)); // Read the body as directory data await rdy.ReadDirBodyAsync(reader); } else { // Read and load the records in the body await rdy.ReadBodyAsync(reader, force); } } return(rdy); }
internal static RdyHeader Parse(string data, bool force) { var header = new RdyHeader(); if (data == null) throw new ArgumentNullException("data"); if (data.Length != HeaderSize && !force) throw new ArgumentException(string.Format("The header must consist of exactly {0} characters.", HeaderSize)); header.TableType = data[0]; int i; if (!int.TryParse(data.Substring(1, 3), NumberStyles.None, CultureInfo.InvariantCulture, out i) && !force) throw new InvalidDataException("Couldn't parse the table ID from the RDY header."); header.TableId = i; if (!int.TryParse(data.Substring(4, 5), NumberStyles.None, CultureInfo.InvariantCulture, out i) && !force) throw new InvalidDataException("Couldn't parse the total number of characters from the RDY header."); header.TotalCharacters = i; if (header.TableType == 'z') { // z indicates a "directory file", which has a truncated header. Exit early. return header; } header.TableVersion = data[9]; if (!int.TryParse(data.Substring(10, 2), NumberStyles.None, CultureInfo.InvariantCulture, out i) && !force) throw new InvalidDataException("Couldn't parse the header size from the RDY header."); if (i != HeaderSize && !force) throw new InvalidDataException(string.Format("The header size in the RDY file should state {0} but it was {1} instead.", HeaderSize, i)); if (!int.TryParse(data.Substring(12, 2), NumberStyles.None, CultureInfo.InvariantCulture, out i) && !force) throw new InvalidDataException("Couldn't parse the record size from the RDY header."); header.RecordSize = i; // work around a known issue with v001 data (from JPR001.RDY) if (header.TableType == 'v' && header.TableId == 1 && header.RecordSize == 96) header.RecordSize = 6; header.RecordCount = SynelNumericFormat.Convert(data.Substring(14, 3)); if (!int.TryParse(data.Substring(17, 2), NumberStyles.None, CultureInfo.InvariantCulture, out i) && !force) throw new InvalidDataException("Couldn't parse the key length from the RDY header."); header.KeyLength = i; if (!int.TryParse(data.Substring(19, 2), NumberStyles.None, CultureInfo.InvariantCulture, out i) && !force) throw new InvalidDataException("Couldn't parse the key offset from the RDY header."); header.KeyOffset = i; if (!int.TryParse(data.Substring(21, 2), NumberStyles.None, CultureInfo.InvariantCulture, out i) && !force) throw new InvalidDataException("Couldn't parse the sorted/packed flags from the RDY header."); header.Sorted = i == 2 || i == 3; header.Packed = i == 1 || i == 3; // Make sure the character count makes sense var expectedChars = HeaderSize + header.RecordCount * header.RecordSize; if (header.TotalCharacters != expectedChars && !force) throw new InvalidDataException(string.Format("The total character count doesn't match. It was reported as {0}, but calculated as {1}.", header.TotalCharacters, expectedChars)); return header; }
internal static RdyHeader Parse(string data, bool force) { var header = new RdyHeader(); if (data == null) { throw new ArgumentNullException("data"); } if (data.Length != HeaderSize && !force) { throw new ArgumentException(string.Format("The header must consist of exactly {0} characters.", HeaderSize)); } header.TableType = data[0]; int i; if (!int.TryParse(data.Substring(1, 3), NumberStyles.None, CultureInfo.InvariantCulture, out i) && !force) { throw new InvalidDataException("Couldn't parse the table ID from the RDY header."); } header.TableId = i; if (!int.TryParse(data.Substring(4, 5), NumberStyles.None, CultureInfo.InvariantCulture, out i) && !force) { throw new InvalidDataException("Couldn't parse the total number of characters from the RDY header."); } header.TotalCharacters = i; if (header.TableType == 'z') { // z indicates a "directory file", which has a truncated header. Exit early. return(header); } header.TableVersion = data[9]; if (!int.TryParse(data.Substring(10, 2), NumberStyles.None, CultureInfo.InvariantCulture, out i) && !force) { throw new InvalidDataException("Couldn't parse the header size from the RDY header."); } if (i != HeaderSize && !force) { throw new InvalidDataException(string.Format("The header size in the RDY file should state {0} but it was {1} instead.", HeaderSize, i)); } if (!int.TryParse(data.Substring(12, 2), NumberStyles.None, CultureInfo.InvariantCulture, out i) && !force) { throw new InvalidDataException("Couldn't parse the record size from the RDY header."); } header.RecordSize = i; // work around a known issue with v001 data (from JPR001.RDY) if (header.TableType == 'v' && header.TableId == 1 && header.RecordSize == 96) { header.RecordSize = 6; } header.RecordCount = SynelNumericFormat.Convert(data.Substring(14, 3)); if (!int.TryParse(data.Substring(17, 2), NumberStyles.None, CultureInfo.InvariantCulture, out i) && !force) { throw new InvalidDataException("Couldn't parse the key length from the RDY header."); } header.KeyLength = i; if (!int.TryParse(data.Substring(19, 2), NumberStyles.None, CultureInfo.InvariantCulture, out i) && !force) { throw new InvalidDataException("Couldn't parse the key offset from the RDY header."); } header.KeyOffset = i; if (!int.TryParse(data.Substring(21, 2), NumberStyles.None, CultureInfo.InvariantCulture, out i) && !force) { throw new InvalidDataException("Couldn't parse the sorted/packed flags from the RDY header."); } header.Sorted = i == 2 || i == 3; header.Packed = i == 1 || i == 3; // Make sure the character count makes sense var expectedChars = HeaderSize + header.RecordCount * header.RecordSize; if (header.TotalCharacters != expectedChars && !force) { throw new InvalidDataException(string.Format("The total character count doesn't match. It was reported as {0}, but calculated as {1}.", header.TotalCharacters, expectedChars)); } return(header); }