/// <summary>Read a stream for header data.</summary> /// <param name="dis">The input stream to read the data from.</param> /// <returns> <CODE>null</CODE> if there was a problem with the header; /// otherwise return the header read from the input stream.</returns> /// <exception cref="TruncatedFileException"> </exception>" public virtual void Read(ArrayDataIO dis) { if (dis is RandomAccess) { fileOffset = FitsUtil.FindOffset(dis); } else { fileOffset = - 1; } byte[] buffer = new byte[80]; bool firstCard = true; int count = 0; bool notEnd = true; while(notEnd) { int need = 80; // try // { for(int len = 1; need > 0 && len > 0;) { len = dis.Read(buffer, 80 - need, need); count += 1; if(firstCard && len == 0 && need == 80) { throw new EndOfStreamException(); } need -= len; } // } // catch(EndOfStreamException e) // { // // Rethrow the EOF if we are at the beginning of the header, // // otherwise we have a FITS error. // if(firstCard && need == 80) // { // throw e; // } // throw new TruncatedFileException(e.Message); // } String cbuf = new String(SupportClass.ToCharArray(buffer)); HeaderCard fcard = new HeaderCard(cbuf); if(firstCard) { String key = fcard.Key; //Console.Out.WriteLine("key = '" + key + "'"); if(key == null || (!key.Equals("SIMPLE") && !key.Equals("XTENSION"))) { throw new IOException("Not FITS format at " + fileOffset + ":" + cbuf); } firstCard = false; } String key2 = fcard.Key; if(key2 != null && cards.ContainsKey(key2)) { Console.Error.WriteLine("Warning: multiple occurrences of key:" + key2); } // save card AddLine(fcard); if (cbuf.Substring(0, (8) - (0)).Equals("END ")) { notEnd = false; } } if (fileOffset >= 0) { oldSize = cards.Count; input = dis; } // Read to the end of the current FITS block. try { if(dis.CanSeek) { dis.Seek(FitsUtil.Padding(count * 80)); } else { int pad = FitsUtil.Padding(count * 80); for (int len = dis.Read(buffer, 0, Math.Min(pad, buffer.Length)); pad > 0 && len != -1; ) { pad -= len; len = dis.Read(buffer, 0, Math.Min(pad, buffer.Length)); } } } catch(IOException e) { throw new TruncatedFileException(e.Message); } }
/// <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> /// 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((int)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>Read table, heap and padding</summary> protected internal void ReadTrueData(ArrayDataIO i) { int len; try { len = table.Read(i); // IO.BinaryReader temp_BinaryReader; Int64 temp_Int64; //temp_BinaryReader = i; temp_Int64 = i.Position; //temp_BinaryReader.BaseStream.Position; temp_Int64 = i.Seek(heapOffset, SeekOrigin.Current) - temp_Int64; //temp_BinaryReader.BaseStream.Seek(heapOffset, IO.SeekOrigin.Current) - temp_Int64; int generatedAux = (int)temp_Int64; heap.Read(i); //IO.BinaryReader temp_BinaryReader2; Int64 temp_Int65; //temp_BinaryReader2 = i; temp_Int65 = i.Position; //temp_BinaryReader2.BaseStream.Position; temp_Int65 = i.Seek(FitsUtil.Padding(TrueSize), SeekOrigin.Current) - temp_Int65; //temp_BinaryReader2.BaseStream.Seek(FitsUtil.padding(TrueSize), IO.SeekOrigin.Current) - temp_Int65; int generatedAux2 = (int)temp_Int65; } catch(IOException e) { throw new FitsException("Error reading binary table data:" + e); } }
/// <summary>Read the data -- or defer reading on random access</summary> public override void Read(ArrayDataIO i) { SetFileOffset(i); currInput = i; if (i is RandomAccess) { try { //BinaryReader temp_BinaryReader; Int64 temp_Int64; //temp_BinaryReader = i; temp_Int64 = i.Position;//temp_BinaryReader.BaseStream.Position; temp_Int64 = i.Seek(TrueSize, SeekOrigin.Current) - temp_Int64; //temp_BinaryReader.BaseStream.Seek(TrueSize, IO.SeekOrigin.Current) - temp_Int64; int generatedAux = (int)temp_Int64; //IO.BinaryReader temp_BinaryReader2; Int64 temp_Int65; //temp_BinaryReader2 = i; temp_Int65 = i.Position;//temp_BinaryReader2.BaseStream.Position; temp_Int65 = i.Seek(FitsUtil.Padding(TrueSize), SeekOrigin.Current) - temp_Int65;//temp_BinaryReader2.BaseStream.Seek(FitsUtil.padding(TrueSize), IO.SeekOrigin.Current) - temp_Int65; int generatedAux2 = (int)temp_Int65; } catch(IOException e) { throw new FitsException("Unable to skip binary table HDU:" + e); } } else { if (table == null) { table = CreateTable(); } ReadTrueData(i); } }
/// <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> /// 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> /// 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>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>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; }