Java source code of 'jhplot.io.HFile'

/**
 *    Copyright (C)  DataMelt project. The jHPLot package by S.Chekanov and Work.ORG
 *    All rights reserved.
 *
 *    This program is free software; you can redistribute it and/or modify it under the terms
 *    of the GNU General Public License as published by the Free Software Foundation; either
 *    version 3 of the License, or any later version.
 *
 *    This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 *    without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *    See the GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License along with this program;
 *    if not, see .
 *
 *    Additional permission under GNU GPL version 3 section 7:
 *    If you have received this program as a library with written permission from the DataMelt team,
 *    you can link or combine this library with your non-GPL project to convey the resulting work.
 *    In this case, this library should be considered as released under the terms of
 *    GNU Lesser public license (see ),
 *    provided you include this license notice and a URL through which recipients can access the
 *    Corresponding Source.
 **/

package jhplot.io;

import jhplot.*; 
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

import jhplot.gui.HelpBrowser;

/**
 * 
 * Write or read objects in sequential order using the Java serialization. The
 * objects inside files are gzipped on-fly. The size of serialized files should
 * be significantly smaller than when using HFile class. Use "close()" to flush
 * buffered output stream. Use BrowserHFile to browser all entries in a GUI
 * frame. Normally, files should have the extension ".jser". Files can be viewed
 * using BrowserHFile.
 * 

* * You can also insert objects using the keys and read them back. In this case, * avoid writing many objects without the keys since the extraction of keys will * be very inefficient. Try not mix write/read with keys or without. * * @author S.Chekanov * */ public class HFile { private FileOutputStream oof; private ObjectOutputStream oos; private ObjectInputStream iis; private int reset = 100; private int nev = 0; private int buffer; private Map hmap; final private int version = 2; /** * Open a file to write/read objects to/from a serialized file in sequential * order. Objects can be gzipped/gunzipped on-fly. If "w" option is set, the * old file will be removed. Use close() to flash the buffer and close the * file. You can set buffer size for I/O . Make it larger for a heavy I/O. * It is best to use buffer sizes that are multiples of 1024 bytes. That * works best with most built-in buffering in hard disks. *

* You can also insert an object using a string key. * *

* If the file name starts from http or ftp, we assume it is located on the * Web and will attempt to read it from URL. * * @param file * File name. Can be located on URL if starts from http or ftp. * @param option * Option to create the file. If "w" - write a file (or read) * file, if "r" only read created file. * @param compression * if true, objects are compressed on-fly using GZIP * @param bufferSize * set buffer size for I/O. It is best to use buffer sizes that * are multiples of 1024 bytes. * */ public HFile(String file, String option, boolean compression, int bufferSize) { buffer = bufferSize; nev = 0; file = file.trim(); hmap = new HFileMap(version); if (option.equalsIgnoreCase("w")) { try { (new File(file)).delete(); oof = new FileOutputStream(file); if (compression == true) { oos = new ObjectOutputStream(new BufferedOutputStream( new GZIPOutputStream(oof), buffer)); } else { oos = new ObjectOutputStream(new BufferedOutputStream(oof, buffer)); } } catch (IOException e) { jhplot.utils.Util.ErrorMessage(e.toString()); } } else if (option.equalsIgnoreCase("r")) { // check. Is is URL? if (file.startsWith("http") || file.startsWith("ftp")) { URL url = null; try { url = new URL(file); } catch (MalformedURLException e) { jhplot.utils.Util.ErrorMessage(e.toString()); } try { URLConnection urlConn = url.openConnection(); urlConn.setDoInput(true); urlConn.setUseCaches(false); if (compression == true) { iis = new ObjectInputStream(new GZIPInputStream( urlConn.getInputStream())); } else { iis = new ObjectInputStream(urlConn.getInputStream()); } } catch (MalformedURLException e) { jhplot.utils.Util.ErrorMessage(e.toString()); } catch (IOException e) { jhplot.utils.Util.ErrorMessage(e.toString()); } } else { // this is normal file on a file system try { FileInputStream iif = new FileInputStream(new File(file)); if (compression == true) { iis = new ObjectInputStream(new BufferedInputStream( new GZIPInputStream(iif), buffer)); } else { iis = new ObjectInputStream(new BufferedInputStream( iif, buffer)); } } catch (IOException e) { jhplot.utils.Util.ErrorMessage(e.toString()); } } } else { jhplot.utils.Util .ErrorMessage("Wrong option!. Only \"r\" or \"w\" is allowed"); } }; /** * Open a file to write/read objects to/from a serialized file in sequential * order. Objects can be gzipped/gunzipped on-fly. If "w" option is set, the * old file will be removed. Use close() to flash the buffer and close the * file. The default buffer size is 12 k (i.e. 12 * 1024). * * @param file * File name * @param option * Option to create the file. If "w" - write a file (or read) * file, if "r" only read created file. * @param compression * if true, objects are compressed on-fly using GZIP * * @param buffer * set buffer size for I/O. It is best to use buffer sizes that * are multiples of 1024 bytes. * */ public HFile(String file, String option, boolean compression) { this(file, option, compression, 12 * 1024); } /** * Get current buffer size for I/O. */ public int getBufferSize() { return this.buffer; } /** * Open file for reading objects from a serialized file in sequential order. * By default, entries are compressed. * * @param file * File name */ public HFile(String file) { this(file, "r", true); }; /** * Open file for reading objects from a serialized file in sequential order. * By default, objects are compressed. * * @param file * File name * @param option * Option to create the file. If "w" - write a file (or read) * file, if "r" only read created file. */ public HFile(String file, String option) { this(file, option, true); }; /** * Add an object using a key. * * @param key * key to access the object. * @param ob * object to be inserted. * @return false if the key exits. */ public boolean write(String key, Object ob) { if (!hmap.containsKey(key)) { hmap.put(key, ob); return true; } else return false; } /** * Add an object to a file * * @param ob * Object * @param key * key for object * @return true if success */ public boolean write(Object ob) { boolean success = true; // fix serialization for for functions if (ob instanceof jhplot.F1D) ob=((F1D)ob).get(); else if (ob instanceof jhplot.F2D) ob=((F2D)ob).get(); else if (ob instanceof jhplot.F3D) ob=((F3D)ob).get(); else if (ob instanceof jhplot.FND) ob=((FND)ob).get(); try { oos.writeObject(ob); nev++; if (nev > 1 && nev % reset == 0) oos.reset(); } catch (IOException e) { // TODO Auto-generated catch block success = false; e.printStackTrace(); } return success; }; /** * Set after how many events data will be flushed. The stream will flush all * the objects from the identity hash table. The default is 100. * * @param reset * after how many events data will be reset. * */ public void setFlush(int reset) { this.reset = reset; } /** * Return objects stored in the form of a map. * * @return */ public Map getObjectMap() { // try to get this map if (hmap.size() == 0 && iis != null) { try { Object obj = null; while ((obj = iis.readObject()) != null) { // System.out.println("Read="+obj.getClass().getName() ); if (obj instanceof jhplot.io.HFileMap) { // Cast object to a Vector // System.out.println("Read="+obj.getClass().getName() // ); hmap = (HFileMap) obj; return hmap; } } } catch (ClassNotFoundException | IOException e) { jhplot.utils.Util.ErrorMessage(e.toString()); return null; } } return hmap; } /** * Return processed number of entries. Entries with the key not counted. * * @return No of processed events * */ public int getEntries() { return nev; } /** * Get object from a file. Return Null if the end if file is reached. * * @return Object extracted object (or Null) */ public Object read() { Object ob = null; try { ob = iis.readObject(); // restore functions if (ob instanceof jhplot.FProxy) { if ( ((FProxy)ob).getType()==1) ob=new F1D((FProxy)ob); else if ( ((FProxy)ob).getType()==2) ob=new F2D((FProxy)ob); else if ( ((FProxy)ob).getType()==3) ob=new F3D((FProxy)ob); else if ( ((FProxy)ob).getType()==4) ob=new FND((FProxy)ob); } if (ob instanceof jhplot.io.HFileMap) { hmap = (HFileMap) ob; return null; } nev++; // if (nev>1 && nev%reset==0) iis.reset(); } catch (ClassNotFoundException | IOException ex) { // This exception will be caught when EOF is // reached return null; } return ob; }; /** * Read an object using a key if exits. * * @param key * @return returned object. */ public Object read(String key) { Object obj = null; if (hmap.size() == 0 && iis != null) { try { while ((obj = iis.readObject()) != null) { if (obj instanceof jhplot.io.HFileMap) { hmap = (HFileMap) obj; } } } catch (ClassNotFoundException | IOException e) { // TODO Auto-generated catch block return null; } } if (hmap.containsKey(key)) return hmap.get(key); return null; } /** * Close the file * * @return */ public boolean close() { boolean success = true; try { if (oos != null) { oos.writeObject(hmap); // add the map as the last object oos.flush(); oos.close(); oof.close(); oos = null; } if (iis != null) { iis.close(); iis = null; } } catch (IOException e) { success = false; // ErrorMessage(e.toString()); } System.gc(); return success; } /** * Show online documentation. */ public void doc() { String a = this.getClass().getName(); a = a.replace(".", "/") + ".html"; new HelpBrowser(HelpBrowser.JHPLOT_HTTP + a); } }