/// <summary> /// Method to read data /// </summary> /// <param name="i"></param> public override void Read(ArrayDataIO i) { // Don't need to read null data (noted by Jens Knudstrup) if (byteSize == 0) { return; } SetFileOffset(i); //if(i is RandomAccess) if (i.CanSeek) { //tiler = new ImageDataTiler(this, (RandomAccess) i, ((RandomAccess) i).FilePointer, dataDescription); tiler = new ImageDataTiler(this, (RandomAccess)i, ((Stream)i).Position, dataDescription); try { double pos = i.Position; //pos = i.Seek((int)byteSize) - pos; i.Seek(byteSize); } catch (IOException e) { throw new FitsException("Unable to skip over data:" + e); } } else { dataArray = ArrayFuncs.NewInstance(dataDescription.type, dataDescription.dims); try { i.ReadArray(dataArray); } catch (IOException e) { throw new FitsException("Unable to read image data:" + e); } tiler = new ImageDataTiler(this, null, 0, dataDescription); } int pad = FitsUtil.Padding(TrueSize); try { long pos = i.Seek(pad); if (pos != pad) { throw new FitsException("Error skipping padding"); } } catch (IOException e) { throw new FitsException("Error reading image padding:" + e); } }
/// <summary> /// Method to read the ArrayDataIO /// </summary> /// <param name="i"></param> public override void Read(ArrayDataIO i) { SetFileOffset(i); if (i is RandomAccess) { try { //BinaryReader temp_BinaryReader; System.Int64 temp_Int64; //temp_BinaryReader = i; temp_Int64 = i.Position; //temp_BinaryReader.BaseStream.Position; temp_Int64 = i.Seek((int)byteSize) - temp_Int64; //temp_BinaryReader.BaseStream.Seek((int) byteSize, SeekOrigin.Current) - temp_Int64; int generatedAux = (int)temp_Int64; } catch (IOException e) { throw new FitsException("Unable to skip over data:" + e); } } else { try { i.Read(data); } catch (IOException e) { throw new FitsException("Unable to read unknown data:" + e); } } int pad = FitsUtil.Padding(TrueSize); try { //BinaryReader temp_BinaryReader2; System.Int64 temp_Int65; //temp_BinaryReader2 = i; temp_Int65 = i.Position; //temp_BinaryReader2.BaseStream.Position; temp_Int65 = i.Seek(pad) - temp_Int65; //temp_BinaryReader2.BaseStream.Seek(pad, SeekOrigin.Current) - temp_Int65; // if (temp_Int65 != pad) if (i.Seek(pad) != pad) { throw new FitsException("Error skipping padding"); } } catch (IOException e) { throw new FitsException("Error reading unknown padding:" + e); } }
/// <summary> /// Writes this binary table in one pass, /// then seeks back to fix NAXIS2. Requires /// s to be seekable and /// either no strings or truncated string output. /// </summary> /// <param name="s">The destination stream.</param> protected void WriteThenFix(ArrayDataIO s) { long headerMark = s.Position; int nRows = WriteTable(s); long endMark = s.Position; myHeader.RemoveCard("NAXIS2"); myHeader.SetNaxis(2, nRows); myHeader.InsertComment("No comment.", "THEAP"); myHeader.RemoveCard("THEAP"); s.Seek(headerMark, SeekOrigin.Begin); myHeader.Write(s); s.Seek(endMark, SeekOrigin.Begin); }
/// <summary>Read in an ASCII table. Reading is deferred if /// we are reading from a random access device</summary> public override void Read(ArrayDataIO str) { SetFileOffset(str); currInput = str; //if(str is RandomAccess) if (str.CanSeek) { try { //BinaryReader temp_BinaryReader; Int64 temp_Int64; //temp_BinaryReader = str; temp_Int64 = str.Position; //temp_BinaryReader.BaseStream.Position; temp_Int64 = str.Seek(nRows * rowLen) - temp_Int64; //temp_BinaryReader.BaseStream.Seek(nRows * rowLen, SeekOrigin.Current) - temp_Int64; int generatedAux = (int)temp_Int64; } catch (IOException e) { throw new FitsException("Error skipping data: " + e); } } else { try { GetBuffer(rowLen * nRows, 0); } catch (IOException e) { throw new FitsException("Error reading ASCII table:" + e); } } try { //BinaryReader temp_BinaryReader2; Int64 temp_Int65; //temp_BinaryReader2 = str; temp_Int65 = str.Position; //temp_BinaryReader2.BaseStream.Position; temp_Int65 = str.Seek(FitsUtil.Padding(nRows * rowLen)) - temp_Int65; //temp_BinaryReader2.BaseStream.Seek(FitsUtil.padding(nRows * rowLen), SeekOrigin.Current) - temp_Int65; int generatedAux2 = (int)temp_Int65; } catch (IOException e) { throw new FitsException("Error skipping padding:" + e); } }
/// <summary>Read the RandomGroupsData.</summary> public override void Read(ArrayDataIO str) { SetFileOffset(str); try { str.ReadArray(dataArray); } catch (IOException e) { throw new FitsException("IO error reading Random Groups data " + e); } int pad = FitsUtil.Padding(TrueSize); try { //System.IO.BinaryReader temp_BinaryReader; System.Int64 temp_Int64; //temp_BinaryReader = str; temp_Int64 = str.Position; //temp_BinaryReader.BaseStream.Position; temp_Int64 = str.Seek(pad) - temp_Int64; //temp_BinaryReader.BaseStream.Seek(pad, System.IO.SeekOrigin.Current) - temp_Int64; int generatedAux = (int)temp_Int64; } catch (IOException) { throw new FitsException("IO error reading padding."); } }
/// <summary>Skip the Data object immediately after the given Header object on /// the given stream object.</summary> /// <param name="stream">the stream which contains the data.</param> /// <param name="hdr">template indicating length of Data section</param> /// <exception cref="IOException"> IOException if the Data object could not be skipped.</exception> public static void SkipData(ArrayDataIO stream, Header hdr) { //System.IO.BinaryReader temp_BinaryReader; Int64 temp_Int64; //temp_BinaryReader = stream; temp_Int64 = stream.Position; //temp_BinaryReader.BaseStream.Position; temp_Int64 = stream.Seek((int)hdr.DataSize) - temp_Int64; //temp_BinaryReader.BaseStream.Seek((int) hdr.DataSize, System.IO.SeekOrigin.Current) - temp_Int64; int generatedAux = (int)temp_Int64; }
/// <summary>Attempt to rewrite the heap with the current contents. /// Note that no checking is done to make sure that the /// heap does not extend past its prior boundaries.</summary> public virtual void Rewrite() { if (this.Rewriteable) { //ArrayDataIO str = (ArrayDataIO) input; //FitsUtil.Reposition(input, fileOffset); input.Seek(fileOffset, SeekOrigin.Begin); Write(input); } else { throw new FitsException("Invalid attempt to rewrite FitsHeap"); } }
/// <summary>Read some data into the buffer.</summary> private void GetBuffer(int size, long offset) { if (currInput == null) { throw new IOException("No stream open to read"); } buffer = new byte[size]; if (offset != 0) { //FitsUtil.Reposition(currInput, offset); currInput.Seek(offset, SeekOrigin.Begin); } currInput.Read(buffer); //SupportClass.ReadInput(currInput.BaseStream, ref buffer, 0, buffer.Length); bp = new ByteParser(buffer); }
/// <summary>Skip the next HDU on the default input stream.</summary> public virtual void SkipHDU() { if (atEOF) { return; } else { Header hdr = new Header(dataStr); if (hdr == null) { atEOF = true; return; } int dataSize = (int)hdr.DataSize; // dataStr.Skip(dataSize); dataStr.Seek(dataSize); } }
/// <summary> /// Writes this binary table with heap temp file if necessary, /// then fixing nRows and PCOUNT in header, /// then if necessary copying heap file to destination stream. /// </summary> /// <param name="s">The destination stream.</param> /// steps: /// 1) write the header to the main stream /// write the table to the main stream /// byterenderers write data to the heap if necessary /// byterenderers return heap positions and lengths if necessary /// these are returned as a byte sequence like any other data /// and are written to the table like any other data /// 2) fix the header /// 3) write the heap tempfile to the main stream /// what a pain protected void WriteHeapOutputWithTempHeapFile(ArrayDataIO s) { String heapFilename = CreateTempFilename() + "heap.tmp"; HeapStream heapS = null; int[] maxColWidths = null; if (_hasStrings) { maxColWidths = new int[_byteRenderers.Length]; heapS = new HeapStream(new FileStream(heapFilename, FileMode.Create)); for (int col = 0; col < _byteRenderers.Length; ++col) { _byteRenderers[col].Heap = heapS; maxColWidths[col] = -1; } } #region 1) write the header and the table // prep header to make sure it will line up properly with the table later on. // since we made the header, we know that anything we add later // (except THEAP, accounted for here) will already have been there, // so we're not inflating the header myHeader.RemoveCard("THEAP"); if (_hasStrings && _writeMode == StringWriteMode.HEAP) { myHeader.AddValue("THEAP", 0, null); } long headerMark = s.Position; myHeader.Write(s); int nRows = 0; for (Array[] els = _rs.GetNextRow(ref _row); els != null;) { ++nRows; for (int col = 0; col < _byteRenderers.Length; ++col) { _byteRenderers[col].Write(els[col], s); if (els[col] is String[]) { maxColWidths[col] = maxColWidths[col] < ((String[])els[col])[0].Length ? ((String[])els[col])[0].Length : maxColWidths[col]; } } els = _rs.GetNextRow(ref _row); } // pad the table. if there's a heap, pad the heap instead if (!_hasStrings) { int pad = FitsUtil.Padding((long)nRows * (long)_rowSizeInBytes); s.Write(new byte[pad], 0, pad); } s.Flush(); #endregion #region 2) fix the header and write it to the main stream myHeader.RemoveCard("NAXIS2"); myHeader.SetNaxis(2, nRows); // shoehorn correct heap information into header // PCOUNT, THEAP, and TFORMn // fix NAXIS1 if (_hasStrings) { long theap = (long)nRows * (long)_rowSizeInBytes; int pad = FitsUtil.Padding(theap + heapS.Position); int pcount = (int)heapS.Position + pad; // here we correct for swapping out actual strings with heap indices/lengths myHeader.RemoveCard("NAXIS1"); myHeader.InsertCard(new HeaderCard("NAXIS1", _rowSizeInBytes, null), "NAXIS2"); myHeader.RemoveCard("PCOUNT"); myHeader.InsertCard(new HeaderCard("PCOUNT", pcount, "Length of heap area in bytes"), "GCOUNT"); myHeader.RemoveCard("THEAP"); // can't fit a long in here! if (pcount > 0 && _writeMode == StringWriteMode.HEAP) { myHeader.AddValue("THEAP", (int)theap, "Position of heap wrt start of binary table"); } // fix the TFORMn entries for string columns IEnumerator ie = null; bool found = false; for (int i = 0; i < maxColWidths.Length; ++i, found = false) { if (maxColWidths[i] > -1) { ie = myHeader.GetEnumerator(); ie.MoveNext(); for (int j = 0; !found && ie.Current != null; ++j, ie.MoveNext()) { if (("TFORM" + (i + 1)).Equals(((DictionaryEntry)ie.Current).Key)) { myHeader.RemoveCard(j); myHeader. InsertCard(new HeaderCard("TFORM" + (i + 1), "1PA(" + maxColWidths[i] + ")", null), j); found = true; } } } } } // rewrite the header long heapMark = s.Position; s.Seek(headerMark, SeekOrigin.Begin); myHeader.Write(s); #endregion #region 3) write the heap tempfile to the main stream if (_hasStrings) { // calculate the pad int pad = FitsUtil.Padding((long)nRows * (long)_rowSizeInBytes + heapS.Position); s.Seek(heapMark, SeekOrigin.Begin); // write heap to the main stream heapS.Seek(0, SeekOrigin.Begin); for (int nRead = heapS.Read(_buf, 0, _buf.Length); nRead > 0;) { s.Write(_buf, 0, nRead); nRead = heapS.Read(_buf, 0, _buf.Length); } heapS.Close(); File.Delete(heapFilename); // pad the file s.Write(new byte[pad], 0, pad); } #endregion }
/// <summary>Fill the subset.</summary> /// <param name="data">The memory-resident data image. /// This may be null if the image is to be read from a file. This should /// be a multi-dimensional primitive array.</param> /// <param name="o">The tile to be filled. This is a simple primitive array.</param> /// <param name="dims">The dimensions of the full image.</param> /// <param name="corners">The indices of the corner of the image.</param> /// <param name="lengths">The dimensions of the subset.</param> protected internal virtual void FillTile(Array data, Array o, int[] dims, int[] corners, int[] lengths) { int n = dims.Length; int[] posits = new int[n]; int baseLength = ArrayFuncs.GetBaseLength(o); int segment = lengths[n - 1]; Array.Copy(corners, 0, posits, 0, n); long currentOffset = 0; if (data == null) { //currentOffset = f.FilePointer; currentOffset = f.Position; } int outputOffset = 0; if (data != null && data.GetType().Equals(typeof(Array)) && !ArrayFuncs.IsArrayOfArrays(data)) { int[] index = new int[posits.Length]; Array.Copy(posits, 0, index, 0, n); index[index.Length - 1] -= 1; for (int i = outputOffset; ArrayFuncs.NextIndex(index, posits, lengths); ++i) { o.SetValue(data.GetValue(index), i); } return; } do { // This implies there is some overlap in the last index // (in conjunction with other tests) int mx = dims.Length - 1; bool validSegment = posits[mx] + lengths[mx] >= 0 && posits[mx] < dims[mx]; // Don't do anything for the current segment if anything but the // last index is out of range. if (validSegment) { for (int i = 0; i < mx; i += 1) { if (posits[i] < 0 || posits[i] >= dims[i]) { validSegment = false; break; } } } if (validSegment) { if (data != null) { FillMemData(data, posits, segment, o, outputOffset, 0); } else { int offset = GetOffset(dims, posits) * baseLength; // Point to offset at real beginning // of segment int actualLen = segment; int actualOffset = offset; int actualOutput = outputOffset; if (posits[mx] < 0) { actualOffset -= posits[mx] * baseLength; actualOutput -= posits[mx]; actualLen += posits[mx]; } if (posits[mx] + segment > dims[mx]) { actualLen -= posits[mx] + segment - dims[mx]; } FillFileData(o, actualOffset, actualOutput, actualLen); } } outputOffset += segment; }while(IncrementPosition(corners, posits, lengths)); if (data == null) { f.Seek(currentOffset, SeekOrigin.Begin); } }