package org.autoplot.idlsupport; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.lang.reflect.Array; import java.net.InetAddress; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.channels.Channels; import java.nio.channels.WritableByteChannel; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.Map.Entry; /** * write data to IDL Save File * http://www.physics.wisc.edu/~craigm/idl/savefmt/node20.html * @author jbf */ public final class WriteIDLSav { private static final int DATATYPE_DOUBLE = 5; private static final int RECTYPE_ENDMARKER = 6; private static final int RECTYPE_TIMESTAMP = 10; private static final int RECTYPE_VARIABLE = 2; private static final int RECTYPE_VERSION = 14; private static final int VARFLAG_ARRAY = 4; private String nameFor( int type ) { if ( type==RECTYPE_VARIABLE ) { return "VARIABLE"; } else if ( type==RECTYPE_TIMESTAMP ) { return "TIMESTAMP"; } else if ( type==RECTYPE_VERSION) { return "VERSION"; } else if ( type==RECTYPE_ENDMARKER ) { return "ENDMARKER"; } else { return ""+type; } } private ByteBuffer timestamp() { //ByteBuffer date= writeString( "Sat Feb 11 08:43:55 2012" ); //Calendar.getInstance().toString() ); //ByteBuffer user= writeString( "jbf" ); //ByteBuffer host= writeString( "Jeremy-Fadens-MacBook-Air.local" ); //TODO: get these from java props //ByteBuffer date= writeString( "Mon Feb 20 06:49:42 2012" ); //Calendar.getInstance().toString() ); //ByteBuffer user= writeString( "jbf" ); //ByteBuffer host= writeString( "spot5" ); //TODO: get these from java props ByteBuffer date= writeString( new java.util.Date().toString() ); //Calendar.getInstance().toString() ); ByteBuffer user= writeString( System.getProperty("user.name") ); String shost; try { shost= InetAddress.getLocalHost().getHostName(); } catch ( UnknownHostException ex ) { shost= "localhost"; // this shouldn't happen } ByteBuffer host= writeString( shost ); ByteBuffer result= ByteBuffer.allocateDirect( 257*4 + date.limit() + user.limit() + host.limit() ); for ( int i=0; i<257*4; i++ ) { result.put((byte)0); } result.put(date); //System.err.println(4+result.position()); result.put(user); //System.err.println(4+result.position()); result.put(host); //System.err.println(4+result.position()); result.flip(); return result; } private ByteBuffer version() { ByteBuffer format= ByteBuffer.allocateDirect(4); format.order(ByteOrder.BIG_ENDIAN); format.putInt(9); format.flip(); ByteBuffer arch= writeString( System.getProperty("os.arch") ); ByteBuffer os= writeString( System.getProperty("os.name")); ByteBuffer release= writeString("(Autoplot)"); ByteBuffer result= ByteBuffer.allocateDirect( 4 + 4 + arch.limit() + os.limit() + release.limit() ); result.putInt( 0 ); result.put( format ); result.put( arch ); result.put( os ); result.put( release ); result.flip(); return result; } static ByteBuffer getBytesStr( String s ) { return ByteBuffer.wrap(s.getBytes()); } static ByteBuffer getBytesByte( byte b ) { return ByteBuffer.wrap(new byte[]{b}); } private ByteBuffer writeString( String s ) { int len= 4 * (int)Math.ceil( ( s.length()+4 ) / 4. ); ByteBuffer result= ByteBuffer.allocateDirect(len); result.order( ByteOrder.BIG_ENDIAN ); result.putInt(s.length()); try { result.put(s.getBytes("US-ASCII")); } catch ( UnsupportedEncodingException ex ) { // this doesn't happen with JavaSE throw new RuntimeException(ex); } for ( int i=result.position(); i l= new LinkedList<>(); d1= data; for ( int i=0; i variables= new LinkedHashMap(); public void checkVariableType( String name, Object data ) { Class c= data.getClass(); Class componentType; Class c1= c; int rank=1; while ( c1.isArray() && c1.getComponentType().isArray() ) { c1= c1.getComponentType(); rank++; } componentType= c1.getComponentType(); if ( rank==0 || rank>3 ) throw new IllegalArgumentException("unsupported rank, only rank 1 or rank 2 data"); if ( !( c.isArray() && ( componentType==double.class || componentType==long.class ) ) && c!=Short.class ) { throw new IllegalArgumentException("\"" + name + "\" is unsupported data type: "+data.getClass() ); } } public void addVariable( String name, Object data ) { checkVariableType( name, data ); variables.put(name, data); } public void write( OutputStream out ) throws IOException { WritableByteChannel ch= Channels.newChannel(out); ch.write(getBytesStr("SR")); ch.write(getBytesByte((byte) 0)); ch.write(getBytesByte((byte) 4)); int pos= 4; pos= writeRecord( ch, RECTYPE_TIMESTAMP, timestamp(), pos ); pos= writeRecord( ch, RECTYPE_VERSION, version(), pos ); for ( Entry var: variables.entrySet() ) { pos= writeRecord( ch, RECTYPE_VARIABLE, variable( var.getKey(), var.getValue(), pos ), pos ); } pos= writeRecord( ch, RECTYPE_ENDMARKER, endMarker(), pos ); ch.close(); } public static void main(String[] args) throws FileNotFoundException, IOException { FileOutputStream fos = new FileOutputStream(new File("/tmp/test.autoplot.idlsav")); WriteIDLSav widls= new WriteIDLSav(); widls.addVariable( "myvar", new double[] { 120,100,120,45,46,47,48,49,120,100,120 } ); widls.addVariable( "second", new double[] { -1,-1,-2,-3,-3,4,5,6,7,7,8,9,9,10 } ); widls.addVariable( "mylong", new long[] { -1, 100000, 100000000000L } ); widls.addVariable( "mydoublearr", new double[][] { { 120,100,120,45}, {46,47,48,49}, {1.2,1.10,1.4,1.25} } ); //widls.addVariable( "oneval", 19.95 ); widls.write(fos); fos.close(); } }