I'm using this method
static void readFile()
{
try
{
FileInputStream fstream = new FileInputStream( "Insurances.txt" );
BufferedReader br = new BufferedReader( new InputStreamReader( fstream ) );
String strLine;
String [] array;
while ( ( strLine = br.readLine() ) != null )
{
array = strLine.split( "," );
pword++;
int type = Integer.parseInt(array[0]);
int tm = Integer.parseInt(array[1]);
int year = Integer.parseInt(array[2]);
int month = Integer.parseInt(array[3]);
int day = Integer.parseInt(array[4]);
int pass = Integer.parseInt(array[5]);
double tc = 0;
if ( type==2 )
{
String man = array[6];
String mod = array[7];
int cc = Integer.parseInt(array[8]);
String lp = array[9];
String ex = array [10];
boolean extra;
if ( ex.equals("true") )
{
extra = true;
}
else
{
extra = false;
}
insurances[insur] = new CarInsurance( pword, type, tm, year, month, day, pass, tc, man, mod, cc, lp, extra );
tc = insurances[insur].calculateCost( pass, a, insur );
insurances[insur].setCost( tc );
insur++;
}
else
{
insurances[insur] = new LifeInsurance( pword, type, tm, year, month, day, pass, tc );
tc = insurances[insur].calculateCost( pass, a, insur );
insurances[insur].setCost( tc );
insur++;
}
System.out.println("y");
}
inp.close();
}
catch ( Exception e )
{
e.getMessage();
}
}
to read some info from a txt file and create an object of my LifeInsurance class or my CarInsurance. The reason i use this System.out.println("y"); is to see whether it completes as many loops as the objects i want to create. When i try to run my programm i only get 7 loops ( 7 y's ) but i need 13. The following is what i have wrote on the txt file :
1,12,2013,6,1,1939
2,12,2008,1,10,1939,Mercedes,E200,2000,AEX32100,false
2,12,2009,1,11,1939,Mercedes,E200,2000,AEX32100,false
2,12,2009,2,10,1940,Fiat,Punto,1400,BIO1245,false
2,12,2009,2,10,1940,Seat,Ibiza,1600,BIE3987,false
2,12,2010,1,10,1940,Seat,Ibiza,1600,BIE3987,false
2,12,2013,6,1,1941,Audi,A4,1600,IXE1256,true
1,12,2008,1,2,1942
1,12,2009,1,2,1942
1,12,2010,1,2,1942
1,12,2011,1,2,1943
2,12,2010,7,23,1943,Renault,Clio,1400,ZIO3890,true
2,12,2011,7,23,1943,Renault,Clio,1400,ZIO3890,true
Could you please help me out because i can't find a reason why it doesn't complete all 13 loops. Thank you in advance.
You should see the line 18 of your LifeInsurance class as suggests your stacktrace:
java.lang.NullPointerException at LifeInsurance.calculateCost(LifeInsurance.java:18)
The data of your 8th line seems to induce something null in the cost calculation.
In order to know if it is an error from inexpected kind of data or a problem in your code, you should first replace 1st line by your 8th and then replace arguments one by one if you don't want to try to debug your code.
(sorry for the "answer" it seems that i cannot add a remark)
I am assuming that you have all of your records in Insurances.txt on different lines as your data does have 13 distinct records there if one reads closely.
You should also follow what #jlordo is saying and change e.getMessage() to e.printStackTrace(). By doing that and running your code, I was getting
Having said that you should also trim all of your strings produced by your strLine.split(",") call. For example (without error checking) use this Integer.parseInt(array[0].trim()) instead of this Integer.parseInt(array[0]).
By doing the trim I was able to see the 'y' print 13 times.
You will never get 13 loops if your input file doesn't have 13 lines. Your program is expected to read them one line at a time.
Related
I am a computer science university student working on my first 'big' project outside of class. I'm attempting to read through large text files (2,000 - 3,000 lines of text), line by line with buffered reader. When a keyword from a list of enums is located, I want it to send the current line from buffered reader to its appropriate method to be handled appropriatley.
I have a solution, but I have a feeling in my gut that there is a much better way to handle this situation. Any suggestions or feedback would be greatly appreciated.
Current Solution
I am looping through the the list of enums, then checking if the current enum's toString return is in the current line from buffered reader using the String.contains method.
If the enum is located, the enum is used in a switch statement for the appropriate method call. (I have 13 total cases just wanted to keep the code sample short).
try (BufferedReader reader = new BufferedReader(new FileReader(inputFile.getAbsoluteFile()))){
while ((currentLine = reader.readLine()) != null) {
for (GameFileKeys gameKey : GameFileKeys.values()) {
if (currentLine.contains(gameKey.toString())) {
switch (gameKey) {
case SEAT -> seatAndPlayerAssignment(currentTableArr, currentLine);
case ANTE -> playerJoinLate(currentLine);
}
}
}
}
}
Previous Solution
Originally, I had a nasty list of if statements checking if the current line contained one of the keywords and then handled it appropriatley. Clearly that is far from optimal, but my gut tells me that my current solution is also less than optimal.
try (BufferedReader reader = new BufferedReader(new FileReader(inputFile.getAbsoluteFile()))){
while ((currentLine = reader.readLine()) != null) {
if(currentLine.contains(GameFileKey.SEAT){
seatAndPlayerAssignment(currentTableArr, currentLine);
}
else if(currentLine.contains(GameFileKey.ANTE){
playerJoinLate(currentLine);
}
}
}
Enum Class
In case you need this, or have any general feedback for how I'm implementing my enums.
public enum GameFileKeys {
ANTE("posts ante"),
SEAT("Seat ");
private final String gameKey;
GameFileKeys(String str) {
this.gameKey = str;
}
#Override
public String toString() {
return gameKey;
}
}
I cannot improve over the core of your code: the looping on values() of the enum, performing a String#contains for each enum object’s string, and using a switch. I can make a few minor suggestions.
I suggest you not override the toString method on your enum. The Object#toString method is generally best used only for debugging and logging, not logic or presentation.
Your string passed to constructor of the enum is likely similar to the idea of a display name commonly seen in such enums. The formal enum name (all caps) is used internally within Java, while the display name is used for display to the user or exchanged with external systems. See the Month and DayOfWeek enums as examples offering a getDisplayName method.
Also, an enum should be named in the singular. This avoids confusion with any collections of the enum’s objects.
By the way, looks like you have a stray SPACE in your second enum's argument.
At first I thought it would help to have a list of all the display names, and a map of display name to enum object. However, in the end neither is needed for your purpose. I kept those as they might prove interesting.
public enum GameFileKey
{
ANTE( "posts ante" ),
SEAT( "Seat" );
private String displayName = null;
private static final List < String > allDisplayNames = Arrays.stream( GameFileKey.values() ).map( GameFileKey :: getDisplayName ).toList();
private static final Map < String, GameFileKey > mapOfDisplayNameToGameFileKey = Arrays.stream( GameFileKey.values() ).collect( Collectors.toUnmodifiableMap( GameFileKey :: getDisplayName , Function.identity() ) );
GameFileKey ( String str ) { this.displayName = str; }
public String getDisplayName ( ) { return this.displayName; }
public static GameFileKey forDisplayName ( final String displayName )
{
return
Objects.requireNonNull(
GameFileKey.mapOfDisplayNameToGameFileKey.get( displayName ) ,
"None of the " + GameFileKey.class.getCanonicalName() + " enum objects has a display name of: " + displayName + ". Message # 4dcefee2-4aa2-48cf-bf66-9a4bde02ac37." );
}
public static List < String > allDisplayNames ( ) { return GameFileKey.allDisplayNames; }
}
You can use a stream of the lines of your file being processed. Just FYI, not necessarily better than your code.
public class Demo
{
public static void main ( String[] args )
{
Demo app = new Demo();
app.demo();
}
private void demo ( )
{
try
{
Path path = Demo.getFilePathToRead();
Stream < String > lines = Files.lines( path );
lines.forEach(
line -> {
for ( GameFileKey gameKey : GameFileKey.values() )
{
if ( line.contains( gameKey.getDisplayName() ) )
{
switch ( gameKey )
{
case SEAT -> this.seatAndPlayerAssignment( line );
case ANTE -> this.playerJoinLate( line );
}
}
}
}
);
}
catch ( IOException e )
{
throw new RuntimeException( e );
}
}
private void playerJoinLate ( String line )
{
System.out.println( "line = " + line );
}
private void seatAndPlayerAssignment ( String line )
{
System.out.println( "line = " + line );
}
public static Path getFilePathToRead ( ) throws IOException
{
Path tempFile = Files.createTempFile( "bogus" , ".txt" );
Files.write( tempFile , "apple\nSeat\norange\nposts ante\n".getBytes() );
return tempFile;
}
}
When run:
line = Seat
line = posts ante
Before asking this question , i spent around half an hour on google , but since i didn't find a solution i thought i maybe should ask here.
So basically i'm using Java Reader to read a text file and converting each line of information into an Object that i called Nation ( With a constructor of course ) and making an array out of all those objects.
The problem is that a single line on my text file goes to 75 characters. But i get an error telling me that the length is only 68 ! So Here's the part of the code where i read informations from the file :
static int lireRemplir (String nomFichier, Nation[] nations)
throws IOException
{
boolean existeFichier = true;
int n =0;
FileReader fr = null;
try {
fr = new FileReader(nomFichier);
}
catch (java.io.FileNotFoundException erreur) {
System.out.println("Probléme avec l'ouverture du fichier " + nomFichier);
existeFichier = false;
}
if (existeFichier) {
BufferedReader entree = new BufferedReader(fr);
boolean finFichier = false;
while (!finFichier) {
String uneLigne = entree.readLine();
if (uneLigne == null) {
finFichier=true;
}
else {
nations[n] = new Nation(uneLigne.charAt(0),uneLigne.substring(55,63),
uneLigne.substring(64,74),uneLigne.substring(1,15),uneLigne.substring(36,54));
n++;
}
}
entree.close();
}
return n;
}
The Error i get is :
Exception in thread "main" java.lang.StringIndexOutOfBoundsException:
begin 64, end 74, length 68
Since i'm new here i tried to post an image of my text but i couldn't, so i'll just try to hand write an exemple:
2ETATS-UNIS WASHINGTON 9629047 291289535
4CHINE PEKIN 9596960 1273111290
3JAPON KYOTO 377835 12761000
There is alot of space between the words it's like an array!
If i change the 74 to 68 i get a result when i try to print my array , but the information is missing.
Here's my constructor:
public Nation(char codeContinent, String superficie, String population, String nom, String capitale) {
this.codeContinent = codeContinent;
this.superficie = superficie;
this.population = population;
this.nom = nom;
this.capitale = capitale;
}
I hope you could help me with this! If you need to know more about my code let me know ! Thank you very much.
To avoid Runtime Exceptions, you need to be careful with your code. In cases where you are dealing with indexes of a String or an array, please check for length of the String to be greater or equal to the maximum index you are using. Enclose you code that is throwing the exception within:
if(uneLigne.length() > 74) {
nations[n] = new Nation(uneLigne.charAt(0),uneLigne.substring(55,63),
uneLigne.substring(64,74),uneLigne.substring(1,15),uneLigne.substring(36,54));
} else {
//your logic to handle the line with less than 74 characters
}
This will ensure your code does not break even if any line is smaller than expected characters.
______________________________________________________________________________
Another approach
Adding the comment as an answer:
The other way would be to use split() method of String class or StringTokenizer class to get the array/tokens if the line is delimited with space or some other character. With this, you need not break the string using substring() method where you need to worry about the lengths and possible Runtime.
Check the below code snippet using split() method, for each line you read from file, you probably have to do this way:
Nation nation = null;
String uneLigne = "2ETATS-UNIS WASHINGTON 9629047 291289535";
String[] strArray = uneLigne.split(" ");
if(strArray.length > 3) {
nation = new Nation(getContinentCodeFromFirstElement(strArray[0]), strArray[1],
strArray[2], strArray[3], strArray[4]);
}
//getContinentCodeFromFirstElement(strArray[0]) is your private method to pick the code from your first token/element.
The simpliest way to solve your problem is to change the 74 by uneLigne.length.
Here's the new code.
nations[n] = new Nation(uneLigne.charAt(0),uneLigne.substring(55,63),
uneLigne.substring(64,uneLigne.length),uneLigne.substring(1,15),uneLigne.substring(36,54));
This is my whole code, it's quite complex but please help me. It's taken me for 2 days but I failed:
public static ArrayList<DocGia> XuatDocGia() throws IOException {
ArrayList<DocGia> listDocGia = new ArrayList<>();
File fileDocGia = new File("fileDocGia.txt");
if(fileDocGia.exists() == false) {
System.out.println("Chưa có đọc giả nào trong thư viện");
} else {
BufferedReader br = new BufferedReader(new FileReader("fileDocGia.txt"));
if (br.readLine() == null) {
System.out.println("Chưa có đọc giả nào trong thư viện");
} else {
int soDong = DemSoDong("fileDocGia.txt");
int dongHienTai = 0;
Scanner fileScanner = new Scanner(fileDocGia);
for(int i = 0, z = 0;;i++, z++) {
DocGia docGia = null;
System.out.println("***Đọc giả thứ: " + (i+1));
docGia.tendocgia = fileScanner.nextLine();
if(i >= 1) {
docGia.tendocgia = fileScanner.nextLine();
}
docGia.maDocGia = fileScanner.nextLine();
docGia.soSachmuon = fileScanner.nextInt();
docGia.thoiGianMuonSach = fileScanner.nextInt();
listDocGia.add(docGia);
docGia.XuatDocGia();
dongHienTai += 4;
if(dongHienTai == soDong) {
fileScanner.close();
break;
}
}
}
for(DocGia docGia: listDocGia) {
docGia.XuatDocGia();
}
}
return listDocGia;
}
look at my code, when i run:
docGia.XuatDocGia();
-> the value of every single element is right at debug. it also means the value of the variable inside is right. but at the end of this function. i run
for(DocGia docGia: listDocGia) {
docGia.XuatDocGia();
}
this is XuatDocGia funtion:
public static void XuatDocGia(){
System.out.println(tendocgia);
System.out.println(maDocGia);
System.out.println(soSachmuon);
System.out.println(thoiGianMuonSach);
}
It just shows for me the last element in this ArrayList, repeat in 3 times( equal the number of elements).
I think a problem come from adding process of listDocGia.add(docGia);
You guys no need to bother everything else in my code, because i know it's really complex. I have tested carefully, just focus on my problem.
I'm so sorry because i'm Vietnamese and beginner at Java. The next time everything will be English. Thank you so much.
If this is the actual code, you are adding null references to your List, but since you are using a static method to print the values, you don't get a NullPointerException. Assuming your code passes compilation, this means all the members of the DocGia class are static, which explains why you get the same values in each iteration of your loop.
You should change
DocGia docGia = null;
to
DocGia docGia = new DocGia ();
and change all the members of DocGia (including the XuatDocGia method that prints them) to be non static.
I'm currently executing a rather complicated data pre-processing operation, this is:
cat large_file.txt \ | ./reverb -q | cut --fields=16,17,18 | awk -F\\t -vq="'" 'function quote(token) { gsub(q, "\\"q, token); return q token q } { print quote($2) "(" quote($3) ", " quote($1) ")." }' >> output.txt
As you can see, this is rather convoluted, first cat, then to that ./reverb, then to cut, and finally to awk.
Next I want to pass the output to a java program, i.e.:
public static void main(String[] args) throws IOException
{
Ontology ontology = new Ontology();
BufferedReader br = new BufferedReader(new FileReader("/home/matthias/Workbench/SUTD/2_January/Prolog/horn_data_test.pl"));
Pattern p = Pattern.compile("'(.*?)'\\('(.*?)','(.*?)'\\)\\.");
String line;
while ((line = br.readLine()) != null)
{
Matcher m = p.matcher(line);
if( m.matches() )
{
String verb = m.group(1);
String object = m.group(2);
String subject = m.group(3);
ontology.addSentence( new Sentence( verb, object, subject ) );
}
}
for( String joint: ontology.getJoints() )
{
for( Integer subind: ontology.getSubjectIndices( joint ) )
{
Sentence xaS = ontology.getSentence( subind );
for( Integer obind: ontology.getObjectIndices( joint ) )
{
Sentence yOb = ontology.getSentence( obind );
Sentence s = new Sentence( xaS.getVerb(),
xaS.getObject(),
yOb.getSubject() );
System.out.println( s );
}
}
}
}
What would be the best way to synthesize this process into one coherent operation? Ideally I'd like to just specify the input file and the output file and run it once. As it stands the entire process is quite discombobulated.
Maybe I can just put all these calls into a bash script? Is that feasible?
The input initially contains English language sentences, one per line, this is:
Oranges are delicious and contain vitamin c.
Brilliant scientists learned that we can prevent scurvy by imbibing vitamin c.
Colorless green ideas sleep furiously.
...
The pre-processing makes it look like this:
'contain'('vitamin c','oranges').
'prevent'('scurvy','vitamin c').
'sleep'('furiously','ideas').
...
The java program is for learning "rules" by inference, so if the processed data yields 'contain'('vitamin c','oranges'). & 'prevent'('scurvy','vitamin c'). then the java code will emit 'prevent'('scurvy','oranges').
I looked at the source code for reverb and I think it's very easy to adapt it to produce the output you want. If you look at the reverb class CommandLineReverb.java, it has the following two methods:
private void extractFromSentReader(ChunkedSentenceReader reader)
throws ExtractorException {
long start;
ChunkedSentenceIterator sentenceIt = reader.iterator();
while (sentenceIt.hasNext()) {
// get the next chunked sentence
ChunkedSentence sent = sentenceIt.next();
chunkTime += sentenceIt.getLastComputeTime();
numSents++;
// make the extractions
start = System.nanoTime();
Iterable<ChunkedBinaryExtraction> extractions = extractor
.extract(sent);
extractTime += System.nanoTime() - start;
for (ChunkedBinaryExtraction extr : extractions) {
numExtrs++;
// run the confidence function
start = System.nanoTime();
double conf = getConf(extr);
confTime += System.nanoTime() - start;
NormalizedBinaryExtraction extrNorm = normalizer
.normalize(extr);
printExtr(extrNorm, conf);
}
if (numSents % messageEvery == 0)
summary();
}
}
private void printExtr(NormalizedBinaryExtraction extr, double conf) {
String arg1 = extr.getArgument1().toString();
String rel = extr.getRelation().toString();
String arg2 = extr.getArgument2().toString();
ChunkedSentence sent = extr.getSentence();
String toks = sent.getTokensAsString();
String pos = sent.getPosTagsAsString();
String chunks = sent.getChunkTagsAsString();
String arg1Norm = extr.getArgument1Norm().toString();
String relNorm = extr.getRelationNorm().toString();
String arg2Norm = extr.getArgument2Norm().toString();
Range arg1Range = extr.getArgument1().getRange();
Range relRange = extr.getRelation().getRange();
Range arg2Range = extr.getArgument2().getRange();
String a1s = String.valueOf(arg1Range.getStart());
String a1e = String.valueOf(arg1Range.getEnd());
String rs = String.valueOf(relRange.getStart());
String re = String.valueOf(relRange.getEnd());
String a2s = String.valueOf(arg2Range.getStart());
String a2e = String.valueOf(arg2Range.getEnd());
String row = Joiner.on("\t").join(
new String[] { currentFile, String.valueOf(numSents), arg1,
rel, arg2, a1s, a1e, rs, re, a2s, a2e,
String.valueOf(conf), toks, pos, chunks, arg1Norm,
relNorm, arg2Norm });
System.out.println(row);
}
The first method is called per sentence and does the extraction. Then it calls the second method to print the tab separated values to the output stream. I guess all you have to do is implement your own version of the second method 'printExtr()'.
So basically what I need to do is:
Read a text file like this:
[Student ID], [Student Name], Asg 1, 10, Asg 2, 10, Midterm, 40, Final, 40
01234567, Timture Choi, 99.5, 97, 100.0, 99.0
02345678, Elaine Tam, 89.5, 88.5, 99.0, 100
and present it like this (with calculations of rank and average):
ID Name Asg 1 Asg 2 Midterm Final Overall Rank
01234567 Timture Choi 99.5 97.0 100.0 99.0 99.3 1
02345678
Elaine Tam 89.5 88.5 99.0 100.0 97.4 2
Average: 94.5 92.75 99.5 99.5 98.3
Using printf() function
now this is what I have done so far:
import java.io.*;
import java.util.Scanner;
class AssignmentGrades {
public static void main(String args[]) throws Exception {
Scanner filename = new Scanner(System.in);
String fn = filename.nextLine(); //scannig the file name
System.out.println("Enter your name of file : ");
FileReader fr = new FileReader(fn+".txt");
BufferedReader br = new BufferedReader (fr);
String list;
while((list = br.readLine()) !=null) {
System.out.println(list);
}
fr.close();
}
}
So I can ask the user for the name of the file, then read it and print.
Now.. I'm stuck. I think I need to probably put it in to array and split?
String firstrow = br.readLine();
String[] firstrow = firstrow.split(", ");
something like that?.. ugh ive been stuck here for more than an hour
I really need help!! I appreciate your attention!! ( I started to learn java this week)
There are two ways for splitting the input line just read from the file
Using String object's split() method which would return an array. Read more about the split here.
StringTokenizer Class - This class can be used to divide the input string into separate tokens based on a set of delimeter. Here is a good tutorial to get started.
You should be able to get more examples using google :)
In case you want to parse integers from String. Check this.
Here I store the columns as an array of Strings and I store the record set as an ArrayList of String arrays. In the while loop if the column set is not initialized yet (first iteration) I initialize it with the split. Otherwise I add the split to the ArrayList. Import java.util.ArrayList.
String[] columns = null;
ArrayList<String[]> values = new ArrayList<String[]>();
String list;
while((list = br.readLine()) !=null) {
if (columns != null) {
columns = list.split(", ");
} else {
values.add(list.split(", "));
}
}
fr.close();