Retrieving Unknown Value using Jsoup - java

I'm attempting to pull the 'Total Cash Flow From Operating Activities' figure from Yahoo Finance. The variable "s" can be any symbol in the SP500. For the most part, the desired output occurs. However, in some cases, like for AAPL, I can't figure out what it's printing or where it came from.
If "s" is A, the output is 711000000. Correct.
If "s" is AA, the output is 1674000000. Correct.
However, if "s" is AAPL, the output is -416542144. No clue where that comes from.
public class CashFlowStatement {
String cashFromOperatingActivities = "Total Cash Flow From Operating Activities";
public CashFlowStatement(String s) {
String cashFlowStatementURL = ("https://finance.yahoo.com/q/cf?s="+s+"+Cash+Flow&annual");
String cashFlowStatementTableName = "table.yfnc_tabledata1";
boolean foundLine = false;
String line;
int line2;
try {
Document doc = Jsoup.connect(cashFlowStatementURL).get();
for (Element table : doc.select(cashFlowStatementTableName)) {
for (Element row : table.select("tr")) {
if(foundLine == false) {
Elements tds = row.select("td");
for( int j = 0; j < tds.size() - 1; j++) {
if(tds.get(j).text().equals(cashFromOperatingActivities)) {
line = tds.get(j+1).text().replaceAll(",","");
line = line.substring(0,(line.length())-2);
line2 = Integer.parseInt(line)*1000;
System.out.println(line2);
foundLine = true;
}
}
}
}
}
}
catch (IOException ex) {
ex.printStackTrace();
}
catch (NumberFormatException ex) {
ex.printStackTrace();
}
}
}

You have an OVERFLOW! The value from the table is 59,713,000. When you multiply it by 1000 - line2 = Integer.parseInt(line)*1000; you get a number which is greater than MAXINT, thus the negative value. Try use long instead int for line2.

Related

Unable to write values into excel using multiple workbook.write methods

The below code is working without any runtime error if I call the owb.write(fileOut) and fileOut.close() method only once at at the ending (commented as write and close positioning) but the problem here is that the first value to be set when k=1, is not being printed in the workbook. It works fine when the iteration is in other columns and k=1.Only the first iteration is not being printed. Rest of the values are being set correctly.
I tried using multiple workbook.write() method. If you look at the below code, commented as [1], I had to invoke owb.write(fileOut) separately in the if condition(commented as if condition[1]) and else condition(commented as else condition [2]) because as I said, first value was not getting set in the workbook. I am getting the following runtime error while trying to execute the code in this scenario: Fail to save: an error occurs while saving the package : The part /docProps/app.xml fail to be saved in the stream with marshaller org.apache.poi.openxml4j.opc.internal.marshallers.DefaultMarshaller#3740f768
for(int i=0;i<noOfCols1;i++)
{
for(int j=1;j<=noOfRows1;j++)
{
value1 = formatter.formatCellValue(sheet1.getRow(j).getCell(i));
for(int m=1;m<=noOfRows2;m++)
{
value2 = formatter.formatCellValue(sheet2.getRow(m).getCell(i));
value1= value1.trim();
value2=value2.trim();
int value2Position = sheet2.getRow(m).getCell(i).getRowIndex();
if(!positions.contains(value2Position))
{
if(value1.contentEquals(value2))
{
positions.add(value2Position);
matched = true;
}
else{
matched = false;
}
}
if(matched==true)
{
break;
}
}
if(matched == false)
{
int k=1;
if(cFilledPositions.isEmpty()) //If condition[i]
{
rowHead = sheet.createRow((short)k);
rowHead.createCell(i).setCellValue(value1);
owb.write(fileOut); //[1]
}
else //else condition [1]
{
int l = cFilledPositions.size()-1;
k = cFilledPositions.get(l)+1;
rowHead = sheet.createRow((short)k);
rowHead.createCell(i).setCellValue(value1);
owb.write(fileOut);
}
cFilledPositions.add(k);
}
matched = false;
}
cFilledPositions.clear();
positions.clear();
}
//write and close positioning
fileOut.close();
I tried debugging and found that the createRow() method deletes the values previously created if called again on the same row.
To elaborate this, suppose the sheet.createRow() sets the value of a cell in the first iteration, and when it finishes its iteration in the j for loop, the cFilledPositions list is cleared and while it comes back after going to the main loop, 'cFilledPositionswill be empty and the integerkwill again be initialized to1. This is whencreateRow(k)` which is 1 is called again. This would flush out the previously existing values in the 1st row. I am trying to figure out a work around for this and will edit my answer with the solution if I my code works.
Below was the work around. I checked if the row is empty. The createRow function is called only when the row is empty. I have added the comments for the new code.
for(int i=0;i<noOfCols1;i++)
{
for(int j=1;j<=noOfRows1;j++)
{
value1 = formatter.formatCellValue(sheet1.getRow(j).getCell(i));
for(int m=1;m<=noOfRows2;m++)
{
value2 = formatter.formatCellValue(sheet2.getRow(m).getCell(i));
value1= value1.trim();
value2=value2.trim();
int value2Position = sheet2.getRow(m).getCell(i).getRowIndex();
if(!positions.contains(value2Position))
{
if(value1.contentEquals(value2))
{
positions.add(value2Position);
matched = true;
}
else{
matched = false;
}
}
if(matched==true)
{
break;
}
}
if(matched == false)
{
int k=1;
if(cFilledPositions.isEmpty())
{
try{
isEmpty = checkIfRowIsEmpty(sheet,k,formatter);
if(isEmpty)
{
rowHead = sheet.createRow(k);
}
rowHead.createCell(i).setCellValue(value1);
}
catch (Exception e){
try{
rowHead = sheet.createRow(k);
rowHead.createCell(i).setCellValue(value1);
}
catch (Exception e1){
}
}
}
else
{
int l = cFilledPositions.size()-1;
k = cFilledPositions.get(l)+1;
try{
isEmpty = checkIfRowIsEmpty(sheet,k,formatter);
if(isEmpty)
{
rowHead = sheet.createRow(k);
}
rowHead.createCell(i).setCellValue(value1);
}
catch (Exception e)
{
try{
rowHead = sheet.createRow(k);
rowHead.createCell(i).setCellValue(value1);
}
catch (Exception e1){
}
}
}
cFilledPositions.add(k);
}
matched = false;
}
cFilledPositions.clear();
positions.clear();
}

