View Javadoc
1   /*
2    * #%L
3    * nom.tam FITS library
4    * %%
5    * Copyright (C) 2004 - 2024 nom-tam-fits
6    * %%
7    * This is free and unencumbered software released into the public domain.
8    *
9    * Anyone is free to copy, modify, publish, use, compile, sell, or
10   * distribute this software, either in source code form or as a compiled
11   * binary, for any purpose, commercial or non-commercial, and by any
12   * means.
13   *
14   * In jurisdictions that recognize copyright laws, the author or authors
15   * of this software dedicate any and all copyright interest in the
16   * software to the public domain. We make this dedication for the benefit
17   * of the public at large and to the detriment of our heirs and
18   * successors. We intend this dedication to be an overt act of
19   * relinquishment in perpetuity of all present and future rights to this
20   * software under copyright law.
21   *
22   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23   * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25   * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
26   * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27   * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28   * OTHER DEALINGS IN THE SOFTWARE.
29   * #L%
30   */
31  package nom.tam.util;
32  
33  import java.io.DataOutput;
34  import java.io.DataOutputStream;
35  import java.io.IOException;
36  import java.io.OutputStream;
37  
38  /**
39   * For writing FITS files through an {@link OutputStream}.
40   * <p>
41   * Testing and timing for this class is performed in the nom.tam.util.test.BufferedFileTester class.
42   * <p>
43   * Version 2.0 -- October 30, 2021: Completely overhauled, with new name and hierarchy. Performance is 2-4 times better
44   * than before. (Attila Kovacs)
45   *
46   * @see FitsInputStream
47   * @see FitsFile
48   */
49  @SuppressWarnings("deprecation")
50  public class FitsOutputStream extends ArrayOutputStream implements FitsOutput {
51  
52      /** the output, as accessible via the <code>DataInput</code> interface */
53      private final DataOutput data;
54  
55      /** Unencoded output byte count */
56      private int unencodedCount;
57  
58      /** For thread synchronization */
59      private Object lock = new Object();
60  
61      /**
62       * Use the BufferedOutputStream constructor
63       *
64       * @param o An open output stream.
65       */
66      public FitsOutputStream(OutputStream o) {
67          this(o, FitsIO.DEFAULT_BUFFER_SIZE);
68      }
69  
70      /**
71       * Use the BufferedOutputStream constructor
72       *
73       * @param o         An open output stream.
74       * @param bufLength The buffer size.
75       */
76      public FitsOutputStream(OutputStream o, int bufLength) {
77          super(o, bufLength);
78          setEncoder(new FitsEncoder(this));
79          if (o instanceof DataOutput) {
80              data = (DataOutput) o;
81          } else {
82              data = new DataOutputStream(o);
83          }
84      }
85  
86      @Override
87      protected FitsEncoder getEncoder() {
88          return (FitsEncoder) super.getEncoder();
89      }
90  
91      @Override
92      public synchronized void write(int b) throws IOException {
93          synchronized (lock) {
94              super.write(b);
95              unencodedCount++;
96          }
97      }
98  
99      @Override
100     public synchronized void write(byte[] b, int start, int length) throws IOException {
101         synchronized (lock) {
102             super.write(b, start, length);
103             unencodedCount += length;
104         }
105     }
106 
107     @Override
108     public void write(boolean[] b, int start, int length) throws IOException {
109         getEncoder().write(b, start, length);
110     }
111 
112     @Override
113     public void write(Boolean[] buf, int offset, int size) throws IOException {
114         getEncoder().write(buf, offset, size);
115     }
116 
117     @Override
118     public void write(char[] c, int start, int length) throws IOException {
119         getEncoder().write(c, start, length);
120     }
121 
122     @Override
123     public void write(short[] s, int start, int length) throws IOException {
124         getEncoder().write(s, start, length);
125     }
126 
127     @Override
128     public void write(int[] i, int start, int length) throws IOException {
129         getEncoder().write(i, start, length);
130     }
131 
132     @Override
133     public void write(long[] l, int start, int length) throws IOException {
134         getEncoder().write(l, start, length);
135     }
136 
137     @Override
138     public void write(float[] f, int start, int length) throws IOException {
139         getEncoder().write(f, start, length);
140     }
141 
142     @Override
143     public void write(double[] d, int start, int length) throws IOException {
144         getEncoder().write(d, start, length);
145     }
146 
147     @Override
148     public void writeBytes(String s) throws IOException {
149         getEncoder().writeBytes(s);
150     }
151 
152     @Override
153     public void writeChars(String s) throws IOException {
154         getEncoder().writeChars(s);
155     }
156 
157     @Override
158     public void writeUTF(String s) throws IOException {
159         data.writeUTF(s);
160     }
161 
162     @Override
163     public void write(String[] s, int start, int len) throws IOException {
164         getEncoder().write(s, start, len);
165     }
166 
167     @Override
168     public void writeByte(int b) throws IOException {
169         getEncoder().writeByte(b);
170     }
171 
172     @Override
173     public void writeBoolean(boolean b) throws IOException {
174         getEncoder().writeBoolean(b);
175     }
176 
177     @Override
178     public void writeChar(int c) throws IOException {
179         getEncoder().writeChar(c);
180     }
181 
182     @Override
183     public void writeShort(int s) throws IOException {
184         getEncoder().writeShort(s);
185     }
186 
187     @Override
188     public void writeInt(int i) throws IOException {
189         getEncoder().writeInt(i);
190     }
191 
192     @Override
193     public void writeLong(long l) throws IOException {
194         getEncoder().writeLong(l);
195     }
196 
197     @Override
198     public void writeFloat(float f) throws IOException {
199         getEncoder().writeFloat(f);
200     }
201 
202     @Override
203     public void writeDouble(double d) throws IOException {
204         getEncoder().writeDouble(d);
205     }
206 
207     /**
208      * Deprecated use {@link #writeArray(Object)}.
209      *
210      * @param      o           The object to be written.
211      *
212      * @throws     IOException if one of the underlying write operations failed
213      *
214      * @deprecated             use {@link #writeArray(Object)} instead
215      */
216     @Deprecated
217     public final void writePrimitiveArray(Object o) throws IOException {
218         writeArray(o);
219     }
220 
221     @Override
222     public boolean isAtStart() {
223         return (unencodedCount + getEncoder().getCount()) == 0;
224     }
225 
226 }