A program i am working on deals with processing file content. Right now i am writing jUnit tests to make sure things work as expected. As part of these tests, i'd like to reference an inline text file which would define the scope of a particular test.
How do i access such a file?
--
Let me clarify:
Normally, when opening a file, you need to indicate where the file is. What i want to say instead is "in this project". This way, when someone else looks at my code, they too will be able to access the same file.I may be wrong, but isn't there a special way, one can access files which are a part of "this" project, relative to "some files out there on disk".
If what you mean is you have a file you need your tests to be able to read from, if you copy the file into the classpath your tests can read it using Class.getResourceAsStream().
For an example try this link (Jon Skeet answered a question like this):
read file in classpath
You can also implement your own test classes for InputStream or what have you.
package thop;
import java.io.InputStream;
/**
*
* #author tonyennis
*/
public class MyInputStream extends InputStream {
private char[] input;
private int current;
public MyInputStream(String s) {
input = s.toCharArray();
current = 0;
}
public int read() {
return (current == input.length) ? -1 : input[current++];
}
#Override
public void close() {
}
}
This is a simple InputStream. You give it a string, it gives you the string. If the code you wanted to test required an InputStream, you could use this (or something like it, heh) to feed exactly the strings wanted to test. You wouldn't need resources or disk files.
Here I use my lame class as input to a BufferedInputStream...
package thop;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
*
* #author tonyennis
*/
public class Main {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException {
InputStream is = new MyInputStream("Now is the time");
BufferedInputStream bis = new BufferedInputStream(is);
int res;
while((res = bis.read()) != -1) {
System.out.println((char)res);
}
}
}
Now, if you want to make sure your program parses the inputStream correctly, you're golden. You can feed it the string you want to test with no difficulty. If you want to make sure the class being tested always closes the InputStream, add a "isOpen" boolean instance variable, set it to true in the constructor, set it to false in close(), and add a getter.
Now your test code would include something like:
MyInputStream mis = new MyInputStream("first,middle,last");
classBeingTested.testForFullName(mis);
assertFalse(mis.isOpen());
Related
I learn how to use java 8 API. I have a simple log file with the following contents:
SVF2018-05-24_12:02:58.917
NHR2018-05-24_12:02:49.914
FAM2018-05-24_12:13:04.512
KRF2018-05-24_12:03:01.250
SVM2018-05-24_12:18:37.735
MES2018-05-24_12:04:45.513
LSW2018-05-24_12:06:13.511
BHS2018-05-24_12:14:51.985
EOF2018-05-24_12:17:58.810
RGH2018-05-24_12:05:14.511
SSW2018-05-24_12:16:11.648
KMH2018-05-24_12:02:51.003
PGS2018-05-24_12:07:23.645
CSR2018-05-24_12:03:15.145
SPF2018-05-24_12:12:01.035
DRR2018-05-24_12:14:12.054
LHM2018-05-24_12:18:20.125
CLS2018-05-24_12:09:41.921
VBM2018-05-24_12:00:00.000
My goal is to parse it using streams. The desired output is the following:
[{SVF = [2018-05-24, 12:02:58.917]}, {NHR = [2018-05-24, 12:02:49.914]}...]
I already have the following:
public class FileParser {
Stream<String> outputStream;
public FileParser(String fileName) throws IOException, URISyntaxException {
FileReader fr = new FileReader();
this.outputStream = fr.getStreamFromFile(fileName);
public List<HashMap<String,ArrayList<String>>> getRacersInfo(){
return outputStream.map(line -> Arrays.asList(line.substring(0,3))
.collect(Collectors.toMap(???)); //Some code here which I cannot come up with.
}
Any help appreciated. If you need any additional information feel free to ask, I'll be glad to provide it.
Problem: FileReader
FileReader is obsolete, don't use it. It's outdated API, and it's problematic, in that it presumes 'platform default encoding' which is a different way of saying 'a bug waiting to happen that no test will catch but that will blow up in your face later'. You never want 'platform default encoding', especially as a silent default.
There's a new File API, and it lets you specify encoding explicitly. Also, in the new File API, if you don't, UTF-8 is assumed which is a far saner default than 'platform default'.
Problem: resources
Resources are objects that represent a resource that takes up OS-level handles. Files, network connections, database connections - those are some common examples of resources. The thing is unlike normal objects, you MUST explicitly CLOSE those. - if you don't, your VM will, eventually, crash. That means you can basically not put readers/inputstreams/outputstreams/writers in fields, ever, because how do you guarantee closing them? The only way is to make your own class a resource too (a thing that must explicitly be closed), which you can do, but is complicated, and not a good idea here.
You should never make resources unless you do so safely:
bad:
FileReader fr = new FileReader(..);
good:
try (FileReader fr = new FileReader(..)) {
// use here
}
// it's gone here
It does require you to restyle things a bit. You have to open a resource, use the resource, and close it. This meshes well with pragmatic concerns: Resources are a drain on the OS, you don't want to keep em open any longer than you must, so 'open it, use it, and lose it' is the right mindset.
Furthermore, of course, resources as a concept are generally 'once-through-only'. for example, when reading a file, well, you read it, once, from the top to the bottom, and then any further attempts to read from it don't work anymore. So, in your example, the first time I call getRacersInfo(), it works. But the second time I call it, it won't, as the reader has now been consumed.
The solution to both problems is to do the reading in the constructor*.
*) See later - we're going to move this out of the constructor eventually, but that's a separate concern.
Problem: Misunderstanding of responsibilities of constructors
This class is called a FileParser. So, it's job is to parse files (that, or, this class has a bad name). Generally, your constructors represent the 'data gathering' phase, not the 'do the job' phase. Therefore, parsing the file in the first place, in that constructor, is bad code style. You should not do this - your constructors should as a rule do as little as possible and definitely nothing tricky, such as opening files or actually parsing things. Again - the JOB of a FileParser is to parse files, and constructors should not do the job. They just set up the object so that it can do the job later.
The proper design, then, is:
public class FileParser {
private final Path path;
public FileParser(Path path) {
this.path = path;
}
public List<Map<String, List<String>> parseRacersInfo() {
try (Stream<String> lines = Files.lines(path)) {
lines.map(.... parse the content here ....);
}
}
}
We have now:
Moved the 'job' part to a method that accurately describes the job.
Ensured the constructor is simple and just gathers information to do the job.
Safely use resources by applying the try(){} concept.
Use the new API (java.nio.file.Files and java.nio.file.Path).
Clarified our typing: That parameter to the constructor represents a path. If I call new FileParser("Hello, IceTea, how's life?") - that call makes no sense. Path is more descriptive than String, and if your method makes sense looking only at the types of the parameters? That's better than if you need to read the docs too.
Problem: Not using java the way it wants to be used
Java is typed. Nominally so. Things should be stored in types that represent that thing. Thus, the string 2018-05-24_12:18:20.125 should be represented by an object that represents a time of some sort. Not a List<String> containing the string 2018-05-24 and 12:18:20.125.
Finally: How do I actually write the mapping?
Streams work by zooming in on a single element in the stream, and doing a series of operations on these elements, transforming them, filtering some out, etcetera. You cannot 'go back' in the process (once you map a thing to another thing, you can't go back to what it used to be), and you can't refer to other objects in your stream (you can't ask: Give me the item before me in the stream).
Thus, once you go: line.substring(0, 3), you've thrown out the date, and that's a problem because we need that info. Therefore, you can't do that; not in a .map() operation, at any rate.
In fact, we can go straight to collecting the stream back into a map here - we need that entire string and we can derive the key from it (SVF), and we need that entire string and we can derive the value from it (the date).
Let's write these conversion functions, and let's translate our string representing a time to a proper (also new in java 8) type for it: java.time.LocalDateTime:
Function<String, String> toKey = in -> in.substring(0, 3);
DateTimeFormatter DATETIME_FORMAT =
DateTimeFormatter.ofPattern("uuuu-MM-dd_HH:mm:ss.SSS", Locale.ENGLISH);
Function<String, LocalDateTime> toValue = in ->
LocalDateTime.parse(in.substring(3), DATETIME_FORMAT);
These are simple and we can test them:
assertEquals("VBM", toKey.apply("VBM2018-05-24_12:00:00.000"));
assertEquals(LocalDateTime.of(2018, 5, 24, 12, 0, 0),
toValue.apply("VBM2018-05-24_12:00:00.000"));
Then we put it all together:
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class FileParser {
private static final DateTimeFormatter DATETIME_FORMAT =
DateTimeFormatter.ofPattern("uuuu-MM-dd_HH:mm:ss.SSS", Locale.ENGLISH);
private final Path path;
public FileParser(Path path) {
this.path = path;
}
public Map<String, LocalDateTime> parseRacersInfo() throws IOException {
try (Stream<String> lines = Files.lines(path)) {
return lines.collect(Collectors.toMap(
in -> in.substring(0, 3),
in -> LocalDateTime.parse(in.substring(3), DATETIME_FORMAT)));
}
}
public static void main(String[] args) throws Exception {
System.out.println(new FileParser("test.txt").parseRacersInfo());
}
}
Path path = Paths.get(fileName);
try (Stream<String> lines = Files.lines(path)) {
Map<String, List<LocalDateTime>> map = lines.collect(Collectors.groupingBy(
line -> line.substring(0, 3),
line -> LocalDateTime.parse(line.substring(3).replace('_', 'T')));
}
The toMap receives a key mapper and a value mapper. Here I keep the Stream of lines.
The resulting map is just a Map. Never provide an implementation, HashMap so the collect may return its own implementation. (If effect you could provide an implementation.)
(I used Files.lines which defaults to UTF-8 encoding, but you can add an encoding. The reason: Path is more generalized than File.)
Something like :
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Test {
public static void main(String[] args) {
String fileName = "C:\\Users\\Asmir\\Desktop\\input1.txt";
Map<String,List<String>> map = new HashMap<>();
try (Stream<String> stream = Files.lines(Paths.get(fileName))) {
map = stream
.collect(Collectors.toMap(s -> s.substring(0,3), s -> Arrays.asList(s.substring(3).split("_"))));
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(map);
}
}
I need to be able to re-use a java.io.InputStream multiple times, and I figured the following code would work, but it only works the first time.
Code
public class Clazz
{
private java.io.InputStream dbInputStream, firstDBInputStream;
private ArrayTable db;
public Clazz(java.io.InputStream defDB)
{
this.firstDBInputStream = defDB;
this.dbInputStream = defDB;
if (db == null)
throw new java.io.FileNotFoundException("Could not find the database at " + db);
if (dbInputStream.markSupported())
dbInputStream.mark(Integer.MAX_VALUE);
loadDatabaseToArrayTable();
}
public final void loadDatabaseToArrayTable() throws java.io.IOException
{
this.dbInputStream = firstDBInputStream;
if (dbInputStream.markSupported())
dbInputStream.reset();
java.util.Scanner fileScanner = new java.util.Scanner(dbInputStream);
String CSV = "";
for (int i = 0; fileScanner.hasNextLine(); i++)
CSV += fileScanner.nextLine() + "\n";
db = ArrayTable.createArrayTableFromCSV(CSV);
}
public void reloadDatabase()//A method called by the UI
{
try
{
loadDatabaseToArrayTable();
}
catch (Throwable t)
{
//Alert the user that an error has occurred
}
}
}
Note that ArrayTable is a class of mine, which uses arrays to give an interface for working with tables.
Question
In this program, the database is shown directly to the user immediately after the reloadDatabase() method is called, and so any solution involving saving the initial read to an object in memory is useless, as that will NOT refresh the data (think of it like a browser; when you press "Refresh", you want it to fetch the information again, not just display the information it fetched the first time). How can I read a java.io.InputStream more than once?
You can't necessarily read an InputStream more than once. Some implementations support it, some don't. What you are doing is checking the markSupported method, which is indeed an indicator if you can read the same stream twice, but then you are ignoring the result. You have to call that method to see if you can read the stream twice, and if you can't, make other arrangements.
Edit (in response to comment): When I wrote my answer, my "other arrangements" was to get a fresh InputStream. However, when I read in your comments to your question about what you want to do, I'm not sure it is possible. For the basics of the operation, you probably want RandomAccessFile (at least that would be my first guess, and if it worked, that would be the easiest) - however you will have file access issues. You have an application actively writing to a file, and another reading that file, you will have problems - exactly which problems will depend on the OS, so whatever solution would require more testing. I suggest a separate question on SO that hits on that point, and someone who has tried that out can perhaps give you more insight.
you never mark the stream to be reset
public Clazz(java.io.InputStream defDB)
{
firstDBInputStream = defDB.markSupported()?defDB:new BufferedInputStream(defDB);
//BufferedInputStream supports marking
firstDBInputStream.mark(500000);//avoid IOException on first reset
}
public final void loadDatabaseToArrayTable() throws java.io.IOException
{
this.dbInputStream = firstDBInputStream;
dbInputStream.reset();
dbInputStream.mark(500000);//or however long the data is
java.util.Scanner fileScanner = new java.util.Scanner(dbInputStream);
StringBuilder CSV = "";//StringBuilder is more efficient in a loop
while(fileScanner.hasNextLine())
CSV.append(fileScanner.nextLine()).append("\n");
db = ArrayTable.createArrayTableFromCSV(CSV.toString());
}
however you could instead keep a copy of the original ArrayTable and copy that when you need to (or even the created string to rebuild it)
this code creates the string and caches it so you can safely discard the inputstreams and just use readCSV to build the ArrayTable
private String readCSV=null;
public final void loadDatabaseToArrayTable() throws java.io.IOException
{
if(readCSV==null){
this.dbInputStream = firstDBInputStream;
java.util.Scanner fileScanner = new java.util.Scanner(dbInputStream);
StringBuilder CSV = "";//StringBuilder is more efficient in a loop
while(fileScanner.hasNextLine())
CSV.append(fileScanner.nextLine()).append("\n");
readCSV=CSV.toString();
fileScanner.close();
}
db = ArrayTable.createArrayTableFromCSV(readCSV);
}
however if you want new information you'll need to create a new stream to read from again
I am receiving a string from user which should be used as a location to save content to a file. This string should contain enough information, like a directory + file name.
My question is, how can I check whether the provided string is a valid path to save content to a file (at least in theory)?
It does not matter whether directories are created or not, or whether one has proper access to the location itself. I am only interested in checking the structure of the provided string.
How should I proceed? I was thinking about creating a File object, then extracting its URI. Is there any better way?
You can use File.getCanonicalPath() to validate according the current OS rules.
import java.io.File;
import java.io.IOException;
public class FileUtils {
public static boolean isFilenameValid(String file) {
File f = new File(file);
try {
f.getCanonicalPath();
return true;
}
catch (IOException e) {
return false;
}
}
public static void main(String args[]) throws Exception {
// true
System.out.println(FileUtils.isFilenameValid("well.txt"));
System.out.println(FileUtils.isFilenameValid("well well.txt"));
System.out.println(FileUtils.isFilenameValid(""));
//false
System.out.println(FileUtils.isFilenameValid("test.T*T"));
System.out.println(FileUtils.isFilenameValid("test|.TXT"));
System.out.println(FileUtils.isFilenameValid("te?st.TXT"));
System.out.println(FileUtils.isFilenameValid("con.TXT")); // windows
System.out.println(FileUtils.isFilenameValid("prn.TXT")); // windows
}
}
Have you looked at Apache Commons IO? This library includes various things for handling path information which may help e.g. FilenameUtils.getPath(String filename) which returns the path from a full filename.
Easiest: try to save, listen for exceptions.
The only time I'd do something more complicated would be if the writing was to be deferred, and you want to give the user his feedback now.
Here is what I have so far:
private static boolean checkLocation(String toCheck) {
// If null, we necessarily miss the directory section
if ( toCheck == null ) {
System.out.println("Missing directory section");
return false;
}
String retrName = new File(toCheck).toURI().toString();
// Are we dealing with a directory?
if ( retrName.charAt(retrName.length()-1) == '/') {
System.out.println("Missing file name");
return false;
}
return true;
}
This tells me whether I have a proper directory structure and whether I am pointing to a directory rather than a file. I do not need I/O access.
I have noticed that if I use the File.createNewFile() method on a location pointing explicitly to a directory (which does not exist yet), Java creates a file with no extension, which is plain wrong. Either it should create a directory or it should throw some kind of error.
Also, the File constructors tend to add the current directory if none is provided in the argument. It is not documented, but no real harm in my case.
If anyone has a better solution, I'll approve it.
EDIT
I have finally combined the above with the input from RealHowTo.
I have a class in C++ which takes an std::ostream as an argument in order to continuously output text (trace information). I need to get this text over to the Java side as efficiently as possible. What's the best way to do this? I was thinking of using a direct buffer, but another method would be to take all the function calls across to Java and do all the processing there, but it seems that I'd need a lot of JNI calls.
If an example could be shown of the exact implementation method, it would be very helpful, or if some code exists already to do this (perhaps part of another project). Another help would be to connect it up directly to a standard Java streaming construct, such that the entire implementation was completely transparent to the developer.
(Edit: I found Sharing output streams through a JNI interface which seems to be a duplicate, but not really of much help -- he didn't seem to find the answer he was looking for)
The std::ostream class requires a std::streambuf object for its output. This is used by the fstream and stringstream classes, which use the features of ostream by providing a custom implementation of the streambuf class.
So you can write your own std::streambuf implementation with an overwritten overflow method, buffer the incomming chars in an internal stringbuffer. Every x calls or on eof/newline generate an java-string and call the print method of your java PrintStream.
An incomplete example class:
class JavaStreamBuff : std::streambuf
{
std::stringstream buff;
int size;
jobject handle;
JNIEnv* env
//Ctor takes env pointer for the working thread and java.io.PrintStream
JavaStreamBuff(JNIEnv* env, jobject jobject printStream, int buffsize = 50)
{
handle = env->NewGlobalRef(printStream);
this->env = env;
this->size = size;
}
//This method is the central output of the streambuf class, every charakter goes here
int overflow(int in)
{
if(in == eof || buff.size() == size)
{
std::string blub = buff.str();
jstring do = //magic here, convert form current locale unicode then to java string
jMethodId id = env->(env->GetObjectClass(handle),"print","(java.lang.String)V");
env->callVoidMethod(id,handle,do);
buff.str("");
}
else
{buff<<in;}
}
virtual ~JavaStreamBuff()
{
env->DeleteGlobalRef(handle);
}
}
Missing:
Multithread support (the env pointer is only valid for the jvm thread)
Error handling (checking for java exceptions thrown)
Testing(written within the last 70 min)
Native java method to set the printstream.
On the java side you need a class to convert the PrintStream to a BufferedReader.
There have to be some bugs there, haven't spend enough time to work on them.
The class requires all access to be from the thread it was created in.
Hope this helps
Note
I got it to work with visual studio but I can't get it to work with g++, will try to debug that later.
Edit
Seems that I should have looked for a more official tutorial on this bevore posting my answer, the MSDN page on this topic derives the stringbuffer in a different way.
Sorry for posting this without testing it better :-(.
A small correction to the code above in a more or less unrelated point: Just implement InputStream with a custom class and push byte[] arrays instead of Strings from c++.
The InputStream has a small interface and a BufferedReader should do most of the work.
Last update on this one, since im unable to get it to work on linux, even with the comments on the std::streambuf class stating that only overflow has to be overwritten.
This implementation pushes the raw strings into an inputstream, which can be read from by an other thread. Since I am too stupid to get the debugger working its untested, again.
//The c++ class
class JavaStreamBuf :public std::streambuf
{
std::vector<char> buff;
unsigned int size;
jobject handle;
JNIEnv* env;
public:
//Ctor takes env pointer for the working thread and java.io.PrintStream
JavaStreamBuf(JNIEnv* env, jobject cppstream, unsigned int buffsize = 50)
{
handle = env->NewGlobalRef(cppstream);
this->env = env;
this->size = size;
this->setbuf(0,0);
}
//This method is the central output of the streambuf class, every charakter goes here
virtual int_type overflow(int_type in = traits_type::eof()){
if(in == std::ios::traits_type::eof() || buff.size() == size)
{
this->std::streambuf::overflow(in);
if(in != EOF)
buff.push_back(in);
jbyteArray o = env->NewByteArray(buff.size());
env->SetByteArrayRegion(o,0,buff.size(),(jbyte*)&buff[0]);
jmethodID id = env->GetMethodID(env->GetObjectClass(handle),"push","([B)V");
env->CallVoidMethod(handle,id,o);
if(in == EOF)
env->CallVoidMethod(handle,id,NULL);
buff.clear();
}
else
{
buff.push_back(in);
}
return in;
}
virtual ~JavaStreamBuf()
{
overflow();
env->DeleteGlobalRef(handle);
}
//The java class
/**
*
*/
package jx;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* #author josefx
*
*/
public class CPPStream extends InputStream {
List<Byte> data = new ArrayList<Byte>();
int off = 0;
private boolean endflag = false;
public void push(byte[] d)
{
synchronized(data)
{
if(d == null)
{
this.endflag = true;
}
else
{
for(int i = 0; i < d.length;++i)
{
data.add(d[i]);
}
}
}
}
#Override
public int read() throws IOException
{
synchronized(data)
{
while(data.isEmpty()&&!endflag)
{
try {
data.wait();
} catch (InterruptedException e) {
throw new InterruptedIOException();
}
}
}
if(endflag)return -1;
else return data.remove(0);
}
}
Sorry for wasting so much space^^(and time :-().
It sounds as though the deliverable here is a subclass of ostream. The immediate question I'd want to be clear about is, will this class be responsible for buffering data until Java calls into it to retrieve, or is it expected to immediately (synchronously?) call via JNI to pass it on? That will be the strongest guide to how the code will shape up.
If you can reasonably expect the text to appear as a series of lines, I'd think about presenting them to Java in one line per call: this seems a fair compromise between the number of JNI calls and not unduly delaying the passing on of the text.
On the Java side I think you're looking at creating a Reader so that clients can pick up the text via a familiar interface, or perhaps a subclass of BufferedReader.
I am accustomed to java.io.* and java.util.* but not to the tree:
com.starbase.util
Class FileUtils
java.lang.Object
|
+--com.starbase.util.FileUtils
Source.
So which class should I import to use the isBinary-method? Do I do "import java.lang.Object;" or "import java.lang.Object.com.starbase.util.FileUtils;"?
You would do import com.starbase.util.FileUtils; or import static com.starbase.util.FileUtils.*. The hierarchy is just showing that the class FileUtils extends Object (as do all classes).
You do also have to have the .jar file/API to access this class.
EDIT: Added possible standalone implementation:
If you want to implement this yourself (I noticed your own 'trivial' answer), you could do something like this:
public static boolean isBinary(String fileName) throws IOException {
return isBinary(new File(fileName));
}
public static boolean isBinary(File file) throws IOException {
InputStream is = new FileInputStream(file);
try {
byte[] buf = new byte[4096];
int bytesRead;
while ((bytesRead = is.read(buf)) >= 0)
{
for (int i = 0; i < bytesRead; i++) {
if (buf[i] == (byte) 0)
return true;
}
}
return false;
} finally {
is.close();
}
}
Please note, I have not tested this.
I should add that this is the trivial implementation. There are many kinds of text files that would be considered binary with this. If you were to allow text to be Unicode and/or UTF-8 (or other text encoding) then this quickly becomes very difficult. Then you need to develop some kinds of heuristics to differentiate between the kinds of files and this would not be 100% accurate. So, it really depends on what you are trying to do with this.
You never have to import java.lang.Object, it's imported implicitely and is the class that every other class is derived from. When you import another class, you import it based on the package it's in. So for the class you want to use it would be:
import com.starbase.util.FileUtils;
com.starbase.util.FileUtils is not in the standard packaged Java SDK, but instead the StarTeam SDK which you would need to download in order to use the FileUtils#isBinary method.
Once installed, you would just need to add:
import com.starbase.util.FileUtils;
However, if you do not want to use a third-party SDK, let us know how isBinary would be helpful to you and we could find a standard Java equivalent.
Also to clarify, import.java.lang.Object.com.starbase.util.FileUtils is not a valid import, you are concatenating two different packages together.
It has to be either import java.lang.Object or import com.starbase.util.FileUtils.
Totally trivial and perhaps easiest but very unreliable!
if( filename.toLowerCase().trim().endsWith(".bin"))
return "Binary";