Alternate for multiple try catch to handle the exception

I am trying to read a CSV file with 20 columns which may or may not contain value but the problem is that I have to create 20 try catch in order to maintain the code flow in control manner. Like
String a = ""; loop
try{
a = list.get(0); // converted the csv to list of list and iterated in
}catch(NoSuchElementException e){}
and same for every other variable.The reason I have seperate try catch because In the below code
String a = "";
String b = "";
try{
a = list.get(0);
b = list.get(1);
}catch(NoSuchElementException e){}
If first line of try gave exception the second line will not execute.
So is there any alternate to these n number of try catch situation?
Thanks
You could create a helper method:
private String getField(List<String> list, int n) {
try {
return list.get(n);
} catch (NoSuchElementException e) {
return "";
}
}
String a = getField(list, 0);
String b = getField(list, 1);
EDIT:
Typically you wouldn't rely on exceptions if you do not have sufficient fields, the following achieves the same thing but subjectively feels cleaner:
private String getField(List<String> list, int n) {
if (n < list.size()) {
return list.get(n);
}
return "";
}

`NullPointerException` thrown while searching text file [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
First, I keep getting a NullPointerException on the line I put in ** below.
Second, my program is giving the wrong output (I somehow got it to work but then it went back to error). It must be a logic error. I have a file directory.txt of 11 lines, each with a name on it. When I run my program to try to find a certain name, it only finds the first name on the first line and everything else, it can't find. How can I fix these 2 errors?
I have 2 classes. This is the first class Directory:
import java.util.*;
import java.io.*;
public class Directory {
//public static void main(String[] args) {
final int maxDirectorySize = 1024;
String directory[] = new String[maxDirectorySize];
int directorySize = 0;
File directoryFile = null;
Scanner directoryDataIn = null;
public Directory(String directoryFileName) {
directoryFile = new File(directoryFileName);
try {
directoryDataIn = new Scanner(directoryFile);
}
catch (FileNotFoundException e) {
System.out.println("File is not found, exiting!" + directoryFileName);
System.exit(0);
}
while (directoryDataIn.hasNext()) {
directory[directorySize++] = directoryDataIn.nextLine();
}
}
public boolean inDirectory(String name) {
boolean inDir = true;
for (int i = 0; i < directory.length; i++) {
**if (directory[i].equalsIgnoreCase(name))**
inDir = true;
else
inDir = false;
}
return inDir;
}
public boolean add(String name) {
if (directory.length == 1024)
return false;
for (int i = 0; i < directory.length; i++) {
if (directory[i].equalsIgnoreCase(name))
return false;
else
directory[directorySize++] = name;
return true;
}
return false;
}
public boolean delete(String name) {
for (int i = 0; i < directory.length; i++) {
if (directory[i].equalsIgnoreCase(name)) {
directory[i] = null;
return true;
}
else
return false;
}
return false;
}
public void closeDirectory() {
directoryDataIn.close();
PrintStream directoryDataOut = null;
try {
directoryDataOut = new PrintStream(directoryFile);
}
catch (FileNotFoundException e) {
System.out.printf("File %s not found, exiting!", directoryFile);
System.exit(0);
}
String originalDirectory[] = {"Mike","Jim","Barry","Cristian","Vincent","Chengjun","susan","ng","serena"};
if (originalDirectory == directory)
System.exit(0);
else
for (int i = 0; i < directorySize; i++)
directoryDataOut.println(directory[i]);
directoryDataOut.close();
}
}
AND this is my second class which I'm trying to run but I keep getting exception main thread NullPointerException.
import java.io.*;
import java.util.*;
public class DirectoryWithObjectDesign {
public static void main(String[] args) throws IOException {
String directoryDataFile = "Directory.txt";
Directory d = new Directory(directoryDataFile);
Scanner stdin = new Scanner(System.in);
System.out.println("Directory Server is Ready!");
System.out.println("Format: command name");
System.out.println("Enter ^Z to end");
while (stdin.hasNext()) {
String command = stdin.next();
String name = stdin.next();
if (command.equalsIgnoreCase("find")) {
if (d.inDirectory(name))
System.out.println(name + " is in the directory");
else
System.out.println(name + " is NOT in the directory");
}
else if (command.equalsIgnoreCase("add")) {
if (d.add(name))
System.out.println(name + " added");
else
System.out.println(name + " cannot add! " + "no more space or already in directory");
}
else if (command.equalsIgnoreCase("delete")) {
if (d.delete(name))
System.out.println(name + " deleted");
else
System.out.println(name + " NOT in directory");
}
else {
System.out.println("bad command, try again");
}
}
}
}
This code:
while (directoryDataIn.hasNext()) {
directory[directorySize++] = directoryDataIn.nextLine();
}
will only fill up as much of directory as there are lines in the input file (11 according to your question).
This code:
for (int i = 0; i < directory.length; i++) {
**if (directory[i].equalsIgnoreCase(name))**
will loop over every entry in directory, up to its length (1024).
Since 1013 of those entries are null, trying to run equalsIgnoreCase() on them will result in a NPE.
Edit
You can solve this one of several ways. For instance, you could
keep track of the number of lines you read, and only read up to that point
check each entry to see if it is null before evaluating it
use a dynamically sized data structure instead of an array, such as ArrayList
perform the check on the known value (e.g. if (name.equalsIgnoreCase(directory[i])))
etc.
Change
for (int i = 0; i < directory.length; i++) {
To
for (int i = 0; i < directorySize; i++ ){
directorySize is already Keeping track of the number of entries so any array entries above that will be null. Therefore trying to call equalsIgnoreCase() on them will get a NPE.
Actually this looks like a prime use for ArrayList rather than array. The list will expand as you need it and List.size() will give you the correct length.

Exception organization assistance?

I had some success with this site, and I hope I find more excellent programmers to assist me.
So I am at my wit's end with this code. I am very new to programming, especially exceptions. I have looked very hard through my course material and sought help, but I have been quite unsuccessful. I am trying to create an improved parser that will override another parser. It reads a .txt file with student information of it including an ID, a name, a grade, and an optional email address and optional comment as tokens in a String separated by commas. The override checks for errors in each token and throws an exception called ParserException. The exception will check the code and then return an error message if the error is unfixable.
For example, if a student puts in an AB for the grade, the exception will flag and check if the input is a valid grade (which it is) and then return, if it is not, then it will throw a ParserException, in this case
throw new ParserException(ParserException.GRADE_INVALID_GRADE,lineIndex);
This shows that the does not work and sends out a message GRADE_INVALID on the line indexLine
I have a list of what I need to have as an output:
Any violation of the file format specified in the Input File Format Description section above should result in an ParcerException with an appropriate message
Duplicate IDs are not allowed
Grade values must be a float (92.0) or a letter grade and not an integer
I have all the code to correct and check for errors, but I cannot figure out how to get the try-catch to work. Here's is the override code:
#Override
public ParserResult parseLine(int lineIndex) {
String[] tokens = lines.get(lineIndex).split(",");
ArrayList<Integer> idList = new ArrayList<Integer>();
Integer studentId;
String name;
String grade;
String email;
String comments;
boolean isFloat;
float gradeFinal;
String editName;
studentId = new Integer(tokens[0]);
ParserResult result;
try{
return super.parseLine(lineIndex);
}
catch(ParserException e){
// Check reasonable number of tokens
if(tokens.length >= 3 && tokens.length <= 5){
name = tokens[1];
grade = tokens[2];
// Check the student ID
if(idList.contains(studentId)){
throw new ParserException(ParserException.DUPLICATE_ID, lineIndex);
}else{
idList.add(studentId);
}
// Check the grade
if(grade.trim().equalsIgnoreCase("A")){
gradeFinal = gradeA;
}else if(grade.trim().equalsIgnoreCase("AB")){
gradeFinal = gradeAB;
}else if(grade.trim().equalsIgnoreCase("B")){
gradeFinal = gradeB;
}else if(grade.trim().equalsIgnoreCase("BC")){
gradeFinal = gradeBC;
}else if(grade.trim().equalsIgnoreCase("C")){
gradeFinal = gradeC;
}else if(grade.trim().equalsIgnoreCase("CD")){
gradeFinal = gradeCD;
}else if(grade.trim().equalsIgnoreCase("D")){
gradeFinal = gradeD;
}else if(grade.trim().equalsIgnoreCase("F")){
gradeFinal = gradeF;
}else{
try{
Integer.parseInt(grade);
isFloat = false;
}
catch(Exception fl) {
isFloat = true;
}
if(isFloat){
if((Float.parseFloat(grade) < 100f) && (Float.parseFloat(grade) >= 0f)){
gradeFinal = Float.parseFloat(grade);
}else{
throw new ParserException(ParserException.GRADE_INVALID_GRADE,lineIndex);
}
}else{
throw new ParserException(ParserException.GRADE_INTEGER_VALUE,lineIndex);
}
}
// Check the name
if(name.split(" ").length > 3){
throw new ParserException(ParserException.UNKNOWN, lineIndex);
}else{
editName = name.trim().split(" ")[0];
}
result = new ParserResult(studentId, editName, gradeFinal);
// Checks the email
if(tokens.length >= 4){
email = tokens[3];
// Check for at sign
if(!email.contains("#")){
throw new ParserException(ParserException.UNKNOWN, lineIndex);
}
int count = 0;
// Counts number of # symbols
for(int i=0; i<email.length(); i++){
if(email.indexOf(i) == '#'){
count++;
}
}
if(count > 1){
throw new ParserException(ParserException.EMAIL_MULTIPLE_AT,lineIndex);
}
if(email.split(".").length == 2){
if(!(email.trim().split(".")[1].contains(".edu")) && !(email.trim().split(".")[1].contains(".com"))){
throw new ParserException(ParserException.EMAIL_NOT_EDU_OR_COM,lineIndex);
}else{
result.setEmail(email);
}
}
// Checks if email contains .com or .edu
// Checks the comments
if(tokens.length == 5){
comments = tokens[4];
result.setComment(comments);
}
}
return result;
}
}
// TODO Call Parser's parseLine() here to attempt to parse, catch any exceptions
return null;
}
The original parseLine that is overridden, but still used is:
public ParserResult parseLine(int lineIndex) {
String[] tokens = lines.get(lineIndex).split(",");
ParserResult result = new ParserResult(Integer.parseInt(tokens[0]),
tokens[1], Float.parseFloat(tokens[2]));
result.setEmail(tokens[3]);
return result;
}
Here is the main() file:
public static void main(String[] args){
// TODO Change the line below to use ImprovedParser
Parser parser = null;
try {
parser = new ImprovedParser(args[0]);
} catch (FileNotFoundException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
System.exit(-1);
}
List<ParserResult> results = parser.parse();
int count = results.size();
double sum = 0.0;
for (ParserResult result : results) {
sum += result.getGrade();
}
System.out.println("Number of valid input lines: " + results.size());
System.out.println("Number of invalid input lines: "
+ (parser.getLineCount() - results.size()));
System.out.println("Average grade: " + sum / count);
for (ParserResult result : results) {
System.out.println(result);
}
}
Lastly, here is the .txt file that is being read:
# student_id,name,grade,email
1234,Bob,92.0,bob#test.edu
4321,Alice,95.0,alice#test.edu
1111,Eve,80.0,eve#test.edu
1121,Barry,85.0,barrytest.edu
1131,Harry,86.0,h#rry#test.edu
1121,Larry,87.0,larry#test.edu
1141,Jim Song,88.0,jim#song.edu
1151,Jerry,77.0,jerry#test.net
1161,James,65.0,james#test.com
The last six inputs should cause exceptions, but I can't figure out how to organize it to work. The code ignores the line with # symbol.
Here is a sample successful output:
Number of valid input lines: 3
Number of invalid input lines: 0
Average grade: 89.0
1234, 92.0, Bob, bob#test.edu,
4321, 95.0, Alice, alice#test.edu,
1111, 80.0, Eve, eve#test.edu,
The major changes should be in the orverride method
Please help if you can, I sit at my desk still pondering possibilities, and your help will be most-appreciated.
Assuming ParseException has an error field being an int and someMethod() that throws ParseException:
try {
someMethod();
} catch (final ParseExeption ex) {
if (ex.getError() == ParseException.SOME_ERROR) {
// do something
} else if (ex.getError() == ParseException.OTHER_ERROR) {
// do something else
}
}
Note that it's usually better to use specific exceptions for specific error, something like SomeErrorParseException, OtherErrorParseException, ... (those can extends ParseException if you want) and try-catch like this:
try {
someMethod();
} catch (final SomeErrorParseException ex) {
// do something
} catch (final OtherErrorParseException ex) {
// do something else
}
Some reading: http://docs.oracle.com/javase/tutorial/essential/exceptions/index.html
It seems that there is no code to actually cause the catch clause in the first place. Try adding a throw new ParserException(STUFF_HERE); when an error has been detected while reading the file.

Converting Java code into Groovy

I am trying to convert a Java function into equivalent Groovy code, but I am not able to find anything which does && operation in loop. Can anyone guide me through..
So far this is what I got
public List getAlert(def searchParameters, def numOfResult) throws UnsupportedEncodingException
{
List respList=null
respList = new ArrayList()
String[] searchStrings = searchParameters.split(",")
try
{
for(strIndex in searchStrings)
{
IQueryResult result = search(searchStrings[strIndex])
if(result!=null)
{
def count = 0
/*The below line gives me error*/
for(it in result.document && count < numOfResult)
{
}
}
}
}
catch(Exception e)
{
e.printStackTrace()
}
}
My Java code
public List getAlert(String searchParameters, int numOfResult) throws UnsupportedEncodingException
{
List respList = null
respList = new ArrayList()
String[] searchStrings = searchParameters.split(",")
try {
for (int strIndex = 0; strIndex < searchStrings.length; strIndex++) {
IQueryResult result = search(searchStrings[strIndex])
if (result != null) {
ListIterator it = result.documents()
int count = 0
while ((it.hasNext()) && (count < numOfResult)) {
IDocumentSummary summary = (IDocumentSummary)it.next()
if (summary != null) {
String docid = summary.getSummaryField("infadocid").getStringValue()
int index = docid.indexOf("#")
docid = docid.substring(index + 1)
String url = summary.getSummaryField("url").getStringValue()
int i = url.indexOf("/", 8)
String endURL = url.substring(i + 1, url.length())
String body = summary.getSummaryField("infadocumenttitle").getStringValue()
String frontURL = produrl + endURL
String strURL
strURL = frontURL
strURL = body
String strDocId
strDocId = frontURL
strDocId = docid
count++
}
}
}
result = null
}
} catch (Exception e) {
e.printStackTrace()
return respList
}
return respList
}
It seems to me like
def summary = result.documents.first()
if (summary) {
String docid = summary.getSummaryField("infadocid").getStringValue()
...
strDocId = docid
}
is all you really need, because the for loop actually doesn't make much sense when all you want is to process the first record.
If there is a possibility that result.documents contains nulls, then replace first() with find()
Edit: To process more than one result:
def summaries = result.documents.take(numOfResult)
// above code assumes result.documents contains no nulls; otherwise:
// def count=0
// def summaries = result.documents.findAll { it && count++<numOfResult }
summaries.each { summary ->
String docid = summary.getSummaryField("infadocid").getStringValue()
...
strDocId = docid
}
In idiomatic Groovy code, many loops are replace by iterating methods like each()
You know the while statement also exists in Groovy ?
As a consequence, there is no reason to transform it into a for loop.
/*The below line gives me error*/
for(it in result.document && count < 1)
{
}
This line is giving you an error, because result.document will try to call result.getDocument() which doesn't exist.
Also, you should avoid using it as a variable name in Groovy, because within the scope of a closure it is the default name of the first closure parameter.
I haven't looked at the code thoroughly (or as the kids say, "tl;dr"), but I suspect if you just rename the file from .java to .groovy, it will probably work.

Categories

Resources