%classpath config resolver scijava.public https://maven.scijava.org/content/groups/public %classpath add mvn net.imagej imagej 2.0.0-rc-71 ij = new net.imagej.ImageJ() "ImageJ v${ij.getVersion()} is ready to go." import java.io.File import org.scijava.util.DigestUtils import org.scijava.util.FileUtils data = """ cols = 7 rows = 7 data = <@@@@@@@@ @ @ @ @@ @ @ @@ @ @ @@ @ @ @@@ > """ desktop = System.getProperty("user.home") + "/Desktop/" tablePath = desktop + "example.char-table" outFile = new File(tablePath) FileUtils.writeFile(outFile, DigestUtils.bytes(data)) "Wrote ${outFile.length()} bytes to '$outFile'" import java.io.File import org.scijava.io.AbstractIOPlugin import org.scijava.io.IOPlugin import org.scijava.plugin.Plugin import org.scijava.table.DefaultGenericTable import org.scijava.table.Table import org.scijava.util.DigestUtils import org.scijava.util.FileUtils @Plugin(type = IOPlugin.class) public class CharTableReader extends AbstractIOPlugin { @Override public Class
getDataType() { // This is the type of object produced by the reader. return Table.class } @Override public boolean supportsOpen(final String source) { // Check whether the source is indeed a .char-table. // This check can be as shallow or as deep as you want, // but it is advised to keep it as fast as possible. // As such, it is not recommended to actually open and // interrogate the source unless you have no choice. return source.toLowerCase().endsWith(".char-table") } @Override public Table open(final String source) throws IOException { // This is where we read the data from its source, // and convert it into the destination data type. // Read in the file. String contents = DigestUtils.string(FileUtils.readFile(new File(source))) // Parse the contents line by line. int rows = 0, cols = 0 String data = null for (line in contents.split("\n")) { int equals = line.indexOf("=") if (equals < 0) continue String key = line.substring(0, equals).trim() String val = line.substring(equals + 1).trim() switch (key) { case "rows": rows = Integer.parseInt(val) break case "cols": cols = Integer.parseInt(val) break case "data": data = val break } } // Do some error checking. if (rows <= 0) throw new IOException("Missing or invalid rows") if (cols <= 0) throw new IOException("Missing or invalid cols") if (data == null || !data.startsWith("<") || !data.endsWith(">")) { throw new IOException("Missing or invalid data") } if (cols * rows != data.length() - 2) { throw new IOException("Expected data length ${cols * rows} but was ${data.length() - 2}") } // Build the resultant table. Table table = new DefaultGenericTable(cols, rows) int index = 1 for (int r = 0; r < rows; r++) { for (int c = 0; c < cols; c++) { table.set(c, r, data.charAt(index++)) } } // HACK: Work around an SJJK bug when column headers are unspecified. for (int c = 0; c < cols; c++) table.setColumnHeader(c, "") return table } // HACK: Work around weird bug in Groovy(?). // It is normally not needed to override this method here. @Override public Class getType() { return String.class } } // Register the plugin with the existing SciJava context. import org.scijava.plugin.PluginInfo info = new PluginInfo(CharTableReader.class, IOPlugin.class) ij.plugin().addPlugin(info) info table = ij.io().open(tablePath) ij.notebook().display((Object) table) import java.io.File import org.scijava.Priority import org.scijava.io.AbstractIOPlugin import org.scijava.io.IOPlugin import org.scijava.plugin.Plugin import org.scijava.table.DefaultGenericTable import org.scijava.table.Table import org.scijava.util.DigestUtils import org.scijava.util.FileUtils @Plugin(type = IOPlugin.class) public class AsciiTableWriter extends AbstractIOPlugin
{ @Override public Class
getDataType() { // This is the type of object exported by the writer. return Table.class } @Override public boolean supportsSave(final String destination) { // Check whether the destination should be a .ascii-table. // This is typically a format extension check. return destination.toLowerCase().endsWith(".ascii-table") } @Override public void save(final Table table, final String destination) throws IOException { // This is where we write the data to its destination, // converting it from the source data type. // Define the default character. byte other = (byte) '-' // Build up the output bytes. int cols = table.getColumnCount() int rows = table.getRowCount() byte[] bytes = new byte[(cols + 1) * rows] int index = 0 for (int r = 0; r < rows; r++) { for (int c = 0; c < cols; c++) { Object cell = table.get(c, r) String s = cell == null ? null : cell.toString() if (s == null || s.length() == 0) { bytes[index++] = other continue } int v = s.charAt(0) bytes[index++] = v >= 32 && v <= 126 ? (byte) v : other } bytes[index++] = '\n' } // Write out the file. FileUtils.writeFile(new File(destination), bytes) } // HACK: Work around weird bug in Groovy(?). // It is normally not needed to override this method here. @Override public Class getType() { return String.class } } // Register the plugin with the existing SciJava context. import org.scijava.plugin.PluginInfo info = new PluginInfo(AsciiTableWriter.class, IOPlugin.class) ij.plugin().addPlugin(info) // HACK: Refresh the IOService. (This bug is fixed on scijava-common master.) import org.scijava.util.ClassUtils ClassUtils.setValue(ClassUtils.getField(org.scijava.plugin.AbstractSingletonService.class, "instances"), ij.io(), null) info outPath = desktop + "fiji.ascii-table" ij.io().save(table, desktop + "fiji.ascii-table") outFile = new File(outPath) "Wrote ${outFile.length()} bytes to '$outFile'" import org.scijava.util.DigestUtils import org.scijava.util.FileUtils DigestUtils.string(FileUtils.readFile(outFile))