read .arff file using Weka library in java - java

I am trying to read an .arff file in Weka. I did this code. I keep getting error not sure about my work.
public String fileArff(String filePath) throws Exception
{
try {
BufferedReader br = new BufferedReader(new FileReader(filePath));
ArffReader re = new ArffReader(br);
Instances data = re.getData();
data.setClassIndex(data.numAttributes()-1);
File file = new File(filePath);
if (file.exists() && file.isFile() && file.canRead()) {
return "The file exists";
}
while (data != null)
{
re.appened(data);
re.appened("\n");
data = br.getData();
}
return re.toString();
}
catch (IOException e)
{
return "There is an error";
}
}
I am trying to read a .arff file in java language, and I used Weka library.

The code after the line data.setClassIndex is either unnecessary or not valid (like re.appened or br.getData). I recommend reading the Javadoc documentation of the Weka API for the relevant classes that you want to use.
The following code has the method readArff, which reads an ARFF file using the DataSource class (this class can the Weka Loader to use automatically based on the file's extension) and returns the Instances dataset object that it generated from it. It will throw an IOException if the file does not exist.
The main method calls the readArff method, expecting one argument (the path to the ARFF file to read) to be supplied when executing the ArffHelper class.
import weka.core.Instances;
import weka.core.converters.ConverterUtils;
import java.io.File;
import java.io.IOException;
public class ArffHelper {
public Instances readArff(String path) throws Exception {
if (!new File(path).exists())
throw new IOException("File does not exist: " + path);
Instances data = ConverterUtils.DataSource.read(path);
data.setClassIndex(data.numAttributes() - 1); // assuming that the class is the last attribute
return data;
}
public static void main(String[] args) throws Exception {
ArffHelper b = new ArffHelper();
Instances data = b.readArff(args[0]);
System.out.println(data);
}
}

Related

Create a file which cannot be deleted by file.delete()

Note: I am aware there are several questions similar to this one, however, I cannot find any which explain how to resolve the situation I am trying to resolve. I will ask this question with a specific example, for which I need a solution.
Consider the code:
private final void writeToFile(final File parent, final String filename, final Charset charset, final String content) throws IOException {
final File file = new File(parent, filename);
if (file.exists()) {
LOG.warn("File {} already exists, file will be replaced.", file.getCanonicalPath());
if (!file.delete()) {
logAndThrow(String.format("Cannot delete file '%s'.", file.getCanonicalPath()), null);
}
}
try (final FileOutputStream fos = new FileOutputStream(file);
OutputStreamWriter writer = new OutputStreamWriter(fos, charset)) {
writer.write(content);
}
}
I am trying to write a unit test to provoke the IOException being thrown when the code cannnot delete the file. The unit test I have tried is as follows:
#Test public void testFileNotDeletable() throws IOException {
final File file = new File(folder.getRoot(), formattedFile.getMetaData().getFormattedCaptureFileName());
file.createNewFile();
try {
file.setReadOnly();
exception.expect(IOException.class);
exception.expectMessage(String.format("Cannot delete file '%s'.", file.getCanonicalPath()));
writer.write(formattedFile);
} finally {
file.setWritable(true);
}
}
I have also tried locking the file:
#Test public void testFileNotDeletable() throws IOException {
final File file = new File(folder.getRoot(), formattedFile.getMetaData().getFormattedCaptureFileName());
file.createNewFile();
try (FileInputStream fis = new FileInputStream(file)) {
final FileLock lock = fis.getChannel().tryLock(0L, Long.MAX_VALUE, true);
try {
exception.expect(IOException.class);
exception.expectMessage(String.format("Cannot delete file '%s'.", file.getCanonicalPath()));
writer.write(formattedFile);
} finally {
lock.release();
}
}
}
No matter what I try, the file.delete() successfully deletes the file, and the test fails, as the expected IOException was not thrown.
Any help greatly appreciated.
Note: Added for clarification, some extra code that shows that the File object is completely separate in the environments. The formattedFile being passed to the write method is not a File or sub-class of File, it is one of our internal classes. The File in the JUnit test is using a TemporaryFolder for the root, the formattedFile has a MetaData item, which determines the filename. In my JUnit test I am trying to create an empty file, which cannot be deleted, in the location that my actual code will attempt to write the file. I need file.delete() to return false, so that I can test the exception is being thrown. I therefore cannot mock a File object.
There are two solutions to your question, I recommend the first one.
Solution 1
You are not testing the java file I/O operations/class here, you are testing your code's functional behaviour in response to file operation. So, ideally in your JUnit you should be mocking the File object & its respective calls, and only focus on testing your code.
Solution 2
If you still wish to test full integration with java file IO, open file in write mode before attempting to delete, and it will take care of your test case.
NOTE: Code tested in CENTOS, WINDOWS, UBUNTU, MAC OS-X
Subject Class:
public class FileSolution {
public void fileHandler(File file) throws IOException, Exception {
if (file.exists()) {
LOG.warn("File {} already exists, file will be replaced.",
file.getCanonicalPath());
if (!file.delete()) {
logAndThrow(String.format("Cannot delete file '%s'.",
file.getCanonicalPath()),
new IOException(String.format("Cannot delete file '%s'.",
file.getCanonicalPath())));
}
}
}
}
Subject Uner Test:
import static org.mockito.BDDMockito.*;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
public class FileSolutionTest {
#Rule
public final ExpectedException exception = ExpectedException.none();
/**
* Solution 1
*
* #throws Exception
*/
#Test
public void testFileNotDeletableWithMock() throws Exception {
final File file = mock(File.class);
file.createNewFile();
// mock file & IO operations
given(file.exists()).willReturn(true);
given(file.delete()).willReturn(false);
given(file.getCanonicalPath()).willReturn("test.txt");
exception.expect(IOException.class);
exception.expectMessage(String.format("Cannot delete file '%s'.", file.getCanonicalPath()));
new FileSolution().fileHandler(file);
}
/**
* Solution 2
*
* #throws Exception
*/
#Test
public void testFileNotDeletable() throws Exception {
File file = null;
FileWriter fileWriter = null;
try{
file = new File("test.txt");
file.createNewFile();
file.deleteOnExit();
exception.expect(IOException.class);
exception.expectMessage(String.format("Cannot delete file '%s'.", file.getCanonicalPath()));
// open file with another process for writing
fileWriter = new FileWriter(file, true);
new FileSolution().fileHandler(file);
} finally{
if(fileWriter != null){
fileWriter.flush();
fileWriter.close();
}
}
}
}
I totally agree with Turing85 about using mockito.
Let's imagine you have an original class with a method similar to the one you want to test:
public class FileDel {
public void logOnIOException(File file) throws IOException {
if (file.exists()) {
LOG.warn("File {} already exists, file will be replaced.", file.getCanonicalPath());
if (!file.delete()) {
logAndThrow(String.format("Cannot delete file '%s'.", file.getCanonicalPath()), null);
}
}
}
public void logAndThrow(String msg, String s) {
//Do nothing
}
private static class LOG {
public static void warn(String msg, String path) {
}
}
}
Then you can trigger an inner exception in this way:
#RunWith(MockitoJUnitRunner.class)
public class FileDelTest {
#Test(expected = IOException.class)
public void testFileNotDeletable() throws IOException {
File file = mock(File.class);
when(file.exists()).thenReturn(true);
when(file.delete()).thenAnswer(new Answer<Boolean>() {
#Override
public Boolean answer(InvocationOnMock iom) throws Throwable {
throw new IOException();
}
});
FileDel f = new FileDel();
try {
f.methodToTest(file);
} finally {
}
}
}
What about open InputStream for this file and do not close it. Until file's descriptor will not be closed, file will not be deleted.
In order to prevent a file from being deleted you have to deny the security permission in windows. From the UI we would need to do something like
Right-click the file or document in your PC => Choose Properties;
In Security, tab Edit to change permission => Select Add and enter Everyone;
Press OK and select the group to change Full control permission to Deny;
Press Yes to confirm.
The only way I know of to change file permissions with Java are:
file.setExecutable(true|false);
file.setReadable(true|false);
file.setWritable(true|false);
and
File file = new File("test.txt");
if(file.exists())
{
//Setting file permissions for owner, group and others using PosixFilePermission
HashSet<PosixFilePermission> set = new HashSet<PosixFilePermission>();
//Adding owner's file permissions
set.add(PosixFilePermission.OWNER_EXECUTE);
set.add(PosixFilePermission.OWNER_READ);
set.add(PosixFilePermission.OWNER_WRITE);
//Adding group's file permissions
set.add(PosixFilePermission.GROUP_EXECUTE);
set.add(PosixFilePermission.GROUP_READ);
set.add(PosixFilePermission.GROUP_WRITE);
//Adding other's file permissions
set.add(PosixFilePermission.OTHERS_EXECUTE);
set.add(PosixFilePermission.OTHERS_READ);
set.add(PosixFilePermission.OTHERS_WRITE);
Files.setPosixFilePermissions(Paths.get("test.txt"), set);
}
else
{
System.out.println("Sorry...File doesn't exist.");
}
So, preventing a file from being deleted I would assume would have to do with file writing permissions. Try disabling the writable and maybe the executable permissions before trying to delete the file.
If this doesn't work then I do not believe it can be done with the Java language yet as these are the only methods available at the moment for changing file permissions. I could be wrong, but I have been unable to find anything else.
UPDATE
For Linux try the following:
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class ExecuteShellComand {
public static void main(String[] args) {
ExecuteShellComand obj = new ExecuteShellComand();
String command = "sudo chattr +i /backups/passwd";
// OR try
//String command = "sudo chattr +i -V /backups/passwd";
String output = obj.executeCommand(command);
System.out.println(output);
}
private String executeCommand(String command) {
StringBuffer output = new StringBuffer();
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader reader =
new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null) {
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
}
The above makes /backups/passwd file immutable (or undeletable). This implies that the file can’t be modified in any way: it can’t be deleted or renamed. You can’t even create a link to it and no data can be written to the file as well.
That's about the only thing I can think of.
Hope this helps.
In Linux you can, with the chattr command set a file that is "immutable" that cannot be deleted even by root. Someone else said "set file permissions" which is right, but did not give specific detail.
Cheers
D

trouble running java program in eclipse

I'm just starting out in java and I'm trying to make a greedy algorithm. The first step is to read the file.txt with the jewel values and bag weight limit and such. unfortunately I am having trouble getting the program to run. I am using eclipse and when I click run I get the following error message "the selection cannot be launched, and there are no recent launches".
When I select the java greedy algorithm folder in the file tree and select run i get the following message "selection does not contain a main type". the work file and file.txt are saved in the same folder on my desktop but I wonder if the program isn't finding it. here's my code:
/** open and read a file, and return the lines in the file as a list of strings */
private List<String> readFile(file.txt)
{
List<String> records = new ArrayList<String>();
try
{
BufferedReader reader = new BufferedReader(new FileReader(file.txt));
String line;
while (( line = reader.readLine()) != null)
{
records.add(line);
}
reader.close():
return records;
}
catch (Exception e)
{
System.err.format("Exception occurred trying to read '%s'.", file.txt);
e.printStackTrace();
return null;
}
}
Thanks for the help.
You have to add a method named void main(String[] args).
This is the method that gets called when you start your program.
In this main method you can call your readFile method, like so:
public static void main(String[] args) {
readFile();
}
A java class should have a main method then only you can run that.
So, your class will be like this.
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String... args) {
//call readFile
List<String> someList = readFile(<pass filename here>);
//do something here with someList
}
/** open and read a file, and return the lines in the file as a list of strings */
private static List<String> readFile(String filename)
{
List<String> records = new ArrayList<>();
try
{
BufferedReader reader = new BufferedReader(new FileReader(filename));
String line;
while (( line = reader.readLine()) != null)
{
records.add(line);
}
reader.close();
return records;
}
catch (Exception e)
{
System.err.format("Exception occurred trying to read '%s'.",filename );
e.printStackTrace();
return null;
}
}
}
Note that, I marked readFile method as static which is because I am invoking it from main method without creating an instance of Test class. If you create an instance of Test class, and call readFile method on it, then you can remove static modifier.
You are missing the
public static void main(String args[])
{
...
}
There you can call your function.

