2
* This program is free software; you can redistribute it and/or modify
3
* it under the terms of the GNU General Public License as published by
4
* the Free Software Foundation; either version 2 of the License, or
5
* (at your option) any later version.
7
* This program is distributed in the hope that it will be useful,
8
* but WITHOUT ANY WARRANTY; without even the implied warranty of
9
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
* GNU General Public License for more details.
12
* You should have received a copy of the GNU General Public License
13
* along with this program; if not, write to the Free Software
14
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
* Copyright (C) 2000 University of Waikato, Hamilton, New Zealand
23
package weka.core.converters;
25
import weka.core.ClassDiscovery;
26
import weka.core.Instance;
27
import weka.core.Instances;
28
import weka.gui.GenericObjectEditor;
29
import weka.gui.GenericPropertiesCreator;
32
import java.io.IOException;
33
import java.io.InputStream;
34
import java.io.OutputStream;
35
import java.io.Serializable;
36
import java.io.StreamTokenizer;
38
import java.util.Arrays;
39
import java.util.Collections;
40
import java.util.Enumeration;
41
import java.util.Hashtable;
42
import java.util.Properties;
43
import java.util.Vector;
46
* Utility routines for the converter package.
48
* @author Mark Hall (mhall@cs.waikato.ac.nz)
49
* @author FracPete (fracpete at waikato dot ac dot nz)
50
* @version $Revision: 1.14 $
53
public class ConverterUtils
54
implements Serializable {
56
/** for serialization. */
57
static final long serialVersionUID = -2460855349276148760L;
60
* Helper class for loading data from files and URLs. Via the ConverterUtils
61
* class it determines which converter to use for loading the data into
62
* memory. If the chosen converter is an incremental one, then the data
63
* will be loaded incrementally, otherwise as batch. In both cases the
64
* same interface will be used (<code>hasMoreElements</code>,
65
* <code>nextElement</code>). Before the
66
* data can be read again, one has to call the <code>reset</code> method.
67
* The data source can also be initialized with an Instances object, in
68
* order to provide a unified interface to files and already loaded datasets.
70
* @author FracPete (fracpete at waikato dot ac dot nz)
71
* @version $Revision: 1.14 $
72
* @see #hasMoreElements(Instances)
73
* @see #nextElement(Instances)
77
public static class DataSource
78
implements Serializable {
80
/** for serialization. */
81
private static final long serialVersionUID = -613122395928757332L;
83
/** the file to load. */
84
protected File m_File;
86
/** the URL to load. */
90
protected Loader m_Loader;
92
/** whether the loader is incremental. */
93
protected boolean m_Incremental;
95
/** the instance counter for the batch case. */
96
protected int m_BatchCounter;
98
/** the last internally read instance. */
99
protected Instance m_IncrementalBuffer;
101
/** the batch buffer. */
102
protected Instances m_BatchBuffer;
105
* Tries to load the data from the file. Can be either a regular file or
106
* a web location (http://, https://, ftp:// or file://).
108
* @param location the name of the file to load
109
* @throws Exception if initialization fails
111
public DataSource(String location) throws Exception {
115
if ( location.startsWith("http://")
116
|| location.startsWith("https://")
117
|| location.startsWith("ftp://")
118
|| location.startsWith("file://") )
119
m_URL = new URL(location);
121
m_File = new File(location);
123
// quick check: is it ARFF?
124
if (isArff(location)) {
125
m_Loader = new ArffLoader();
129
m_Loader = ConverterUtils.getLoaderForFile(location);
131
m_Loader = ConverterUtils.getURLLoaderForFile(location);
133
// do we have a converter?
134
if (m_Loader == null)
135
throw new IllegalArgumentException("No suitable converter found for '" + location + "'!");
138
// incremental loader?
139
m_Incremental = (m_Loader instanceof IncrementalConverter);
145
* Initializes the datasource with the given dataset.
147
* @param inst the dataset to use
149
public DataSource(Instances inst) {
152
m_BatchBuffer = inst;
156
m_Incremental = false;
160
* Initializes the datasource with the given Loader.
162
* @param loader the Loader to use
164
public DataSource(Loader loader) {
167
m_BatchBuffer = null;
171
m_Incremental = (m_Loader instanceof IncrementalConverter);
177
* Initializes the datasource with the given input stream. This stream
178
* is always interpreted as ARFF.
180
* @param stream the stream to use
182
public DataSource(InputStream stream) {
185
m_BatchBuffer = null;
186
m_Loader = new ArffLoader();
188
m_Loader.setSource(stream);
190
catch (Exception e) {
195
m_Incremental = (m_Loader instanceof IncrementalConverter);
201
* initializes the batch buffer if necessary, i.e., for non-incremental
204
protected void initBatchBuffer() {
206
if (!isIncremental())
207
m_BatchBuffer = m_Loader.getDataSet();
209
m_BatchBuffer = null;
211
catch (Exception e) {
217
* returns whether the extension of the location is likely to be of ARFF
218
* format, i.e., ending in ".arff" or ".arff.gz" (case-insensitive).
220
* @param location the file location to check
221
* @return true if the location seems to be of ARFF format
223
public static boolean isArff(String location) {
224
if ( location.toLowerCase().endsWith(ArffLoader.FILE_EXTENSION.toLowerCase())
225
|| location.toLowerCase().endsWith(ArffLoader.FILE_EXTENSION_COMPRESSED.toLowerCase()) )
232
* returns whether the loader is an incremental one.
234
* @return true if the loader is a true incremental one
236
public boolean isIncremental() {
237
return m_Incremental;
241
* returns the determined loader, null if the DataSource was initialized
242
* with data alone and not a file/URL.
244
* @return the loader used for retrieving the data
246
public Loader getLoader() {
251
* returns the full dataset, can be null in case of an error.
253
* @return the full dataset
254
* @throws Exception if resetting of loader fails
256
public Instances getDataSet() throws Exception {
265
if (m_Loader != null)
266
result = m_Loader.getDataSet();
268
result = m_BatchBuffer;
270
catch (Exception e) {
279
* returns the full dataset with the specified class index set,
280
* can be null in case of an error.
282
* @param classIndex the class index for the dataset
283
* @return the full dataset
284
* @throws Exception if resetting of loader fails
286
public Instances getDataSet(int classIndex) throws Exception {
289
result = getDataSet();
291
result.setClassIndex(classIndex);
299
* @throws Exception if resetting fails
301
public void reset() throws Exception {
303
((AbstractFileLoader) m_Loader).setFile(m_File);
304
else if (m_URL != null)
305
((URLSourcedLoader) m_Loader).setURL(m_URL.toString());
306
else if (m_Loader != null)
310
m_IncrementalBuffer = null;
312
if (m_Loader != null) {
313
if (!isIncremental())
314
m_BatchBuffer = m_Loader.getDataSet();
316
m_BatchBuffer = null;
321
* returns the structure of the data.
323
* @return the structure of the data
324
* @throws Exception if something goes wrong
326
public Instances getStructure() throws Exception {
327
if (m_Loader != null)
328
return m_Loader.getStructure();
330
return new Instances(m_BatchBuffer, 0);
334
* returns the structure of the data, with the defined class index.
336
* @param classIndex the class index for the dataset
337
* @return the structure of the data
338
* @throws Exception if something goes wrong
340
public Instances getStructure(int classIndex) throws Exception {
343
result = getStructure();
345
result.setClassIndex(classIndex);
351
* returns whether there are more Instance objects in the data.
353
* @param structure the structure of the dataset
354
* @return true if there are more Instance objects
356
* @see #nextElement(Instances)
358
public boolean hasMoreElements(Instances structure) {
363
if (isIncremental()) {
364
// user still hasn't collected the last one?
365
if (m_IncrementalBuffer != null) {
370
m_IncrementalBuffer = m_Loader.getNextInstance(structure);
371
result = (m_IncrementalBuffer != null);
373
catch (Exception e) {
380
result = (m_BatchCounter < m_BatchBuffer.numInstances());
387
* returns the next element and sets the specified dataset, null if
390
* @param dataset the dataset to set for the instance
391
* @return the next Instance
393
public Instance nextElement(Instances dataset) {
398
if (isIncremental()) {
399
// is there still an instance in the buffer?
400
if (m_IncrementalBuffer != null) {
401
result = m_IncrementalBuffer;
402
m_IncrementalBuffer = null;
406
result = m_Loader.getNextInstance(dataset);
408
catch (Exception e) {
415
if (m_BatchCounter < m_BatchBuffer.numInstances()) {
416
result = m_BatchBuffer.instance(m_BatchCounter);
421
result.setDataset(dataset);
427
* convencience method for loading a dataset in batch mode.
429
* @param location the dataset to load
430
* @return the dataset
431
* @throws Exception if loading fails
432
* @see #DataSource(String)
434
public static Instances read(String location) throws Exception {
438
source = new DataSource(location);
439
result = source.getDataSet();
445
* convencience method for loading a dataset in batch mode from a stream.
447
* @param stream the stream to load the dataset from
448
* @return the dataset
449
* @throws Exception if loading fails
450
* @see #DataSource(InputStream)
452
public static Instances read(InputStream stream) throws Exception {
456
source = new DataSource(stream);
457
result = source.getDataSet();
463
* convencience method for loading a dataset in batch mode.
465
* @param loader the loader to get the dataset from
466
* @return the dataset
467
* @throws Exception if loading fails
468
* @see #DataSource(Loader)
470
public static Instances read(Loader loader) throws Exception {
474
source = new DataSource(loader);
475
result = source.getDataSet();
481
* for testing only - takes a data file as input.
483
* @param args the commandline arguments
484
* @throws Exception if something goes wrong
486
public static void main(String[] args) throws Exception {
487
if (args.length != 1) {
488
System.out.println("\nUsage: " + DataSource.class.getName() + " <file>\n");
492
DataSource loader = new DataSource(args[0]);
494
System.out.println("Incremental? " + loader.isIncremental());
495
System.out.println("Loader: " + loader.getLoader().getClass().getName());
496
System.out.println("Data:\n");
497
Instances structure = loader.getStructure();
498
System.out.println(structure);
499
while (loader.hasMoreElements(structure))
500
System.out.println(loader.nextElement(structure));
502
Instances inst = loader.getDataSet();
503
loader = new DataSource(inst);
504
System.out.println("\n\nProxy-Data:\n");
505
System.out.println(loader.getStructure());
506
while (loader.hasMoreElements(structure))
507
System.out.println(loader.nextElement(inst));
512
* Helper class for saving data to files. Via the ConverterUtils
513
* class it determines which converter to use for saving the data.
514
* It is the logical counterpart to <code>DataSource</code>.
516
* @author FracPete (fracpete at waikato dot ac dot nz)
517
* @version $Revision: 1.14 $
520
public static class DataSink
521
implements Serializable {
523
/** for serialization. */
524
private static final long serialVersionUID = -1504966891136411204L;
526
/** the saver to use for storing the data. */
527
protected Saver m_Saver = null;
529
/** the stream to store the data in (always in ARFF format). */
530
protected OutputStream m_Stream = null;
533
* initializes the sink to save the data to the given file.
535
* @param filename the file to save data to
536
* @throws Exception if set of saver fails
538
public DataSink(String filename) throws Exception {
541
if (DataSource.isArff(filename))
542
m_Saver = new ArffSaver();
544
m_Saver = getSaverForFile(filename);
546
((AbstractFileSaver) m_Saver).setFile(new File(filename));
550
* initializes the sink to save the data to the given Saver (expected to be
553
* @param saver the saver to use for saving the data
555
public DataSink(Saver saver) {
561
* initializes the sink to save the data in the stream (always in ARFF
564
* @param stream the output stream to use for storing the data in ARFF
567
public DataSink(OutputStream stream) {
573
* writes the given data either via the saver or to the defined
574
* output stream (depending on the constructor). In case of the stream,
575
* the stream is only flushed, but not closed.
577
* @param data the data to save
578
* @throws Exception if saving fails
580
public void write(Instances data) throws Exception {
581
if (m_Saver != null) {
582
m_Saver.setInstances(data);
583
m_Saver.writeBatch();
586
m_Stream.write(data.toString().getBytes());
592
* writes the data to the given file.
594
* @param filename the file to write the data to
595
* @param data the data to store
596
* @throws Exception if writing fails
598
public static void write(String filename, Instances data) throws Exception {
601
sink = new DataSink(filename);
606
* writes the data via the given saver.
608
* @param saver the saver to use for writing the data
609
* @param data the data to store
610
* @throws Exception if writing fails
612
public static void write(Saver saver, Instances data) throws Exception {
615
sink = new DataSink(saver);
620
* writes the data to the given stream (always in ARFF format).
622
* @param stream the stream to write the data to (ARFF format)
623
* @param data the data to store
624
* @throws Exception if writing fails
626
public static void write(OutputStream stream, Instances data) throws Exception {
629
sink = new DataSink(stream);
634
* for testing only - takes a data file as input and a data file for the
637
* @param args the commandline arguments
638
* @throws Exception if something goes wrong
640
public static void main(String[] args) throws Exception {
641
if (args.length != 2) {
643
"\nUsage: " + DataSource.class.getName() + " <input-file> <output-file>\n");
648
Instances data = DataSource.read(args[0]);
651
DataSink.write(args[1], data);
655
/** the core loaders - hardcoded list necessary for RMI/Remote Experiments
656
* (comma-separated list). */
657
public final static String CORE_FILE_LOADERS =
658
weka.core.converters.ArffLoader.class.getName() + ","
659
+ weka.core.converters.C45Loader.class.getName() + ","
660
+ weka.core.converters.CSVLoader.class.getName() + ","
661
+ weka.core.converters.DatabaseConverter.class.getName() + ","
662
+ weka.core.converters.LibSVMLoader.class.getName() + ","
663
+ weka.core.converters.SerializedInstancesLoader.class.getName() + ","
664
+ weka.core.converters.TextDirectoryLoader.class.getName() + ","
665
+ weka.core.converters.XRFFLoader.class.getName();
667
/** the core savers - hardcoded list necessary for RMI/Remote Experiments
668
* (comma-separated list). */
669
public final static String CORE_FILE_SAVERS =
670
weka.core.converters.ArffSaver.class.getName() + ","
671
+ weka.core.converters.C45Saver.class.getName() + ","
672
+ weka.core.converters.CSVSaver.class.getName() + ","
673
+ weka.core.converters.DatabaseConverter.class.getName() + ","
674
+ weka.core.converters.LibSVMSaver.class.getName() + ","
675
+ weka.core.converters.SerializedInstancesSaver.class.getName() + ","
676
+ weka.core.converters.XRFFSaver.class.getName();
678
/** all available loaders (extension <-> classname). */
679
protected static Hashtable<String,String> m_FileLoaders;
681
/** all available URL loaders (extension <-> classname). */
682
protected static Hashtable<String,String> m_URLFileLoaders;
684
/** all available savers (extension <-> classname). */
685
protected static Hashtable<String,String> m_FileSavers;
687
// determine all loaders/savers
692
// generate properties
693
// Note: does NOT work with RMI, hence m_FileLoadersCore/m_FileSaversCore
694
GenericPropertiesCreator creator = new GenericPropertiesCreator();
695
creator.execute(false);
696
Properties props = creator.getOutputProperties();
699
m_FileLoaders = new Hashtable<String,String>();
700
m_URLFileLoaders = new Hashtable<String,String>();
701
m_FileSavers = new Hashtable<String,String>();
704
m_FileLoaders = getFileConverters(
705
props.getProperty(Loader.class.getName(), CORE_FILE_LOADERS),
706
new String[]{FileSourcedConverter.class.getName()});
709
m_URLFileLoaders = getFileConverters(
710
props.getProperty(Loader.class.getName(), CORE_FILE_LOADERS),
712
FileSourcedConverter.class.getName(),
713
URLSourcedLoader.class.getName()});
716
m_FileSavers = getFileConverters(
717
props.getProperty(Saver.class.getName(), CORE_FILE_SAVERS),
718
new String[]{FileSourcedConverter.class.getName()});
720
catch (Exception e) {
725
if (m_FileLoaders.size() == 0) {
726
classnames = GenericObjectEditor.getClassnames(AbstractFileLoader.class.getName());
727
if (classnames.size() > 0)
728
m_FileLoaders = getFileConverters(
730
new String[]{FileSourcedConverter.class.getName()});
732
m_FileLoaders = getFileConverters(
734
new String[]{FileSourcedConverter.class.getName()});
738
if (m_URLFileLoaders.size() == 0) {
739
classnames = GenericObjectEditor.getClassnames(AbstractFileLoader.class.getName());
740
if (classnames.size() > 0)
741
m_URLFileLoaders = getFileConverters(
744
FileSourcedConverter.class.getName(),
745
URLSourcedLoader.class.getName()});
747
m_URLFileLoaders = getFileConverters(
750
FileSourcedConverter.class.getName(),
751
URLSourcedLoader.class.getName()});
755
if (m_FileSavers.size() == 0) {
756
classnames = GenericObjectEditor.getClassnames(AbstractFileSaver.class.getName());
757
if (classnames.size() > 0)
758
m_FileSavers = getFileConverters(
760
new String[]{FileSourcedConverter.class.getName()});
762
m_FileSavers = getFileConverters(
764
new String[]{FileSourcedConverter.class.getName()});
770
* returns a hashtable with the association
771
* "file extension <-> converter classname" for the comma-separated list
772
* of converter classnames.
774
* @param classnames comma-separated list of converter classnames
775
* @param intf interfaces the converters have to implement
776
* @return hashtable with ExtensionFileFilters
778
protected static Hashtable<String,String> getFileConverters(String classnames, String[] intf) {
784
names = classnames.split(",");
785
for (i = 0; i < names.length; i++)
788
return getFileConverters(list, intf);
792
* returns a hashtable with the association
793
* "file extension <-> converter classname" for the list of converter
796
* @param classnames list of converter classnames
797
* @param intf interfaces the converters have to implement
798
* @return hashtable with ExtensionFileFilters
800
protected static Hashtable<String,String> getFileConverters(Vector classnames, String[] intf) {
801
Hashtable<String,String> result;
805
FileSourcedConverter converter;
809
result = new Hashtable<String,String>();
811
for (i = 0; i < classnames.size(); i++) {
812
classname = (String) classnames.get(i);
814
// all necessary interfaces implemented?
815
for (n = 0; n < intf.length; n++) {
816
if (!ClassDiscovery.hasInterface(intf[n], classname))
820
// get data from converter
822
cls = Class.forName(classname);
823
converter = (FileSourcedConverter) cls.newInstance();
824
ext = converter.getFileExtensions();
826
catch (Exception e) {
832
if (converter == null)
835
for (n = 0; n < ext.length; n++)
836
result.put(ext[n], classname);
843
* Gets token, skipping empty lines.
845
* @param tokenizer the stream tokenizer
846
* @throws IOException if reading the next token fails
848
public static void getFirstToken(StreamTokenizer tokenizer)
851
while (tokenizer.nextToken() == StreamTokenizer.TT_EOL){};
852
if ((tokenizer.ttype == '\'') ||
853
(tokenizer.ttype == '"')) {
854
tokenizer.ttype = StreamTokenizer.TT_WORD;
855
} else if ((tokenizer.ttype == StreamTokenizer.TT_WORD) &&
856
(tokenizer.sval.equals("?"))) {
857
tokenizer.ttype = '?';
864
* @param tokenizer the stream tokenizer
865
* @throws IOException if reading the next token fails
867
public static void getToken(StreamTokenizer tokenizer) throws IOException {
869
tokenizer.nextToken();
870
if (tokenizer.ttype== StreamTokenizer.TT_EOL) {
874
if ((tokenizer.ttype == '\'') ||
875
(tokenizer.ttype == '"')) {
876
tokenizer.ttype = StreamTokenizer.TT_WORD;
877
} else if ((tokenizer.ttype == StreamTokenizer.TT_WORD) &&
878
(tokenizer.sval.equals("?"))) {
879
tokenizer.ttype = '?';
884
* Throws error message with line number and last token read.
886
* @param theMsg the error message to be thrown
887
* @param tokenizer the stream tokenizer
888
* @throws IOException containing the error message
890
public static void errms(StreamTokenizer tokenizer, String theMsg)
893
throw new IOException(theMsg + ", read " + tokenizer.toString());
897
* returns a vector with the classnames of all the loaders from the
900
* @param ht the hashtable with the extension/converter relation
901
* @return the classnames of the loaders
903
protected static Vector<String> getConverters(Hashtable<String,String> ht) {
904
Vector<String> result;
905
Enumeration<String> enm;
908
result = new Vector<String>();
910
// get all classnames
912
while (enm.hasMoreElements()) {
913
converter = enm.nextElement();
914
if (!result.contains(converter))
915
result.add(converter);
919
Collections.sort(result);
925
* tries to determine the converter to use for this kind of file, returns
926
* null if none can be found in the given hashtable.
928
* @param filename the file to return a converter for
929
* @param ht the hashtable with the relation extension/converter
930
* @return the converter if one was found, null otherwise
932
protected static Object getConverterForFile(String filename, Hashtable<String,String> ht) {
939
index = filename.lastIndexOf('.');
941
extension = filename.substring(index).toLowerCase();
942
result = getConverterForExtension(extension, ht);
943
// is it a compressed format?
944
if (extension.equals(".gz") && result == null) {
945
index = filename.lastIndexOf('.', index - 1);
946
extension = filename.substring(index).toLowerCase();
947
result = getConverterForExtension(extension, ht);
955
* tries to determine the loader to use for this kind of extension, returns
956
* null if none can be found.
958
* @param extension the file extension to return a converter for
959
* @param ht the hashtable with the relation extension/converter
960
* @return the converter if one was found, null otherwise
962
protected static Object getConverterForExtension(String extension, Hashtable<String,String> ht) {
967
classname = (String) ht.get(extension);
968
if (classname != null) {
970
result = Class.forName(classname).newInstance();
972
catch (Exception e) {
982
* checks whether the given class is one of the hardcoded core file loaders.
984
* @param classname the class to check
985
* @return true if the class is one of the core loaders
986
* @see #CORE_FILE_LOADERS
988
public static boolean isCoreFileLoader(String classname) {
992
classnames = CORE_FILE_LOADERS.split(",");
993
result = (Arrays.binarySearch(classnames, classname) >= 0);
999
* returns a vector with the classnames of all the file loaders.
1001
* @return the classnames of the loaders
1003
public static Vector<String> getFileLoaders() {
1004
return getConverters(m_FileLoaders);
1008
* tries to determine the loader to use for this kind of file, returns
1009
* null if none can be found.
1011
* @param filename the file to return a converter for
1012
* @return the converter if one was found, null otherwise
1014
public static AbstractFileLoader getLoaderForFile(String filename) {
1015
return (AbstractFileLoader) getConverterForFile(filename, m_FileLoaders);
1019
* tries to determine the loader to use for this kind of file, returns
1020
* null if none can be found.
1022
* @param file the file to return a converter for
1023
* @return the converter if one was found, null otherwise
1025
public static AbstractFileLoader getLoaderForFile(File file) {
1026
return getLoaderForFile(file.getAbsolutePath());
1030
* tries to determine the loader to use for this kind of extension, returns
1031
* null if none can be found.
1033
* @param extension the file extension to return a converter for
1034
* @return the converter if one was found, null otherwise
1036
public static AbstractFileLoader getLoaderForExtension(String extension) {
1037
return (AbstractFileLoader) getConverterForExtension(extension, m_FileLoaders);
1041
* returns a vector with the classnames of all the URL file loaders.
1043
* @return the classnames of the loaders
1045
public static Vector<String> getURLFileLoaders() {
1046
return getConverters(m_URLFileLoaders);
1050
* tries to determine the URL loader to use for this kind of file, returns
1051
* null if none can be found.
1053
* @param filename the file to return a URL converter for
1054
* @return the converter if one was found, null otherwise
1056
public static AbstractFileLoader getURLLoaderForFile(String filename) {
1057
return (AbstractFileLoader) getConverterForFile(filename, m_URLFileLoaders);
1061
* tries to determine the URL loader to use for this kind of file, returns
1062
* null if none can be found.
1064
* @param file the file to return a URL converter for
1065
* @return the converter if one was found, null otherwise
1067
public static AbstractFileLoader getURLLoaderForFile(File file) {
1068
return getURLLoaderForFile(file.getAbsolutePath());
1072
* tries to determine the URL loader to use for this kind of extension, returns
1073
* null if none can be found.
1075
* @param extension the file extension to return a URL converter for
1076
* @return the converter if one was found, null otherwise
1078
public static AbstractFileLoader getURLLoaderForExtension(String extension) {
1079
return (AbstractFileLoader) getConverterForExtension(extension, m_URLFileLoaders);
1083
* checks whether the given class is one of the hardcoded core file savers.
1085
* @param classname the class to check
1086
* @return true if the class is one of the core savers
1087
* @see #CORE_FILE_SAVERS
1089
public static boolean isCoreFileSaver(String classname) {
1091
String[] classnames;
1093
classnames = CORE_FILE_SAVERS.split(",");
1094
result = (Arrays.binarySearch(classnames, classname) >= 0);
1100
* returns a vector with the classnames of all the file savers.
1102
* @return the classnames of the savers
1104
public static Vector<String> getFileSavers() {
1105
return getConverters(m_FileSavers);
1109
* tries to determine the saver to use for this kind of file, returns
1110
* null if none can be found.
1112
* @param filename the file to return a converter for
1113
* @return the converter if one was found, null otherwise
1115
public static AbstractFileSaver getSaverForFile(String filename) {
1116
return (AbstractFileSaver) getConverterForFile(filename, m_FileSavers);
1120
* tries to determine the saver to use for this kind of file, returns
1121
* null if none can be found.
1123
* @param file the file to return a converter for
1124
* @return the converter if one was found, null otherwise
1126
public static AbstractFileSaver getSaverForFile(File file) {
1127
return getSaverForFile(file.getAbsolutePath());
1131
* tries to determine the saver to use for this kind of extension, returns
1132
* null if none can be found.
1134
* @param extension the file extension to return a converter for
1135
* @return the converter if one was found, null otherwise
1137
public static AbstractFileSaver getSaverForExtension(String extension) {
1138
return (AbstractFileSaver) getConverterForExtension(extension, m_FileSavers);