I am trying to implement c45 algorithm on Map Reduce and the code here generates only a rule set given some training data.
This class contains the main method.
public class DecisionTreec45 extends Configured implements Tool
{
public static MySplit currentsplit=new MySplit();
public static List <MySplit> splitted=new ArrayList<MySplit>();
public static int current_index=0;
public static void main(String[] args) throws Exception {
MyMapper mp=new MyMapper();
splitted.add(currentsplit);
int res=0;
// double bestGain=0;
// boolean stop=true;
// boolean outerStop=true;
int split_index=0;
double gainratio=0;
double best_gainratio=0;
double entropy=0;
String classLabel=null;
int total_attributes=mp.no_Attr;
total_attributes=4;
int split_size=splitted.size();
MyGainRatio gainObj;
MySplit newnode;
while(split_size>current_index)
{
currentsplit = (MySplit) splitted.get(current_index);
gainObj = new MyGainRatio();
res = ToolRunner.run(new Configuration(), new DecisionTreec45(), args);
System.out.println("Current NODE INDEX . ::"+current_index);
int j=0;
int temp_size;
gainObj.getcount();
entropy=gainObj.currNodeEntophy();
classLabel=gainObj.majorityLabel();
currentsplit.classLabel=classLabel;
if(entropy!=0.0 && currentsplit.attr_index.size()!=total_attributes)
{
System.out.println("");
System.out.println("Entropy NOTT zero SPLIT INDEX:: "+entropy);
best_gainratio=0;
for(j=0;j<total_attributes;j++) //Finding the gain of each attribute
{
if(currentsplit.attr_index.contains(j)) // Splitting all ready done with this attribute
{
// System.out.println("Splitting all ready done with index "+j);
}
else
{
gainratio=gainObj.gainratio(j,entropy);
if(gainratio>=best_gainratio)
{
split_index=j;
best_gainratio=gainratio;
}
}
}
String attr_values_split=gainObj.getvalues(split_index);
StringTokenizer attrs = new StringTokenizer(attr_values_split);
int number_splits=attrs.countTokens(); //number of splits possible with attribute selected
String red="";
// int tred=-1;
System.out.println(" INDEX :: "+split_index);
System.out.println(" SPLITTING VALUES "+attr_values_split);
for(int splitnumber=1;splitnumber<=number_splits;splitnumber++)
{
temp_size=currentsplit.attr_index.size();
newnode=new MySplit();
for(int y=0;y<temp_size;y++) // CLONING OBJECT CURRENT NODE
{
newnode.attr_index.add(currentsplit.attr_index.get(y));
newnode.attr_value.add(currentsplit.attr_value.get(y));
}
red=attrs.nextToken();
newnode.attr_index.add(split_index);
newnode.attr_value.add(red);
splitted.add(newnode);
}
}
else
{
System.out.println("");
String rule="";
temp_size=currentsplit.attr_index.size();
for(int val=0;val<temp_size;val++)
{
rule=rule+" "+currentsplit.attr_index.get(val)+" "+currentsplit.attr_value.get(val);
}
rule=rule+" "+currentsplit.classLabel;
writeRuleToFile(rule);
if(entropy!=0.0)
System.out.println("Enter rule in file:: "+rule);
else
System.out.println("Enter rule in file Entropy zero :: "+rule);
}
split_size=splitted.size();
System.out.println("TOTAL NODES:: "+split_size);
current_index++;
}
System.out.println("COMPLETE");
System.exit(res);
}
public static void writeRuleToFile(String text)
{
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(new File("/home/hduser/C45/rule.txt/"), true));
bw.write(text);
bw.newLine();
bw.close();
} catch (Exception e) {
}
}
public int run(String[] args) throws Exception
{
JobConf conf = new JobConf(getConf(),DecisionTreec45.class);
conf.setJobName("c4.5");
// the keys are words (strings)
conf.setOutputKeyClass(Text.class);
// the values are counts (ints)
conf.setOutputValueClass(IntWritable.class);
conf.setMapperClass(MyMapper.class);
conf.setReducerClass(MyReducer.class);
//set your input file path below
FileInputFormat.setInputPaths(conf, "/home/hduser/Id3_hds/playtennis.txt");
FileOutputFormat.setOutputPath(conf, new Path("/home/hduser/Id3_hds/1/output"+current_index));
JobClient.runJob(conf);
return 0;
}
}
This class is used to calculate the gain ratio.
public class MyGainRatio
{
int linenumber=0;
static String count[][]=new String[10000][4];
int currnode[]=new int[100];
String majorityLabel=null;
public String majorityLabel()
{
return majorityLabel;
}
//Calculation of entrophy
public double currNodeEntophy()
{
int currentindex=0;
double entropy=0;
currentindex=Integer.parseInt(count[0][0]);
int i=0;
int covered[]=new int[1000];
String classLabel=count[0][2];
int j=0;
int ind=-1;
int maxStrength=0;
System.out.println("Values in node rep to classwise");
while(currentindex==Integer.parseInt(count[j][0]))
{
if(covered[j]==0)
{
classLabel=count[j][2];
ind++;
i=j;
while(currentindex==Integer.parseInt(count[i][0]))
{
if(covered[i]==0)
{
if(classLabel.contentEquals(count[i][2]))
{
currnode[ind] = currnode[ind]+Integer.parseInt(count[i][3]);
covered[i]=1;
}
}
i++;
if(i==linenumber)
break;
}
if(currnode[ind]>maxStrength)
{
maxStrength=currnode[ind];
majorityLabel=classLabel;
}
System.out.print(" "+classLabel+" "+currnode[ind]);
}
else
{
j++;
}
if(j==linenumber)
break;
}
entropy=entropy(currnode);
return entropy;
}
public double entropy(int c[])
{
double entropy=0;
int i=0;
int sum=0;
double frac;
while(c[i]!=0)
{
sum=sum+c[i];
i++;
}
i=0;
while(c[i]!=0)
{
frac=(double)c[i]/sum;
entropy=entropy-frac*(Math.log(frac)/Math.log(2));
i++;
}
return entropy;
}
public void getcount()
{
DecisionTreec45 id=new DecisionTreec45();
FileInputStream fstream;
try {
fstream = new FileInputStream("/home/hduser/C45/output/intermediate" + id.current_index + ".txt");
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line;
//Read File Line By Line
StringTokenizer itr;
// System.out.println("READING FROM intermediate "+id.current_index);
while ((line = br.readLine()) != null) {
itr= new StringTokenizer(line);
count[linenumber][0]=itr.nextToken();
count[linenumber][1]=itr.nextToken();
count[linenumber][2]=itr.nextToken();
count[linenumber][3]=itr.nextToken();
int i=linenumber;
linenumber++;
}
count[linenumber][0]=null;
count[linenumber][1]=null;
count[linenumber][2]=null;
count[linenumber][3]=null;
in.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
//Close the input stream
}
}
public double gainratio(int index,double enp)
{
//100 is considered as max ClassLabels
int c[][]=new int[1000][100];
int sum[]=new int[1000]; //
String currentatrrval="#3#441get";
double gainratio=0;
int j=0;
int m=-1; //index for split number
int lines=linenumber;
int totalsum=0;
for(int i=0;i<lines;i++)
{
if(Integer.parseInt(count[i][0])==index)
{
if(count[i][1].contentEquals(currentatrrval))
{
j++;
c[m][j]=Integer.parseInt(count[i][3]);
sum[m]=sum[m]+c[m][j];
}
else
{
j=0;
m++;
currentatrrval=count[i][1];
c[m][j]=Integer.parseInt(count[i][3]); //(different class) data sets count per m index split
sum[m]=c[m][j];
}
}
}
int p=0;
while(sum[p]!=0)
{
totalsum=totalsum+sum[p]; //calculating total instance in node
p++;
}
double wtenp=0;
double splitenp=0;
double part=0;
for(int splitnum=0;splitnum<=m;splitnum++)
{
part=(double)sum[splitnum]/totalsum;
wtenp=wtenp+part*entropy(c[splitnum]);
}
splitenp=entropy(sum);
gainratio=(enp-wtenp)/(splitenp);
return gainratio;
}
public String getvalues(int n)
{ int flag=0;
String values="";
String temp="%%%%%!!#";
for(int z=0;z<1000;z++)
{
if(count[z][0]!=null)
{
if(n==Integer.parseInt(count[z][0]))
{
flag=1;
if(count[z][1].contentEquals(temp))
{
// System.out.println("Equals COUNT Index z "+z+" "+count[z][1]+ "temp "+temp);
}
else
{
values=values+" "+count[z][1];
temp=count[z][1];
}
}
else if(flag==1)
break;
}
else
break;
}
return values;
}
}
This mapper class checks whether this instance belongs to Current Node or not.
For all uncovered attributes it outputs index and its value
and class label of instance.
public class MyMapper extends MapReduceBase
implements Mapper<LongWritable, Text, Text, IntWritable> {
private final static IntWritable one = new IntWritable(1);
private Text attValue = new Text();
private Text cLabel = new Text();
private int i;
private String token;
public static int no_Attr;
//public static int splitAttr[];
private int flag=0;
public void map(LongWritable key, Text value,OutputCollector<Text, IntWritable> output,Reporter reporter) throws IOException {
DecisionTreec45 id=new DecisionTreec45();
MySplit split=null;
int size_split=0;
split=id.currentsplit;
String line = value.toString(); //changing input instance value to string
StringTokenizer itr = new StringTokenizer(line);
int index=0;
String attr_value=null;
no_Attr=itr.countTokens()-1;
String attr[]=new String[no_Attr];
boolean match=true;
for(i=0;i<no_Attr;i++)
{
attr[i]=itr.nextToken(); //Finding the values of different attributes
}
String classLabel=itr.nextToken();
size_split=split.attr_index.size();
for(int count=0;count<size_split;count++)
{
index=(Integer) split.attr_index.get(count);
attr_value=(String)split.attr_value.get(count);
if(attr[index].equals(attr_value)) //may also use attr[index][z][1].contentEquals(attr_value)
{
//System.out.println("EQUALS IN MAP nodes "+attr[index]+" inline "+attr_value);
}
else
{
// System.out.println("NOT EQUAL IN MAP nodes "+attr[index]+" inline "+attr_value);
match=false;
break;
}
}
//id.attr_count=new int[no_Attr];
if(match)
{
for(int l=0;l<no_Attr;l++)
{
if(split.attr_index.contains(l))
{
}
else
{
token=l+" "+attr[l]+" "+classLabel;
attValue.set(token);
output.collect(attValue, one);
}
}
if(size_split==no_Attr)
{
token=no_Attr+" "+"null"+" "+classLabel;
attValue.set(token);
output.collect(attValue, one);
}
}
}
}
This class counts number of occurrences of combination of ( index and
its value and class Label ) and prints count against it.
public class MyReducer extends MapReduceBase implements
Reducer<Text, IntWritable, Text, IntWritable> {
public void reduce(Text key, Iterator<IntWritable> values,
OutputCollector<Text, IntWritable> output, Reporter reporter)
throws IOException {
int sum = 0;
String line = key.toString();
// StringTokenizer itr = new StringTokenizer(line);
while (values.hasNext()) {
sum += values.next().get();
}
output.collect(key, new IntWritable(sum));
writeToFile(key + " " + sum);
/*
* int index=Integer.parseInt(itr.nextToken()); String
* value=itr.nextToken(); String classLabel=itr.nextToken(); int
* count=sum;
*/
}
public static void writeToFile(String text) {
try
{
DecisionTreec45 id = new DecisionTreec45();
BufferedWriter bw = new BufferedWriter(new FileWriter(new File(
"/home/hduser/C45/output/intermediate" + id.current_index
+ ".txt"), true));
bw.write(text);
bw.newLine();
bw.close();
}
catch (Exception e)
{
}
}
}
This class Splits the attributes
public class MySplit implements Cloneable
{
public List attr_index;
public List attr_value;
double entophy;
String classLabel;
MySplit()
{
this.attr_index= new ArrayList<Integer>();
this.attr_value = new ArrayList<String>();
}
MySplit(List attr_index,List attr_value)
{
this.attr_index=attr_index;
this.attr_value=attr_value;
}
void add(MySplit obj)
{
this.add(obj);
}
}
The input training data set looks like this->
sunny hot high weak no
sunny hot high strong no
overcast hot high weak yes
rain mild high weak yes
rain cool normal weak yes
rain cool normal strong no
overcast cool normal strong yes
sunny mild high weak no
sunny cool normal weak yes
rain mild normal weak yes
sunny mild normal strong yes
overcast mild high strong yes
overcast hot normal weak yes
rain mild high strong no
Related
I have an arraylist of object type:
public static ArrayList crimes = new ArrayList();
The CityCrime.java has the following:
public class CityCrime {
//Instance variables
private String city;
private String state;
private int population;
private int murder;
private int robbery;
private int assault;
private int burglary;
private int larceny;
private int motorTheft;
public int totalCrimes;
public static void main(String[] args) {
}
public int getTotalCrimes() {
return totalCrimes;
}
public void setTotalCrimes(int murder, int robbery, int assault, int burglary, int larceny, int motorTheft) {
this.totalCrimes = murder + robbery + assault + burglary + larceny + motorTheft;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
if(state.equalsIgnoreCase("ALABAMA")) {
this.state = "AL";
}
else if(state.equalsIgnoreCase("ALASKA")) {
this.state = "AK";
}
else if(state.equalsIgnoreCase("ARIZONA")) {
this.state = "AR";
}
//etc
}
public int getPopulation() {
return population;
}
public void setPopulation(int population) {
this.population = population;
}
public int getMurder() {
return murder;
}
public void setMurder(int murder) {
this.murder = murder;
}
public int getRobbery() {
return robbery;
}
public void setRobbery(int robbery) {
this.robbery = robbery;
}
public int getAssault() {
return assault;
}
public void setAssault(int assault) {
this.assault = assault;
}
public int getBurglary() {
return burglary;
}
public void setBurglary(int burglary) {
this.burglary = burglary;
}
public int getLarceny() {
return larceny;
}
public void setLarceny(int larceny) {
this.larceny = larceny;
}
public int getMotorTheft() {
return motorTheft;
}
public void setMotorTheft(int motorTheft) {
this.motorTheft = motorTheft;
}
public static void showAllMurderDetails() {
for (CityCrime crime : StartApp.crimes) {
System.out.println("Crime: City= " + crime.getCity() + ", Murder= " + crime.getMurder());
}
System.out.println();
}
public static int showAllViolentCrimes() {
int total = 0;
for(CityCrime crime : StartApp.crimes) {
total=total+crime.getMurder();
total=total+crime.getRobbery();
total=total+crime.getAssault();
}
System.out.println("Total of violent crimes: " + total);
return total;
}
public static int getPossessionCrimes() {
int total=0;
for (CityCrime crime : StartApp.crimes) {
total = total + crime.getBurglary();
total = total + crime.getLarceny();
total = total + crime.getMotorTheft();
}
System.out.println("Total of possession crimes: " + total);
return total;
}
}
The CityCrime ArrayList gets popular from another csv file:
public static void readCrimeData() {
File file = new File("crimeUSA.csv");
FileReader fileReader;
BufferedReader bufferedReader;
String crimeInfo;
String[] stats;
try {
fileReader = new FileReader(file);
bufferedReader = new BufferedReader(fileReader);
crimeInfo = bufferedReader.readLine();
crimeInfo = bufferedReader.readLine();
do {
CityCrime crime = new CityCrime(); // Default constructor
stats = crimeInfo.split(",");
{
if (stats[0] != null) {
crime.setCity(stats[0]);
}
if (stats[1] != null) {
crime.setState(stats[1]);
}
if (stats[2] != null) {
if (Integer.parseInt(stats[2]) >= 0) {
crime.setPopulation(Integer.parseInt(stats[2]));
}
}
if (stats[3] != null) {
if (Integer.parseInt(stats[3]) >= 0) {
crime.setMurder(Integer.parseInt(stats[3]));
}
}
if (stats[4] != null) {
if (Integer.parseInt(stats[4]) >= 0) {
crime.setRobbery(Integer.parseInt(stats[4]));
}
}
if (stats[5] != null) {
if (Integer.parseInt(stats[5]) >= 0) {
crime.setAssault(Integer.parseInt(stats[5]));
}
}
if (stats[6] != null) {
if (Integer.parseInt(stats[6]) >= 0) {
crime.setBurglary(Integer.parseInt(stats[6]));
}
}
if (stats[7] != null) {
if (Integer.parseInt(stats[7]) >= 0) {
crime.setLarceny(Integer.parseInt(stats[7]));
}
}
if (stats[8] != null) {
if (Integer.parseInt(stats[8]) >= 0) {
crime.setMotorTheft(Integer.parseInt(stats[8]));
}
}
crime.setTotalCrimes(Integer.parseInt(stats[3]), Integer.parseInt(stats[4]), Integer.parseInt(stats[5]), Integer.parseInt(stats[6]), Integer.parseInt(stats[7]), Integer.parseInt(stats[8]));
}
crimes.add(crime);
System.out.println(crime);
crimeInfo = bufferedReader.readLine();
} while (crimeInfo != null);
fileReader.close();
bufferedReader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
I want to sort the array list and output to the csv file the list of robberies in descending order with the corresponding city. So far I have got the following, but I am stuck and not sure if going in the right direction. I'm relatively new to Java as you can probably tell so would appreciate it in as simple terms as can be:
public static void writeToFile() throws IOException {
File csvFile = new File("Robbery.csv");
FileWriter fileWriter = new FileWriter(csvFile);
ArrayList<Integer> robberyRates = new ArrayList();
for(CityCrime crime : crimes) {
robberyRates.add(crime.getRobbery());
}
Collections.sort(robberyRates);
}
The desired output will be for example:
Robbery,City
23511,New York
15863,Chicago
14353,Los Angeles
11371,Houston
10971,Philadelphia
etc…
Your help is appreciated. I have searched any page I can find on Google, but all I see from other example is writing to the csv from a set String ArrayList where they know the number of lines etc. Thankyou
You can try something like this:
public static void writeToFile() throws IOException {
File csvFile = new File("Robbery.csv");
try(FileWriter fileWriter = new FileWriter(csvFile)) { // try-with-resources to be sure that fileWriter will be closed at end
StringBuilder stringBuilder = new StringBuilder(); // Betther than String for multiple concatenation
crimes.sort(Comparator.comparingInt(CityCrime::getRobbery).reversed()); // I want to compare according to getRobbery, as Int, in reversed order
stringBuilder.append("Robbery")
.append(',')
.append("City")
.append(System.lineSeparator()); // To get new line character according to OS
for (final var crime : crimes)
stringBuilder.append(crime.getRobbery())
.append(',')
.append(crime.getCity())
.append(System.lineSeparator());
fileWriter.write(stringBuilder.toString());
}
}
If you are stuck because you can't figure out how to write a list, convert your list into a String and print the String instead.
I commented the piece of code, if you have any questions, don't hesitate.
Another solution is to use specific CSV parser library, OpenCSV for example.
It makes it easier to read and write CSV file.
Here a tutorial about OpenCSV:
https://mkyong.com/java/how-to-read-and-parse-csv-file-in-java/
Im trying to read a txt file and save into a array but im only getting null in the output of my array. What am i missing?
A part of the txt file, and yes it is with these blank lines between the numbers
306741
581016
783580
529978
772824
54939
797499
235178
675900
365768
561760
986962
242452
621124
555822
80045
914383
634731
18956
The code that creates the array
public class Stack {
protected final int MAX=1000000;
protected Integer[]pilha;
Stack(){
pilha = new Integer[MAX];
}
void add(Integer newElement){
int i;
for(i=0;pilha[i]!=null;i++);
pilha[i]= newElement;
}
And the main:
public class Main {
public static void main(String[] args) throws Exception {
File file = new File("D:\\entradas\\tarefas1000.txt");
Scanner sc = new Scanner(file);
Stack guardar=new Stack();
while (sc.hasNext()){
guardar.add(sc.nextInt());
}
sc.close();
System.out.println(Arrays.toString(guardar.pilha));
}
}
public class Stack {
protected final int MAX = 1_000_000;
protected int[] pilha;
private int numero;
Stack(){
pilha = new int[MAX];
}
void add(int newElement){
pilha[numero] = newElement;
++numero;
}
public int size() {
return numero;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('[');
boolean needsComma = false;
for (int i = 0; i < numero; ++i) {
if (needsComma) {
sb.append(", ");
}
sb.append(pilha[i]);
needsComma = true;
};
sb.append(']');
return sb.toString(); // Arrays.toString(pilha);
}
}
public static void main(String[] args) throws Exception {
Stack guardar = new Stack();
Path file = Paths.get("D:\\entradas\\tarefas1000.txt");
Files.lines(file) //This method needs a parameter to work on
.forEach(line -> {
if (!line.trim().isEmpty()) {
guardar.add(Integer.parseInt(line));
}
});
System.out.println(guardar);
}
I have a class which represents an ArrayList stored in a file, because I need an ArrayList with multiple gigabytes of data in it which is obviously too large to be stored in memory. The data is represented by a class called Field and the function Field.parse() is just for converting the Field into a String and the other way.
The Field class stores a list of (strange) chess pieces and their coordinates.
My class is working fine, but it takes a long time to add an element to the file and I need my program to run as fast as possible. Does anyone know a more efficient/faster way of doing things?
Also, I am not allowed to use external libraries/apis. Please keep that in mind.
This is the class which is responsible for storing Field objects in a temp file:
private File file;
private BufferedReader reader;
private BufferedWriter writer;
public FieldSaver() {
try {
file = File.createTempFile("chess-moves-", ".temp");
System.out.println(file.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
}
public void add(Field field) {
try {
File temp = File.createTempFile("chess-moves-", ".temp");
writer = new BufferedWriter(new FileWriter(temp));
reader = new BufferedReader(new FileReader(file));
String line;
while((line = reader.readLine()) != null ) {
writer.write(line);
writer.newLine();
}
reader.close();
writer.write(field.parse());
writer.close();
file.delete();
file = new File(temp.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
}
public Field get(int n) {
try {
reader = new BufferedReader(new FileReader(file));
for (int i = 0; i < n; i++) {
reader.readLine();
}
String line = reader.readLine();
reader.close();
return Field.parse(line);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
And this is the Field class:
private WildBoar wildBoar;
private HuntingDog[] huntingDogs;
private Hunter hunter;
private int size;
#Override
public String toString() {
String result = "Wildschwein: " + wildBoar.toString();
for (HuntingDog dog : huntingDogs) {
result += "; Hund: " + dog.toString();
}
return result + "; Jäger: " + hunter.toString();
}
#Override
public boolean equals(Object obj) {
if (obj instanceof Field) {
Field field = (Field) obj;
HuntingDog[] dogs = field.getHuntingDogs();
return wildBoar.equals(field.getWildBoar()) && hunter.equals(field.getHunter()) && huntingDogs[0].equals(dogs[0]) && huntingDogs[1].equals(dogs[1]) && huntingDogs[2].equals(dogs[2]);
}
return false;
}
public Field(int size, WildBoar wildBoar, HuntingDog[] huntingDogs, Hunter hunter) {
this.size = size;
this.wildBoar = wildBoar;
this.huntingDogs = huntingDogs;
this.hunter = hunter;
}
public WildBoar getWildBoar() {
return wildBoar;
}
public HuntingDog[] getHuntingDogs() {
return huntingDogs;
}
public Hunter getHunter() {
return hunter;
}
public int getSize() {
return size;
}
public static Field parse(String s) {
String[] arr = s.split(",");
WildBoar boar = WildBoar.parse(arr[0]);
Hunter hunter = Hunter.parse(arr[1]);
HuntingDog[] dogs = new HuntingDog[arr.length - 2];
for(int i = 2; i < arr.length; i++) {
dogs[i - 2] = HuntingDog.parse(arr[i]);
}
return new Field(8, boar, dogs, hunter);
}
public String parse() {
String result = wildBoar.parse() + "," + hunter.parse();
for(HuntingDog dog : huntingDogs) {
result += "," + dog.parse();
}
return result;
}
Here's an MCVE to do what you want, based on the information you provided.
You can run it and see that it can save a Field to the file and get a Field by index very quickly.
The Fields are constant length, so you can get a Field by index by going to byte offset of index times field length in bytes. This would be significantly more difficult if the field were not constant length.
import java.io.Closeable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class FieldSaver implements Closeable {
public static void main(String[] args) throws IOException {
File f = File.createTempFile("chess-moves-", ".temp");
try (FieldSaver test = new FieldSaver(f);) {
for (byte i = 0; i < 100; i++) {
test.add(new Field(8, new WildBoar(i, i), new Hunter(i, i), new HuntingDog[] {
new HuntingDog(i, i),
new HuntingDog(i, i),
new HuntingDog(i, i) }));
}
// Get a few Fields by index
System.out.println(test.get(0));
System.out.println(test.get(50));
System.out.println(test.get(99));
// EOF exception, there is no Field 100
// System.out.println(test.get(100));
}
}
private final RandomAccessFile data;
public FieldSaver(File f) throws FileNotFoundException {
data = new RandomAccessFile(f, "rw");
}
public void add(Field field) throws IOException {
data.seek(data.length());
field.write(data);
}
public Field get(int index) throws IOException {
data.seek(index * Field.STORAGE_LENGTH_BYTES);
return Field.read(data);
}
public void close() throws IOException { data.close(); }
static abstract class Piece {
protected byte xPos;
protected byte yPos;
public Piece(DataInput data) throws IOException {
xPos = data.readByte();
yPos = data.readByte();
}
public Piece(byte xPos, byte yPos) {
this.xPos = xPos;
this.yPos = yPos;
}
public void write(DataOutput data) throws IOException {
data.writeByte(xPos);
data.writeByte(yPos);
}
public String toString() { return "[" + xPos + ", " + yPos + "]"; }
}
static class Hunter extends Piece {
public Hunter(byte xPos, byte yPos) { super(xPos, yPos); }
public Hunter(DataInput data) throws IOException { super(data); }
}
static class HuntingDog extends Piece {
public HuntingDog(byte xPos, byte yPos) { super(xPos, yPos); }
public HuntingDog(DataInput data) throws IOException { super(data); }
}
static class WildBoar extends Piece {
public WildBoar(byte xPos, byte yPos) { super(xPos, yPos); }
public WildBoar(DataInput data) throws IOException { super(data); }
}
static class Field {
// size of boar + hunter + 3 dogs
public static final int STORAGE_LENGTH_BYTES = 2 + 2 + (3 * 2);
private int size;
private WildBoar boar;
private Hunter hunter;
private final HuntingDog[] dogs;
public Field(int size, WildBoar wildBoar, Hunter hunter, HuntingDog[] huntingDogs) {
this.size = size;
this.boar = wildBoar;
this.hunter = hunter;
this.dogs = huntingDogs;
}
public String toString() {
String result = "Wildschwein: " + boar.toString();
for (HuntingDog dog : dogs) {
result += "; Hund: " + dog.toString();
}
return result + "; Jäger: " + hunter.toString();
}
public static Field read(DataInput data) throws IOException {
WildBoar boar = new WildBoar(data);
Hunter hunter = new Hunter(data);
HuntingDog[] dogs = new HuntingDog[3];
for (int i = 0; i < 3; i++) {
dogs[i] = new HuntingDog(data);
}
return new Field(8, boar, hunter, dogs);
}
public void write(DataOutput data) throws IOException {
boar.write(data);
hunter.write(data);
for (HuntingDog dog : dogs) {
dog.write(data);
}
}
}
}
Use a Map implementation like Cache from ehcache. This library will optimize for you so you don't have to handle writing and reading to disk and manage when to keep it in memory or on disk. You can just use it as a normal map. You probably want a map instead of a list for faster lookup so the library can optimize even more for you.
http://www.ehcache.org/
CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
.withCache("preConfigured",
CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
ResourcePoolsBuilder.heap(100))
.build())
.build(true);
Cache<Long, String> preConfigured
= cacheManager.getCache("preConfigured", Long.class, String.class);
I have a program that is supposed to load a text file and display/sort the data, however the data is not being displayed at all. Any ideas as to what I'm doing wrong? I have to stick with 1.4.2 Java only.
Here is the code:
import java.io.*;
import java.util.StringTokenizer;
class NewClass {
private static int quantity;
private static String[] name;
public static void main(String args[]) throws Exception {
InputStreamReader kb = new InputStreamReader(System.in);
BufferedReader in;
in = new BufferedReader(kb);
String buffer;
char choice;
boolean fileread=false;
int[]number=new int[quantity];
String[]name=new String[quantity];
String sorttype="";
do
{ //Setup Menu
choice=menu(in);
if(choice=='E')
{
if(fileread)
System.out.println("Data already has been entered");
else
{
fileread=true;
getdata(number,name);
}
}
else if(choice=='D')
{
if(fileread)
display(number,name,in);
else
System.out.println("Must enter data before it is displayed");
}
else if(choice=='S')
{
if(fileread)
sorttype=sort(number,name,in);
else
System.out.println("Must enter data before it is sorted");
}
} while(choice!='X');
}
//Sort Data
public static void sortint(int[] number, String[] name)
{
int i,j;
for(i=0;i<quantity-1;i++)
for(j=i+1;j<quantity;j++)
if(number[i]>number[j])
{
swap(number,i,j);
swap(name,i,j);
}
}
public static void sortstring(String[] name, int[] number)
{
int i,j;
for(i=0;i<quantity-1;i++)
for(j=i+1;j<quantity;j++)
if(name[i].compareToIgnoreCase(name[j])>0)
{
swap(number,i,j);
swap(name,i,j);
}
}
public static void swap(int[] a,int i,int j)
{
int t;
t=a[i];
a[i]=a[j];
a[j]=t;
}
public static void swap(String[] a,int i,int j)
{
String t;
t=a[i];
a[i]=a[j];
a[j]=t;
}
public static String sort(int[] number, String[] name, BufferedReader kb)throws Exception
{
String buffer;
do
{
//Allow user to sort the phone book
System.out.println("What do you want to sort by?");
System.out.println("Number");
System.out.println("Name");
System.out.print("Enter>>");
buffer=kb.readLine();
if(buffer.equalsIgnoreCase("number"))
{
sortint(number,name);
print(name, number,kb);
return buffer;
}
else if(buffer.equalsIgnoreCase("name"))
{
sortstring(name,number);
print(name,number,kb);
return buffer;
}
System.out.println("Invalid entry");
} while(true);
}
public static void print(String[] name, int[] number, BufferedReader kb)throws Exception
{
System.out.println("Sorted data");
System.out.println("Number\tName");
for(int i=0;i<quantity;i++)
System.out.println(number[i]+"\t"+name[i]);
}
public static void display(int[] number, String[] name, BufferedReader kb)throws Exception
{
System.out.println("Number Name");
for(int i=0;i<quantity;i++)
System.out.println(number[i]+" "+name[i]);
}
public static void getdata(int number[],String name[])throws Exception
{
FileReader file = new FileReader("phoneData.txt");
try (BufferedReader input = new BufferedReader(file)) {
int i;
String buffer;
for( i=0;i<quantity;i++)
{
buffer=input.readLine();
StringTokenizer st = new StringTokenizer(buffer, ",");
name[i]=st.nextToken();
number[i]=Integer.parseInt((st.nextToken()).trim());
}
}
}
public static char menu(BufferedReader kb)throws Exception
{
String buffer;
char input;
do
{
System.out.println("\nWhat would you like to do?");
System.out.println("E-Enter phone book data");
System.out.println("D-Display phone book data");
System.out.println("X-Exit program");
System.out.println("S-Sort list");
System.out.print("Enter E, D, X, S>>");
buffer=kb.readLine();
input=(buffer.toUpperCase()).charAt(0);
if(input=='E'||input=='D'||input=='X'||input=='S')
return input;
System.out.println("Invalid entry");
} while(true);
}
}
And here is what it is returning:
What would you like to do?
E-Enter phone book data
D-Display phone book data
X-Exit program
S-Sort list
Enter E, D, X, S>>D
Number Name
What would you like to do?
E-Enter phone book data
D-Display phone book data
X-Exit program
S-Sort list
Enter E, D, X, S>>
Any help is much appreciated.
You might want to initialize quantity
private static int quantity = 1;
instead of just
private static int quantity;
so that the code inside the the loop
for( i=0;i<quantity;i++)
can get a chance....
And as stated in my first comment, you should add some Exception handling and return value checking to your code.
Also you might just delete this line
private static String[] name;
since you have name declared locally in main.
EDIT
public static void getdata(int number[],String name[])throws Exception
{
BufferedReader input = null;
try {
input = new BufferedReader(new FileReader("phoneData.txt"));
int i;
String buffer;
for( i=0;i<quantity;i++)
{
// readLinde returns null when EOF is reached
buffer=input.readLine();
if(buffer != null) {
StringTokenizer st = new StringTokenizer(buffer, ",");
name[i]=st.nextToken();
number[i]=Integer.parseInt((st.nextToken()).trim());
} else {
break; // since nothing left to read
// remaining buckets in the arrays are left empty
}
}
} catch (Exception e) {
// catch exceptions to where know your program fails
System.out.println(e.toString());
} finally {
if(input != null) {
// close the input stream when you are done
input.close();
}
}
}
Also you should consider using List instead of arrays
public static void getdata(List number,List name) {
BufferedReader input = null;
try {
input = new BufferedReader(new FileReader("phoneData.txt"));
String buffer;
while(null != (buffer = input.readLine())) {
StringTokenizer st = new StringTokenizer(buffer, ",");
name.add(st.nextToken());
number.add(Integer.valueOf(Integer.parseInt((st.nextToken()).trim())));
}
} catch (Exception e) {
System.out.println(e.toString());
} finally {
if(input != null) {
try {
input.close();
} catch (IOException e) {
// ignore
}
}
}
}
I work at a printing company that has many programs in COBOL and I have been tasked to
convert the COBOL programs into JAVA programs. I've run into a snag in the one conversion. I need to take a file that each line is a record and on each line the data is blocked.
Example of a line is
60000003448595072410013 FFFFFFFFFFV 80 0001438001000014530020120808060134
I need to sort data by a 5 digit number at the 19-23 characters and then by the very first character on a line.
BufferedReader input;
BufferedWriter output;
String[] sort, sorted, style, accountNumber, customerNumber;
String holder;
int lineCount;
int lineCounter() {
int result = 0;
boolean eof = false;
try {
FileReader inputFile = new FileReader("C:\\Users\\cbook\\Desktop\\Chemical\\"
+ "LB26529.fil");
input = new BufferedReader(inputFile);
while (!eof) {
holder = input.readLine();
if (holder == null) {
eof = true;
} else {
result++;
}
}
} catch (IOException e) {
System.out.println("Error - " + e.toString());
}
return result;
}
chemSort(){
lineCount = this.lineCounter();
sort = new String[lineCount];
sorted = new String[lineCount];
style = new String[lineCount];
accountNumber = new String[lineCount];
customerNumber = new String[lineCount];
try {
FileReader inputFile = new FileReader("C:\\Users\\cbook\\Desktop\\Chemical\\"
+ "LB26529.fil");
input = new BufferedReader(inputFile);
for (int i = 0; i < (lineCount + 1); i++) {
holder = input.readLine();
if (holder != null) {
sort[i] = holder;
style[i] = sort[i].substring(0, 1);
customerNumber[i] = sort[i].substring(252, 257);
}
}
} catch (IOException e) {
System.out.println("Error - " + e.toString());
}
}
This what I have so far and I'm not really sure where to go from here or even if this is the correct way
to go about sorting the file. After the file is sorted it will be stored into another file and processed
again with another program for it to be ready for printing.
List<String> linesAsList = new ArrayList<String>();
String line=null;
while(null!=(line=reader.readLine())) linesAsList.add(line);
Collections.sort(linesAsList, new Comparator<String>() {
public int compare(String o1,String o2){
return (o1.substring(18,23)+o1.substring(0,1)).compareTo(o2.substring(18,23)+o2.substring(0,1));
}});
for (String line:linesAsList) System.out.println(line); // or whatever output stream you want
This phone's autocorrect is messing up my answer
Read the file into an ArrayList (instead of an array). Use the following methods:
// to declare the arraylist
ArrayList<String> lines = new ArrayList<String>();
// to add a new line to it (within your reading-lines loop)
lines.add(input.readLine());
Then, sort it using a custom Comparator:
Collections.sort(lines, new Comparator<String>() {
public int compare(String a, String b) {
String a5 = theFiveNumbersOf(a);
String b5 = theFiveNumbersOf(b);
int firstComparison = a5.compareTo(b5);
if (firstComparison != 0) { return firstComparison; }
String a1 = theDigitOf(a);
String b1 = theDigitOf(b);
return a1.compareTo(b1);
}
});
(It is unclear what 5 digits or what digit you want to compare; I've left them as functions for you to fill in).
Finally, write it to the output file:
BufferedWriter ow = new BufferedWriter(new FileOutputStream("filename.extension"));
for (String line : lines) {
ow.println(line);
}
ow.close();
(adding imports and try/catch as needed)
This code will sort a file based on mainframe sort parameters.
You pass 3 parameters to the main method of the Sort class.
The input file path.
The output file path.
The sort parameters in mainframe sort format. In your case, this string would be 19,5,CH,A,1,1,CH,A
This first class, the SortParameter class, holds instances of the sort parameters. There's one instance for every group of 4 parameters in the sort parameters string. This class is a basic getter / setter class, except for the getDifference method. The getDifference method brings some of the sort comparator code into the SortParameter class to simplify the comparator code in the Sort class.
public class SortParameter {
protected int fieldStartByte;
protected int fieldLength;
protected String fieldType;
protected String sortDirection;
public SortParameter(int fieldStartByte, int fieldLength, String fieldType,
String sortDirection) {
this.fieldStartByte = fieldStartByte;
this.fieldLength = fieldLength;
this.fieldType = fieldType;
this.sortDirection = sortDirection;
}
public int getFieldStartPosition() {
return fieldStartByte - 1;
}
public int getFieldEndPosition() {
return getFieldStartPosition() + fieldLength;
}
public String getFieldType() {
return fieldType;
}
public String getSortDirection() {
return sortDirection;
}
public int getDifference(String a, String b) {
int difference = 0;
if (getFieldType().equals("CH")) {
String as = a.substring(getFieldStartPosition(),
getFieldEndPosition());
String bs = b.substring(getFieldStartPosition(),
getFieldEndPosition());
difference = as.compareTo(bs);
if (getSortDirection().equals("D")) {
difference = -difference;
}
}
return difference;
}
}
The Sort class contains the code to read the input file, sort the input file, and write the output file. This class could probably use some more error checking.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Sort implements Runnable {
protected List<String> lines;
protected String inputFilePath;
protected String outputFilePath;
protected String sortParameters;
public Sort(String inputFilePath, String outputFilePath,
String sortParameters) {
this.inputFilePath = inputFilePath;
this.outputFilePath = outputFilePath;
this.sortParameters = sortParameters;
}
#Override
public void run() {
List<SortParameter> parameters = parseParameters(sortParameters);
lines = read(inputFilePath);
lines = sort(lines, parameters);
write(outputFilePath, lines);
}
protected List<SortParameter> parseParameters(String sortParameters) {
List<SortParameter> parameters = new ArrayList<SortParameter>();
String[] field = sortParameters.split(",");
for (int i = 0; i < field.length; i += 4) {
SortParameter parameter = new SortParameter(
Integer.parseInt(field[i]), Integer.parseInt(field[i + 1]),
field[i + 2], field[i + 3]);
parameters.add(parameter);
}
return parameters;
}
protected List<String> sort(List<String> lines,
final List<SortParameter> parameters) {
Collections.sort(lines, new Comparator<String>() {
#Override
public int compare(String a, String b) {
for (SortParameter parameter : parameters) {
int difference = parameter.getDifference(a, b);
if (difference != 0) {
return difference;
}
}
return 0;
}
});
return lines;
}
protected List<String> read(String filePath) {
List<String> lines = new ArrayList<String>();
BufferedReader reader = null;
try {
String line;
reader = new BufferedReader(new FileReader(filePath));
while ((line = reader.readLine()) != null) {
lines.add(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return lines;
}
protected void write(String filePath, List<String> lines) {
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(filePath));
for (String line : lines) {
writer.write(line);
writer.newLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (writer != null) {
writer.flush();
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
if (args.length < 3) {
System.err.println("The sort process requires 3 parameters.");
System.err.println(" 1. The input file path.");
System.err.println(" 2. The output file path.");
System.err.print (" 3. The sort parameters in mainframe ");
System.err.println("sort format. Example: 15,5,CH,A");
} else {
new Sort(args[0], args[1], args[2]).run();
}
}
}