KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jxl > read > biff > File


1 /*********************************************************************
2 *
3 * Copyright (C) 2002 Andrew Khan
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ***************************************************************************/

19
20 package jxl.read.biff;
21
22 import java.io.InputStream JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.InterruptedIOException JavaDoc;
25 import java.io.FileOutputStream JavaDoc;
26
27 import common.Logger;
28
29 import jxl.WorkbookSettings;
30 import jxl.biff.IntegerHelper;
31 import jxl.biff.Type;
32 import jxl.biff.BaseCompoundFile;
33
34 /**
35  * File containing the data from the binary stream
36  */

37 public class File
38 {
39   /**
40    * The logger
41    */

42   private static Logger logger = Logger.getLogger(File.class);
43
44   /**
45    * The data from the excel 97 file
46    */

47   private byte[] data;
48   /**
49    * The current position within the file
50    */

51   private int filePos;
52   /**
53    * The saved pos
54    */

55   private int oldPos;
56   /**
57    * The initial file size
58    */

59   private int initialFileSize;
60   /**
61    * The amount to increase the growable array by
62    */

63   private int arrayGrowSize;
64   /**
65    * A handle to the compound file. This is only preserved when the
66    * copying of PropertySets is enabled
67    */

68   private CompoundFile compoundFile;
69   /**
70    * The workbook settings
71    */

72   private WorkbookSettings workbookSettings;
73
74   /**
75    * Constructs a file from the input stream
76    *
77    * @param is the input stream
78    * @param ws the workbook settings
79    * @exception IOException
80    * @exception BiffException
81    */

82   public File(InputStream JavaDoc is, WorkbookSettings ws)
83     throws IOException JavaDoc, BiffException
84   {
85     // Initialize the file sizing parameters from the settings
86
workbookSettings = ws;
87     initialFileSize = workbookSettings.getInitialFileSize();
88     arrayGrowSize = workbookSettings.getArrayGrowSize();
89
90     byte[] d = new byte[initialFileSize];
91     int bytesRead = is.read(d);
92     int pos = bytesRead;
93
94     // Handle thread interruptions, in case the user keeps pressing
95
// the Submit button from a browser. Thanks to Mike Smith for this
96
if (Thread.currentThread().isInterrupted())
97     {
98       throw new InterruptedIOException JavaDoc();
99     }
100
101     while (bytesRead != -1)
102     {
103       if (pos >= d.length)
104       {
105         // Grow the array
106
byte[] newArray = new byte[d.length + arrayGrowSize];
107         System.arraycopy(d, 0, newArray, 0, d.length);
108         d = newArray;
109       }
110       bytesRead = is.read(d, pos, d.length - pos);
111       pos += bytesRead;
112
113       if (Thread.currentThread().isInterrupted())
114       {
115         throw new InterruptedIOException JavaDoc();
116       }
117     }
118
119     bytesRead = pos + 1;
120
121     // Perform file reading checks and throw exceptions as necessary
122
if (bytesRead == 0)
123     {
124       throw new BiffException(BiffException.excelFileNotFound);
125     }
126
127     CompoundFile cf = new CompoundFile(d, ws);
128     try
129     {
130       data = cf.getStream("workbook");
131     }
132     catch (BiffException e)
133     {
134       // this might be in excel 95 format - try again
135
data = cf.getStream("book");
136     }
137
138     if (!workbookSettings.getPropertySetsDisabled() &&
139         (cf.getPropertySetNames().length >
140          BaseCompoundFile.STANDARD_PROPERTY_SETS.length))
141     {
142       compoundFile = cf;
143     }
144
145     cf = null;
146
147     if (!workbookSettings.getGCDisabled())
148     {
149       System.gc();
150     }
151
152     // Uncomment the following lines to send the pure workbook stream
153
// (ie. a defragged ole stream) to an output file
154

155 // FileOutputStream fos = new FileOutputStream("defraggedxls");
156
// fos.write(data);
157
// fos.close();
158

159   }
160
161   /**
162    * Constructs a file from already defragged binary data. Useful for
163    * displaying subportions of excel streams. This is only used during
164    * special runs of the "BiffDump" demo program and should not be invoked
165    * as part of standard JExcelApi parsing
166    *
167    * @param d the already parsed data
168    */

169   public File(byte[] d)
170   {
171     data = d;
172   }
173
174   /**
175    * Returns the next data record and increments the pointer
176    *
177    * @return the next data record
178    */

179   Record next()
180   {
181     Record r = new Record(data, filePos, this);
182     return r;
183   }
184
185   /**
186    * Peek ahead to the next record, without incrementing the file position
187    *
188    * @return the next record
189    */

190   Record peek()
191   {
192     int tempPos = filePos;
193     Record r = new Record(data, filePos, this);
194     filePos = tempPos;
195     return r;
196   }
197
198   /**
199    * Skips forward the specified number of bytes
200    *
201    * @param bytes the number of bytes to skip forward
202    */

203   public void skip(int bytes)
204   {
205     filePos += bytes;
206   }
207
208   /**
209    * Copies the bytes into a new array and returns it.
210    *
211    * @param pos the position to read from
212    * @param length the number of bytes to read
213    * @return The bytes read
214    */

215   public byte[] read(int pos, int length)
216   {
217     byte[] ret = new byte[length];
218     try
219     {
220       System.arraycopy(data, pos, ret, 0, length);
221     }
222     catch (ArrayIndexOutOfBoundsException JavaDoc e)
223     {
224       logger.error("Array index out of bounds at position " + pos +
225                    " record length " + length);
226       throw e;
227     }
228     return ret;
229   }
230
231   /**
232    * Gets the position in the stream
233    *
234    * @return the position in the stream
235    */

236   public int getPos()
237   {
238     return filePos;
239   }
240
241   /**
242    * Saves the current position and temporarily sets the position to be the
243    * new one. The original position may be restored usind the restorePos()
244    * method. This is used when reading in the cell values of the sheet - an
245    * addition in 1.6 for memory allocation reasons.
246    *
247    * These methods are used by the SheetImpl.readSheet() when it is reading
248    * in all the cell values
249    *
250    * @param p the temporary position
251    */

252   public void setPos(int p)
253   {
254     oldPos = filePos;
255     filePos = p;
256   }
257
258   /**
259    * Restores the original position
260    *
261    * These methods are used by the SheetImpl.readSheet() when it is reading
262    * in all the cell values
263    */

264   public void restorePos()
265   {
266     filePos = oldPos;
267   }
268
269   /**
270    * Moves to the first bof in the file
271    */

272   private void moveToFirstBof()
273   {
274     boolean bofFound = false;
275     while (!bofFound)
276     {
277       int code = IntegerHelper.getInt(data[filePos], data[filePos + 1]);
278       if (code == Type.BOF.value)
279       {
280         bofFound = true;
281       }
282       else
283       {
284         skip(128);
285       }
286     }
287   }
288
289   /**
290    * "Closes" the biff file
291    *
292    * @deprecated As of version 1.6 use workbook.close() instead
293    */

294   public void close()
295   {
296   }
297
298   /**
299    * Clears the contents of the file
300    */

301   public void clear()
302   {
303     data = null;
304   }
305
306   /**
307    * Determines if the current position exceeds the end of the file
308    *
309    * @return TRUE if there is more data left in the array, FALSE otherwise
310    */

311   public boolean hasNext()
312   {
313     // Allow four bytes for the record code and its length
314
return filePos < data.length - 4;
315   }
316
317   /**
318    * Accessor for the compound file. The returned value will only be non-null
319    * if the property sets feature is enabled and the workbook contains
320    * additional property sets
321    *
322    * @return the compound file
323    */

324   CompoundFile getCompoundFile()
325   {
326     return compoundFile;
327   }
328 }
329
Popular Tags