Scanner throws FileNotFoundException but using bufferedreader and inputstream doesn't?

I am trying to write code for a word guessing game, and it works well when I use bufferedreader and inputstream combined. But when I try it using scanner, it cannot find the file, even though in both instances the file is in the same folder. It is in a folder called res under the src folder in my project folder(I am coding in eclipse).
import java.util.ArrayList;
import java.util.Scanner;
import java.io.File;
public class WordGen {
private final String filename = "/res/words.txt";
File file = new File(filename);
Scanner input = null;
private ArrayList<String> list = new ArrayList<>();
public WordGen() {
try {
input = new Scanner(file);
while (input.hasNextLine()) {
String w = input.nextLine();
list.add(w);
}
} catch (Exception ex) {
System.out.println("File not found.");
}
}
public String getword() {
if (list.isEmpty()) {
return "NOTHING";
}
return list.get((int) (Math.random() * list.size()));
}
}
public class test {
public static void main(String[] args) {
WordGen wordgen = new WordGen();
System.out.println(wordgen.getword());
}
}
I tried searching for this problem but couldn't find it here. I am guessing it's a very small error which I cannot figure out. Thanks and regards.
EDIT: Here's the other code that worked(Everything else same as before):
public WordGenerator()
{
try(InputStream input = getClass().getResourceAsStream(fileName);
BufferedReader bfreader = new BufferedReader(new InputStreamReader(input)))
{
String line = "";
while ((line = bfreader.readLine()) != null)
words.add(line);
}
catch (Exception e)
{
System.out.println("Couldn't find file");
}
}
Scanner is trying to load a file - and you're providing an absolute filename, /res/words.txt.
In order to create an InputStream, you're loading a resource, giving it an absolute resource name, even though you've called the variable fileName:
getClass().getResourceAsStream(fileName)
That works because it can load a resource called /res/words.txt from the classpath, but it's not loading a file with a filename of /res/words.txt.
You could use a filename of res/words.txt, if you run the code from the src directory... or you could just stick to using getResourceAsStream, which is probably a better idea as it doesn't rely on your working directory, and will continue to work even if your code and resources are packaged up into a jar file.
If you really want to use Scanner, you could always use new Scanner(input) - there's a Scanner constructor accepting an InputStream.

