001/*****************************************************************************
002 * Copyright by The HDF Group.                                               *
003 * Copyright by the Board of Trustees of the University of Illinois.         *
004 * All rights reserved.                                                      *
005 *                                                                           *
006 * This file is part of the HDF Java Products distribution.                  *
007 * The full copyright notice, including terms governing use, modification,   *
008 * and redistribution, is contained in the files COPYING and Copyright.html. *
009 * COPYING can be found at the root of the source code distribution tree.    *
010 * Or, see http://hdfgroup.org/products/hdf-java/doc/Copyright.html.         *
011 * If you do not have access to either file, you may request a copy from     *
012 * help@hdfgroup.org.                                                        *
013 ****************************************************************************/
014
015package hdf.view;
016
017import java.io.BufferedInputStream;
018import java.io.BufferedOutputStream;
019import java.io.File;
020import java.io.FileInputStream;
021import java.io.FileOutputStream;
022import java.io.RandomAccessFile;
023import java.util.Enumeration;
024import java.util.Hashtable;
025import java.util.StringTokenizer;
026
027import javax.swing.filechooser.FileFilter;
028
029/**
030 * A convenience implementation of FileFilter that filters out all files except
031 * for those type extensions that it knows about.
032 * 
033 * @author Peter X. Cao
034 * @version 2.4 9/6/2007
035 */
036public class DefaultFileFilter extends FileFilter {
037    private static FileFilter FILE_FILTER_HDF = null;
038    private static FileFilter FILE_FILTER_HDF4 = null;
039    private static FileFilter FILE_FILTER_HDF5 = null;
040    private static FileFilter FILE_FILTER_JPEG = null;
041    private static FileFilter FILE_FILTER_TIFF = null;
042    private static FileFilter FILE_FILTER_PNG = null;
043    private static FileFilter FILE_FILTER_GIF = null;
044    private static FileFilter FILE_FILTER_BMP = null;
045    private static FileFilter FILE_FILTER_IMG = null;
046    private static FileFilter FILE_FILTER_TEXT = null;
047    private static FileFilter FILE_FILTER_BINARY = null;
048
049    private static String fileExtension = ViewProperties.getFileExtension();
050
051    private Hashtable<String, DefaultFileFilter> filters = null;
052    private String description = null;
053    private String fullDescription = null;
054    private boolean useExtensionsInDescription = true;
055
056    /**
057     * Creates a file filter. If no filters are added, then all files are
058     * accepted.
059     * 
060     * @see #addExtension
061     */
062    public DefaultFileFilter() {
063        this.filters = new Hashtable<String, DefaultFileFilter>();
064    }
065
066    /**
067     * Creates a file filter that accepts files with the given extension.
068     * Example: new DefaultFileFilter("jpg");
069     * 
070     * @param extension The extension for this FileFilter to filter by
071     * 
072     * @see #addExtension
073     */
074    public DefaultFileFilter(String extension) {
075        this(extension, null);
076    }
077
078    /**
079     * Creates a file filter that accepts the given file type. Example: new
080     * DefaultFileFilter("jpg", "JPEG Image Images");
081     * 
082     * Note that the "." before the extension is not needed. If provided, it
083     * will be ignored.
084     * 
085     * @param extension The extension for this FileFilter to filter by
086     * 
087     * @param description The human readable description of this FileFilter
088     * 
089     * @see #addExtension
090     */
091    public DefaultFileFilter(String extension, String description) {
092        this();
093        if (extension != null) {
094            addExtension(extension);
095        }
096        if (description != null) {
097            setDescription(description);
098        }
099    }
100
101    /**
102     * Creates a file filter from the given string array. Example: new
103     * DefaultFileFilter(String {"gif", "jpg"});
104     * 
105     * Note that the "." before the extension is not needed adn will be ignored.
106     * 
107     * @param filters The array of extensions for this FileFilter to filter by
108     * 
109     * @see #addExtension
110     */
111    public DefaultFileFilter(String[] filters) {
112        this(filters, null);
113    }
114
115    /**
116     * Creates a file filter from the given string array and description.
117     * Example: new DefaultFileFilter(String {"gif", "jpg"},
118     * "Gif and JPG Images");
119     * 
120     * Note that the "." before the extension is not needed and will be ignored.
121     * 
122     * @param filters The array of extensions for this FileFilter to filter by
123     * 
124     * @param description The human readable description of this FileFilter
125     * 
126     * @see #addExtension
127     */
128    public DefaultFileFilter(String[] filters, String description) {
129        this();
130        for (int i = 0; i < filters.length; i++) {
131            // add filters one by one
132            addExtension(filters[i]);
133        }
134        if (description != null) {
135            setDescription(description);
136        }
137    }
138
139    /**
140     * Return true if this file should be shown in the directory pane, false if
141     * it shouldn't.
142     * 
143     * Files that begin with "." are ignored.
144     * 
145     * @see #getExtension
146     */
147    @Override
148        public boolean accept(File f) {
149        if (f != null) {
150            if (f.isDirectory()) {
151                return true;
152            }
153            String extension = getExtension(f);
154            if ((extension != null) && (filters.get(getExtension(f)) != null)) {
155                return true;
156            }
157        }
158
159        return false;
160    }
161
162    /**
163     * Return the extension portion of the file's name.
164     * 
165     * @param f The file to get the extension portion of the name for
166     * 
167     * @return The extension portion of the given file's name
168     * 
169     * @see #getExtension
170     * @see FileFilter#accept
171     */
172    public String getExtension(File f) {
173        if (f != null) {
174            String filename = f.getName();
175            int i = filename.lastIndexOf('.');
176            if ((i > 0) && (i < filename.length() - 1)) {
177                return filename.substring(i + 1).toLowerCase();
178            }
179        }
180        return null;
181    }
182
183    /**
184     * Adds a filetype "dot" extension to filter against.
185     * 
186     * For example: the following code will create a filter that filters out all
187     * files except those that end in ".jpg" and ".tif":
188     * 
189     * DefaultFileFilter filter = new DefaultFileFilter();
190     * filter.addExtension("jpg"); filter.addExtension("tif"); or
191     * filter.addExtension("jpg, tif");
192     * 
193     * Note that the "." before the extension is not needed and will be ignored.
194     * 
195     * @param extension The "dot" extension to add
196     */
197    public void addExtension(String extension) {
198        if (filters == null) {
199            filters = new Hashtable<String, DefaultFileFilter>(5);
200        }
201
202        String ext = null;
203        StringTokenizer st = new StringTokenizer(extension, ",");
204        while (st.hasMoreElements()) {
205            ext = st.nextToken().trim();
206            filters.put(ext.toLowerCase(), this);
207        }
208        fullDescription = null;
209    }
210
211    /**
212     * Returns the human readable description of this filter. For example:
213     * "JPEG and GIF Image Files (*.jpg, *.gif)"
214     */
215    @Override
216        public String getDescription() {
217        if (fullDescription == null) {
218            if ((description == null) || isExtensionListInDescription()) {
219                fullDescription = description == null ? "(" : description
220                        + " (";
221                // build the description from the extension list
222                Enumeration<String> extensions = filters.keys();
223                if (extensions != null) {
224
225                    if (!extensions.hasMoreElements()) {
226                        fullDescription = null;
227                        return null;
228                    }
229
230                    fullDescription += "." + extensions.nextElement();
231                    while (extensions.hasMoreElements()) {
232                        fullDescription += ", "
233                                + extensions.nextElement();
234                    }
235                }
236                fullDescription += ")";
237            }
238            else {
239                fullDescription = description;
240            }
241        }
242        return fullDescription;
243    }
244
245    /**
246     * Sets the human readable description of this filter. For example:
247     * filter.setDescription("Gif and JPG Images");
248     * 
249     * @param description The human readable description to set for this filter
250     */
251    public void setDescription(String description) {
252        this.description = description;
253        fullDescription = null;
254    }
255
256    /**
257     * Determines whether the extension list (.jpg, .gif, etc) should show up in
258     * the human readable description.
259     * 
260     * Only relevant if a description was provided in the constructor or using
261     * setDescription();
262     * 
263     * @param b Sets extension list to show up in the human readable description
264     *          if true; list doesn't show up otherwise
265     */
266    public void setExtensionListInDescription(boolean b) {
267        useExtensionsInDescription = b;
268        fullDescription = null;
269    }
270
271    /**
272     * Returns whether the extension list (.jpg, .gif, etc) should show up in
273     * the human readable description.
274     * 
275     * Only relevant if a description was provided in the constructor or using
276     * setDescription();
277     * 
278     * @return True if the extension list should show up in the human readable
279     *              description; false otherwise
280     */
281    public boolean isExtensionListInDescription() {
282        return useExtensionsInDescription;
283    }
284
285    /**
286     * Returns a file filter for HDF4/5 file.
287     * 
288     * @return A FileFilter for HDF4/5 files
289     */
290    public static FileFilter getFileFilter() {
291        boolean extensionNotChanged = (fileExtension
292                .equalsIgnoreCase(ViewProperties.getFileExtension()));
293
294        if ((FILE_FILTER_HDF != null) && extensionNotChanged) {
295            return FILE_FILTER_HDF;
296        }
297
298        // update extensions
299        fileExtension = ViewProperties.getFileExtension();
300
301        DefaultFileFilter filter = new DefaultFileFilter();
302        filter.setDescription("HDF & more");
303
304        filter.addExtension(fileExtension);
305
306        return (FILE_FILTER_HDF = filter);
307    }
308
309    /**
310     * Returns a file filter for HDF4 file.
311     * 
312     * @return A FileFilter for HDF4 files
313     */
314    public static FileFilter getFileFilterHDF4() {
315        if (FILE_FILTER_HDF4 != null) {
316            return FILE_FILTER_HDF4;
317        }
318
319        DefaultFileFilter filter = new DefaultFileFilter();
320        filter.addExtension("hdf");
321        filter.addExtension("h4");
322        filter.addExtension("hdf4");
323        filter.setDescription("HDF4 files");
324        FILE_FILTER_HDF4 = filter;
325
326        return FILE_FILTER_HDF4;
327    }
328
329    /**
330     * Returns a file filter for HDF5 file.
331     * 
332     * @return A FileFilter for HDF5 files
333     */
334    public static FileFilter getFileFilterHDF5() {
335        if (FILE_FILTER_HDF5 != null) {
336            return FILE_FILTER_HDF5;
337        }
338
339        DefaultFileFilter filter = new DefaultFileFilter();
340        filter.addExtension("h5");
341        filter.addExtension("hdf5");
342        filter.setDescription("HDF5 files");
343        FILE_FILTER_HDF5 = filter;
344
345        return FILE_FILTER_HDF5;
346    }
347
348    /**
349     * Returns a file filter for JPEG image files.
350     * 
351     * @return A FileFilter for JPEG image files
352     */
353    public static FileFilter getFileFilterJPEG() {
354        if (FILE_FILTER_JPEG != null) {
355            return FILE_FILTER_JPEG;
356        }
357
358        DefaultFileFilter filter = new DefaultFileFilter();
359        filter.addExtension("jpg");
360        filter.addExtension("jpeg");
361        filter.addExtension("jpe");
362        filter.addExtension("jif");
363        filter.addExtension("jfif");
364        filter.addExtension("jfi");
365        filter.setDescription("JPEG images");
366        FILE_FILTER_JPEG = filter;
367
368        return FILE_FILTER_JPEG;
369    }
370
371    /**
372     * Returns a file filter for TIFF image files.
373     * 
374     * @return A FileFilter for TIFF image files
375     */
376    public static FileFilter getFileFilterTIFF() {
377        if (FILE_FILTER_TIFF != null) {
378            return FILE_FILTER_TIFF;
379        }
380
381        DefaultFileFilter filter = new DefaultFileFilter();
382        filter.addExtension("tif");
383        filter.addExtension("tiff");
384        filter.setDescription("TIFF images");
385        FILE_FILTER_TIFF = filter;
386
387        return FILE_FILTER_TIFF;
388    }
389
390    /**
391     * Returns a file filter for PNG image files.
392     * 
393     * @return A FileFilter for PNG image files
394     */
395    public static FileFilter getFileFilterPNG() {
396        if (FILE_FILTER_PNG != null) {
397            return FILE_FILTER_PNG;
398        }
399
400        DefaultFileFilter filter = new DefaultFileFilter();
401        filter.addExtension("png");
402        filter.setDescription("PNG images");
403        FILE_FILTER_PNG = filter;
404
405        return FILE_FILTER_PNG;
406    }
407
408    /**
409     * Returns a file filter for BMP image files.
410     * 
411     * @return A FileFilter for BMP image files
412     */
413    public static FileFilter getFileFilterBMP() {
414        if (FILE_FILTER_BMP != null) {
415            return FILE_FILTER_BMP;
416        }
417
418        DefaultFileFilter filter = new DefaultFileFilter();
419        filter.addExtension("bmp");
420        filter.addExtension("dib");
421        filter.setDescription("BMP images");
422        FILE_FILTER_BMP = filter;
423
424        return FILE_FILTER_BMP;
425    }
426
427    /**
428     * Returns a file filter for GIF image files.
429     * 
430     * @return A FileFilter for GIF image files
431     */
432    public static FileFilter getFileFilterGIF() {
433        if (FILE_FILTER_GIF != null) {
434            return FILE_FILTER_GIF;
435        }
436
437        DefaultFileFilter filter = new DefaultFileFilter();
438        filter.addExtension("gif");
439        filter.setDescription("GIF images");
440        FILE_FILTER_GIF = filter;
441
442        return FILE_FILTER_GIF;
443    }
444
445    /**
446     * Returns a file filter for GIF, JPEG, BMP, or PNG image files.
447     * 
448     * @return A FileFilter for GIF, JPEG, BMP, or PNG image files
449     */
450    public static FileFilter getImageFileFilter() {
451        if (FILE_FILTER_IMG != null) {
452            return FILE_FILTER_IMG;
453        }
454
455        DefaultFileFilter filter = new DefaultFileFilter();
456        filter.addExtension("jpg");
457        filter.addExtension("jpeg");
458        filter.addExtension("jpe");
459        filter.addExtension("jif");
460        filter.addExtension("jfif");
461        filter.addExtension("jfi");
462        filter.addExtension("png");
463        filter.addExtension("gif");
464        filter.addExtension("bmp");
465        filter.addExtension("dib");
466        filter.setDescription("GIF, JPEG, BMP, or PNG images");
467        FILE_FILTER_IMG = filter;
468
469        return FILE_FILTER_IMG;
470    }
471
472    /**
473     * Returns a file filter for text files.
474     * 
475     * @return A FileFilter for text files
476     */
477    public static FileFilter getFileFilterText() {
478        if (FILE_FILTER_TEXT != null) {
479            return FILE_FILTER_TEXT;
480        }
481
482        DefaultFileFilter filter = new DefaultFileFilter();
483        filter.addExtension("txt");
484        filter.addExtension("text");
485        filter.setDescription("Text");
486        FILE_FILTER_TEXT = filter;
487
488        return FILE_FILTER_TEXT;
489    }
490    
491    /**
492     * Returns a file filter for binary files.
493     * 
494     * @return A FileFilter for binary files
495     */
496    public static FileFilter getFileFilterBinary() {
497        if (FILE_FILTER_BINARY != null) {
498            return FILE_FILTER_BINARY;
499        }
500
501        DefaultFileFilter filter = new DefaultFileFilter();
502        filter.addExtension("bin");
503        filter.setDescription("Binary");
504        FILE_FILTER_BINARY = filter;
505
506        return FILE_FILTER_BINARY;
507    }
508
509    /**
510     * look at the first 4 bytes of the file to see if it is an HDF4 file.
511     * byte[0]=14, byte[1]=3, byte[2]=19, byte[3]=1 or if it is a netCDF file
512     * byte[0]=67, byte[1]=68, byte[2]=70, byte[3]=1 or
513     * 
514     * @param filename The name of the file to check
515     * 
516     * @return true if the specified file is an HDF4 file; false otherwise
517     */
518    public static boolean isHDF4(String filename) {
519        boolean ish4 = false;
520        RandomAccessFile raf = null;
521
522        try {
523            raf = new RandomAccessFile(filename, "r");
524        }
525        catch (Exception ex) {
526            raf = null;
527        }
528
529        if (raf == null) {
530            return false;
531        }
532
533        byte[] header = new byte[4];
534        try {
535            raf.read(header);
536        }
537        catch (Exception ex) {
538            header = null;
539        }
540
541        if (header != null) {
542            if (
543            // HDF4
544            ((header[0] == 14) && (header[1] == 3) && (header[2] == 19) && (header[3] == 1))
545            /*
546             * // netCDF || (header[0]==67 && header[1]==68 && header[2]==70 &&
547             * header[3]==1)
548             */
549            ) {
550                ish4 = true;
551            }
552            else {
553                ish4 = false;
554            }
555        }
556
557        try {
558            raf.close();
559        }
560        catch (Exception ex) {
561        }
562
563        return ish4;
564    }
565
566    /**
567     * look at the first 8 bytes of the file to see if it is an HDF5 file.
568     * byte[0]=-199 which is 137 in unsigned byte, byte[1]=72, byte[2]=68,
569     * byte[3]=70, byte[4]=13, byte[5]=10, byte[6]=26, byte[7]=10
570     * 
571     * @param filename The name of the file to check
572     * 
573     * @return true if the specified file is an HDF5 file; false otherwise
574     */
575    public static boolean isHDF5(String filename) {
576        boolean ish5 = false;
577        RandomAccessFile raf = null;
578
579        try {
580            raf = new RandomAccessFile(filename, "r");
581        }
582        catch (Exception ex) {
583            raf = null;
584        }
585
586        if (raf == null) {
587            return false;
588        }
589
590        byte[] header = new byte[8];
591        long fileSize = 0;
592        try {
593            fileSize = raf.length();
594        }
595        catch (Exception ex) {
596        }
597
598        // The super block is located by searching for the HDF5 file signature
599        // at byte offset 0, byte offset 512 and at successive locations in the
600        // file, each a multiple of two of the previous location, i.e. 0, 512,
601        // 1024, 2048, etc
602        long offset = 0;
603        while (!ish5 && (offset < fileSize)) {
604            try {
605                raf.seek(offset);
606                raf.read(header);
607            }
608            catch (Exception ex) {
609                header = null;
610            }
611
612            if ((header[0] == -119) && (header[1] == 72) && (header[2] == 68)
613                    && (header[3] == 70) && (header[4] == 13)
614                    && (header[5] == 10) && (header[6] == 26)
615                    && (header[7] == 10)) {
616                ish5 = true;
617            }
618            else {
619                ish5 = false;
620                if (offset == 0) {
621                    offset = 512;
622                }
623                else {
624                    offset *= 2;
625                }
626            }
627        }
628
629        try {
630            raf.close();
631        }
632        catch (Exception ex) {
633        }
634
635        return ish5;
636    }
637
638    /**
639     * look at the first 4 bytes of the file to see if it is a netCDF file
640     * byte[0]=67, byte[1]=68, byte[2]=70, byte[3]=1 or
641     * 
642     * @param filename The name of the file to check
643     * 
644     * @return true if the specified file is a NetCDF file; false otherwise
645     */
646    public static boolean isNetcdf(String filename) {
647        boolean isnc = false;
648        RandomAccessFile raf = null;
649
650        try {
651            raf = new RandomAccessFile(filename, "r");
652        }
653        catch (Exception ex) {
654            raf = null;
655        }
656
657        if (raf == null) {
658            return false;
659        }
660
661        byte[] header = new byte[4];
662        try {
663            raf.read(header);
664        }
665        catch (Exception ex) {
666            header = null;
667        }
668
669        if (header != null) {
670            if (
671            // netCDF
672            (header[0] == 67) && (header[1] == 68) && (header[2] == 70)
673                    && (header[3] == 1)) {
674                isnc = true;
675            }
676            else {
677                isnc = false;
678            }
679        }
680
681        try {
682            raf.close();
683        }
684        catch (Exception ex) {
685        }
686
687        return isnc;
688    }
689
690    /**
691     * Read HDF5 user block data into byte array.
692     * 
693     * @param filename The name of the file to read the HDF5 user block from
694     * 
695     * @return a byte array of user block, or null if there is user data.
696     */
697    public static byte[] getHDF5UserBlock(String filename) {
698        byte[] userBlock = null;
699        RandomAccessFile raf = null;
700
701        try {
702            raf = new RandomAccessFile(filename, "r");
703        }
704        catch (Exception ex) {
705            try {
706                raf.close();
707            }
708            catch (Throwable err) {
709                ;
710            }
711            raf = null;
712        }
713
714        if (raf == null) {
715            return null;
716        }
717
718        byte[] header = new byte[8];
719        long fileSize = 0;
720        try {
721            fileSize = raf.length();
722        }
723        catch (Exception ex) {
724            fileSize = 0;
725        }
726        if (fileSize <= 0) {
727            try {
728                raf.close();
729            }
730            catch (Throwable err) {
731                ;
732            }
733            return null;
734        }
735
736        // The super block is located by searching for the HDF5 file signature
737        // at byte offset 0, byte offset 512 and at successive locations in the
738        // file, each a multiple of two of the previous location, i.e. 0, 512,
739        // 1024, 2048, etc
740        long offset = 0;
741        boolean ish5 = false;
742        while (offset < fileSize) {
743            try {
744                raf.seek(offset);
745                raf.read(header);
746            }
747            catch (Exception ex) {
748                header = null;
749            }
750
751            if ((header[0] == -119) && (header[1] == 72) && (header[2] == 68)
752                    && (header[3] == 70) && (header[4] == 13)
753                    && (header[5] == 10) && (header[6] == 26)
754                    && (header[7] == 10)) {
755                ish5 = true;
756                break; // find the end of user block
757            }
758            else {
759                ish5 = false;
760                if (offset == 0) {
761                    offset = 512;
762                }
763                else {
764                    offset *= 2;
765                }
766            }
767        }
768
769        if (!ish5 || (offset == 0)) {
770            try {
771                raf.close();
772            }
773            catch (Throwable err) {
774                ;
775            }
776            return null;
777        }
778
779        int blockSize = (int) offset;
780        userBlock = new byte[blockSize];
781        try {
782            raf.seek(0);
783            raf.read(userBlock, 0, blockSize);
784        }
785        catch (Exception ex) {
786            userBlock = null;
787        }
788
789        try {
790            raf.close();
791        }
792        catch (Exception ex) {
793        }
794
795        return userBlock;
796    }
797
798    /**
799     * Write HDF5 user block data into byte array.
800     * 
801     * @param fin The name of the file to copy to the output file
802     * 
803     * @param fout The name of the file to write HDF5 user block data to
804     * 
805     * @param buf The HDF5 user block data to write into the output file
806     * 
807     * @return a byte array of user block, or null if there is user data.
808     */
809    public static boolean setHDF5UserBlock(String fin, String fout, byte[] buf) {
810        boolean ish5 = false;
811
812        if ((buf == null) || (buf.length <= 0)) {
813            return false;
814        }
815
816        File tmpFile = new File(fin);
817        if (!tmpFile.exists()) {
818            return false;
819        }
820
821        // find the end of user block for the input file;
822        RandomAccessFile raf = null;
823        try {
824            raf = new RandomAccessFile(fin, "r");
825        }
826        catch (Exception ex) {
827            raf = null;
828        }
829
830        if (raf == null) {
831            return false;
832        }
833
834        byte[] header = new byte[8];
835        long fileSize = 0;
836        try {
837            fileSize = raf.length();
838        }
839        catch (Exception ex) {
840            fileSize = 0;
841        }
842        try {
843            fileSize = raf.length();
844        }
845        catch (Exception ex) {
846            fileSize = 0;
847        }
848        if (fileSize <= 0) {
849            try {
850                raf.close();
851            }
852            catch (Throwable err) {
853                ;
854            }
855            return false;
856        }
857
858        // The super block is located by searching for the HDF5 file signature
859        // at byte offset 0, byte offset 512 and at successive locations in the
860        // file, each a multiple of two of the previous location, i.e. 0, 512,
861        // 1024, 2048, etc
862        long offset = 0;
863        while (offset < fileSize) {
864            try {
865                raf.seek(offset);
866                raf.read(header);
867            }
868            catch (Exception ex) {
869                header = null;
870            }
871
872            if ((header[0] == -119) && (header[1] == 72) && (header[2] == 68)
873                    && (header[3] == 70) && (header[4] == 13)
874                    && (header[5] == 10) && (header[6] == 26)
875                    && (header[7] == 10)) {
876                ish5 = true;
877                break;
878            }
879            else {
880                ish5 = false;
881                if (offset == 0) {
882                    offset = 512;
883                }
884                else {
885                    offset *= 2;
886                }
887            }
888        }
889        try {
890            raf.close();
891        }
892        catch (Throwable err) {
893            ;
894        }
895
896        if (!ish5) {
897            return false;
898        }
899
900        int length = 0;
901        int bsize = 1024;
902        byte[] buffer;
903        BufferedInputStream bi = null;
904        BufferedOutputStream bo = null;
905
906        try {
907            bi = new BufferedInputStream(new FileInputStream(fin));
908        }
909        catch (Exception ex) {
910            try {
911                bi.close();
912            }
913            catch (Exception ex2) {
914            }
915            return false;
916        }
917
918        try {
919            bo = new BufferedOutputStream(new FileOutputStream(fout));
920        }
921        catch (Exception ex) {
922            try {
923                bo.close();
924            }
925            catch (Exception ex2) {
926            }
927            try {
928                bi.close();
929            }
930            catch (Exception ex2) {
931            }
932            return false;
933        }
934
935        // skip the header of original file
936        try {
937            bi.skip(offset);
938        }
939        catch (Exception ex) {
940        }
941
942        // write the header into the new file
943        try {
944            bo.write(buf, 0, buf.length);
945        }
946        catch (Exception ex) {
947        }
948
949        // The super block space is allocated by offset 0, 512, 1024, 2048, etc
950        offset = 512;
951        while (offset < buf.length) {
952            offset *= 2;
953        }
954        int padSize = (int) (offset - buf.length);
955        if (padSize > 0) {
956            byte[] padBuf = new byte[padSize];
957            try {
958                bo.write(padBuf, 0, padSize);
959            }
960            catch (Exception ex) {
961            }
962        }
963
964        // copy the hdf5 file content from input file to the output file
965        buffer = new byte[bsize];
966        try {
967            length = bi.read(buffer, 0, bsize);
968        }
969        catch (Exception ex) {
970            length = 0;
971        }
972        while (length > 0) {
973            try {
974                bo.write(buffer, 0, length);
975                length = bi.read(buffer, 0, bsize);
976            }
977            catch (Exception ex) {
978                length = 0;
979            }
980        }
981
982        try {
983            bo.flush();
984        }
985        catch (Exception ex) {
986        }
987        try {
988            bi.close();
989        }
990        catch (Exception ex) {
991        }
992        try {
993            bo.close();
994        }
995        catch (Exception ex) {
996        }
997        return true;
998    }
999}