Is there a way I can convert a FileInputStream to an Object without using ObjectInputStream?

I was wondering if it was possible to get an object from a FileInputStream without using ObjectInputStream.
Why am I doing this? I've been working on a project recently, it reads .DAT files from a game and converts them to .OBJ - There is a catch to these .DAT files however: Their stream header is ALWAYS 0xFACEAF0E. Is there a way I can get around the restriction ObjectInputStream has on stream headers and get an Object from one of these files?
Here is the code I need help with.
package xan_code;
/*
* Purpose: Determine file extension and run it through the code to move it to an OBJ.
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Scanner;
import main.BeginConversion; //Import the conversion code. Returns a string based on the file
import xan_code.dathandler.ReadBinary; //Get the .DAT reading functions
#SuppressWarnings("serial")
public class HandleFiles extends Main { //Extend main to get the log from the opener UI.
static BeginConversion converter = new BeginConversion(); //Get the converter for XML files since this will also read XMLs derived from the .DAT
static String DatText = ""; //The "text" to return for the .DAT (To pack into the decoded file)
static Object _object; //THIS IS THE VARIABLE OF THE OBJECT I NEED IN ORDER TO CONVERT THE .DAT TO A MODEL
#SuppressWarnings("static-access")
public static String convert(File file, boolean isXML, FileInputStream FIS) { //Convert. Passes in the .DAT or .XML file, a boolean to whether or not its extension is .XML, and the FileInputStream from file
if (isXML) { //If it's an XML
String xml = ""; //This is the text to store the XML as a string
String obj = ""; //This is the text to store the WaveFront OBJ (Model format) as a string
try {
xml = new Scanner(file).useDelimiter("\\Z").next(); //use the scanner to get the string of the XML
obj = converter.BeginConvert(xml); //Pass the XML into the java files required to read from the XML and convert it to an OBJ. They return the text from an OBJ file.
} catch (Exception e) {
//Exceptions are handled before, though to be safe...
e.printStackTrace();
}
return obj; //Return that text to Main so I can create the file.
} else { //We have a .DAT
try {
//HELP REQUIRED HERE. NEED TO GET _object FROM THE FILE WITHOUT USING ObjectInputStream
DatText = ReadBinary.Read(file, _object); //Right now this actually returns the text of an XML, but that doesn't matter much at the moment.
} catch (IOException e) {
DatText = "Unexpected error while reading .DAT file!";
e.printStackTrace();
}
return DatText;
}
}
}
You can just strip off the extra bytes that ObjectInputStream should not see first with a FileInputStream.
static class MyObject implements Serializable{
int i;
}
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
MyObject obj = new MyObject();
obj.i = 77;
File testFile = new File("test.dat");
try (FileOutputStream fos = new FileOutputStream(testFile)) {
fos.write(new byte[]{(byte) 0xFA, (byte) 0xCE, (byte) 0xAF, (byte) 0x0E});
try (ObjectOutputStream oos = new ObjectOutputStream(fos)) {
oos.writeObject(obj);
}
}
try (FileInputStream fis = new FileInputStream(testFile)) {
byte b4[] = new byte[4];
fis.read(b4);
try (ObjectInputStream ois = new ObjectInputStream(fis)) {
MyObject newObj = (MyObject) ois.readObject();
System.out.println("newObj.i = " + newObj.i);
}
}
}

Reading all files in a package and copying the contents to a List or a map

I am currently working on a machine learning project. I have a package/directory of java files and i want to read their contents. Later, i will apply other methods to achieve results.
The problem is that the given code reads the txt files, however, when i pass the directory containing java files it doesn't work properly. Following is what I did
I read the names of all files in a directory.
As every directory has different number of files and different structure of files and folders inside it. I am looking for a generic solution.
Next, I read the contents of every file and put it in a list or MAP or whatever
The given code is as follows. I have written 3 methods.
This method list all files in a directory and make a set
// it will list all files in a directory.
public Collection<File> listFileTree(File dir) {
Set<File> fileTree = new HashSet<File>();
for (File entry : dir.listFiles()) {
if (entry.isFile())
fileTree.add(entry);
else
fileTree.addAll(listFileTree(entry));
}
return fileTree;
}
Here using the above method i have tried to read the contents of each file.
File file = new File("C:\\txt_sentoken");// c\\japa..if i use it code only show directory files
Iterator<File> i = Util.listFileTree(file).iterator();
String temp = null;
while(i.hasNext()){
temp = Util.readFile(i.next().getAbsolutePath().toString());
System.out.println(temp);
}
}
This is the readFile method
// using scanner class for reading file contents
public String readFile(String pathname) throws IOException {
File file = new File(pathname);
StringBuilder fileContents = new StringBuilder((int)file.length());
Scanner scanner = new Scanner(file);
String lineSeparator = System.getProperty("line.separator");
try {
while(scanner.hasNextLine()) {
fileContents.append(scanner.nextLine() + lineSeparator);
}
return fileContents.toString();
} finally {
scanner.close();
}
}
If i pass a directory (in File file = new File("C:\\txt_sentoken");) containing txt files this code works but for java or c++ or other code directories or packages it doesn't.
Can anyone guide me in refining this code? Also if there is any API or generic solution available please share.
Use Java NIO.2 to achieve your goal.
If you need any filtering you can put checks in the FileVisitor.
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
public class Test {
public static void main(String... args) {
try {
System.out.println(readAllFiles("")); // <----- Fill in path
} catch (IOException e) {
e.printStackTrace();
}
}
public static Map<Path, List<String>> readAllFiles(String path) throws IOException {
final Map<Path, List<String>> readFiles = new TreeMap<>();
Files.walkFileTree(Paths.get(path), new SimpleFileVisitor<Path>() {
#Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Objects.requireNonNull(file);
readFiles.put(file, Files.readAllLines(file, StandardCharsets.UTF_8));
return FileVisitResult.CONTINUE;
}
});
return readFiles;
}
}
A Java 8 - also sorted - solution would be:
public static Map<Path, List<String>> readAllFiles(String path) throws IOException {
return Files.walk(Paths.get(path)).filter(p -> !Files.isDirectory(p)).collect(Collectors.toMap(k -> k, k -> {
try {
return Files.readAllLines(k);
} catch (IOException e) {
throw new RuntimeException(e);
}
} , (u, v) -> {
throw new IllegalStateException(String.format("Duplicate key %s", u));
} , TreeMap::new));
}

Categories