Develop Java App for Reading Inventory File: Total Inventory for Each Product ID

  • Comp Sci
  • Thread starter iamjon.smith
  • Start date
  • Tags
    Java
In summary: Close file output stream }catch (IOException e) { // if there's an IOException, print the error and exit }}}
  • #1
iamjon.smith
117
3
Develop an application that reads a file of inventory information containing product ID and quantity. An example inventory file:

10401 32
10522 25
10401 1
10402 15

The file can contain several entries for the same Product ID. Your application should accumulate the quantities for each Product ID as you read the inventory information from the file. The application should print total inventory for each Product ID.


Subclass:

Code:
package myInventory;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author Jon and Jessica
 */
public class Inventory {

    private int productID;
    private int productQuantity;

     // no-argument constructor calls other constructor with default values
   public Inventory()
   {
      this(  0,0 ); // call two-argument constructor
   } // end no-argument CityRecord constructor

   // initialize a record
   public Inventory( int productID, int productQuantity )
   {
       setProductID(productID);
       setProductQuantity(productQuantity);
   }

    public int getProductID() {
        return productID;
    }

    public void setProductID(int productID) {
        this.productID = productID;
    }

    public int getProductQuantity() {
        return productQuantity;
    }

    public void setProductQuantity(int productQuantity) {
        this.productQuantity = productQuantity;
    }

}

Main class:

Code:
package myInventory;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
import java.io.*;
import java.util.*;
/**
 *
 * @author Jonathan Smith
 */
public class InventoryTest {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
       
       int productID,productQuantity;
        
       Scanner scanner = null;  // scanner to read input
       FileOutputStream invOut; // declare a file output object
       PrintStream p1;  // declare a print stream

       TreeSet< Integer > invTree = new TreeSet< Integer >(); // Treeset to contain product data
       int[] invQuantity = null;   // integer array to hold quantity
       Inventory inventory = new Inventory(); // inventory constructor

       try{
           // Create new file output streams
        invOut = new FileOutputStream("currentInventory.txt", true); // output stream for current inventory with boolean value for appending to file

        // Connect print streams to the output stream
        p1 = new PrintStream( invOut );

	scanner = new Scanner(new File("inventory.txt")).useDelimiter("\t"); // Scanner construct that reads the input file

        while (scanner.hasNextLine())
            { //Checks if there's any more lines

                invTree.add(scanner.nextInt()); // reads to first tab in line, sets the variable
                productQuantity = scanner.nextInt(); // reads to integer, sets the variable
                invQuantity[productQuantity] = productQuantity;  // add product quantity to invQuantity array

                if (productQuantity !=0)
                {
                    productQuantity = productQuantity + scanner.nextInt(); // if product quantity contains value add new value to old value
                }
                else
                {
                    productQuantity = scanner.nextInt();   // else enter value for product quantity
                }

            }
                
            }
                catch (Exception e)
                {
                        System.err.println ("Error writing to file");  // print error to screen
                }
                printTreeSet(invTree);   // call print method to print the inventory tree set
    }

     // This method prints the elements of a given TreeSet object.
    public static void printTreeSet(TreeSet invTree) {
        System.out.print( "Inventory: " + "\n" );

        // Use an Iterator to print each element of the TreeSet.
        Iterator iterator = invTree.iterator();
        while (iterator.hasNext())
            System.out.print( iterator.next() + "\n" );
            System.out.println();
    }
}

I am having a problem getting the values into the array for product quantity, and it only prints out the first element of the tree set. Someone please take a look and see what I am doing wrong.
 
Physics news on Phys.org
  • #2
I don't understand what you're doing in the main class. You declare an Inventory instance, but then you don't use it. I would think that your TreeSet would contain Inventory objects. Instead, it appears that your TreeSet in the main class contains just product IDs, and that you have a separate array for product quantities.

I don't know much about the high-level containers in Java, but I've done a little reading of the docs published by Oracle. The add method on TreeSet returns a boolean, but you aren't using it. If you attempt to add an element that is already present in a TreeSet, add returns false.

Did the instructor give any hints or suggestions for how this should be solved? If you can provide an explanation in words of what you're trying to do, that would be helpful.
 
  • #3
OK, The instructor hasn't really given too much info on how to do this as it is the next to last assignment. We were just told to choose a java collection type to use.

Here is what I am attempting to do:

Read productID from inventory text file

pass first productID (first integer) to Treeset (invTree)

read productQuantity (second integer) to array where first element (0) of the array will match the first element of the treeset.

continue to read in the productID and quantity from the inventory text file. If the productID exists, add the new quantity to the old quantity.

once the end of the inventory file is reached, print out the inventoryID with matching Quantity.

A treeset or treemap is ideal as there will be no duplicate productIDs.

If there is a better way of doing this, I am all ears :)
 
  • #4
Lack of the ability to quickly retrieve the count of a specific product ID is a problem here with TreeSet.

Personally, I would be rather tempted to add it to a HashMap with the product ID as the key and count as the value. But if you expect to print the entries out in product ID order, you might need to look at TreeMap. HashMap will give them to you in a seemingly random order. TreeMap works similarly to HashMap but will keep them in the natural order of the key. Or you can set a comparator.

Let's say I'm using a HashMap<int, int>. You can still iterate through the elements in the HashMap. But this comes to mind:

1. Read next product from list
2. Try and find existing product with same ID in HashMap
3. If ID already in HashMap, get current count and increment by count from file
Otherwise, add new product/count into the HashMap.
4. If not yet done, return to step 1.

Anyways, I suspect you want to use TreeMap. The logic isn't terribly different from HashMap.

In this case, I'd be tempted to not have the Inventory class at all. But as Mark said, I don't know exactly what your teacher wants or expects.
 
  • #5
TreeMap would be the ideal solution as I would like them to appear in a sorted order.

After going back through the class recording, the inventory class is not actually required.

One additional "hint" from the instructor is that the productID could be used as a key.
 
  • #6
Ok, got rid of the Inventory class, Grep was right, it was not necessary.

Also moved from TreeSet to TreeMap

New code:

Code:
package myInventory;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
import java.io.*;
import java.util.*;
/**
 *
 * @author Jonathan Smith
 */
public class InventoryTest {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
       
       int productID,productQuantity;
        
       Scanner scanner = null;  // scanner to read input
       FileOutputStream invOut; // declare a file output object
       PrintStream p1;  // declare a print stream

       TreeMap< Integer, Integer > invTree = new TreeMap< Integer, Integer >(); // Treeset to contain product data
       int[] invQuantity = null;   // integer array to hold quantity
       
       try{
           // Create new file output streams
        invOut = new FileOutputStream("currentInventory.txt", true); // output stream for current inventory with boolean value for appending to file

        // Connect print streams to the output stream
        p1 = new PrintStream( invOut );

	scanner = new Scanner(new File("inventory.txt")).useDelimiter("\t"); // Scanner construct that reads the input file

        while (scanner.hasNextLine())
            { //Checks if there's any more lines

                productID = scanner.nextInt();
                invTree.put(productID, new Integer(scanner.nextInt()));
                productQuantity = scanner.nextInt();
                invTree.put(productQuantity, new Integer(scanner.nextInt()));
                
                if (productQuantity !=0)
                {
                    productQuantity = productQuantity + scanner.nextInt(); // if product quantity contains value add new value to old value
                }
                else
                {
                    productQuantity = scanner.nextInt();   // else enter value for product quantity
                }

            }
                
            }
                catch (Exception e)
                {
                        System.err.println ("Error writing to file");  // print error to screen
                }
                printTreeMap(invTree);   // call print method to print the inventory tree set

    }

     // This method prints the elements of a given TreeSet object.
    public static void printTreeMap(TreeMap invTree) {
        System.out.print( "Inventory: " + "\n" );

        // Use an Iterator to print each element of the TreeSet.
        Iterator iterator = invTree.iterator();
        while (iterator.hasNext())
            System.out.print( iterator.next() + "\n" );
            System.out.println();

    }
}

I am aware that there is a problem with the print method at the end. I know that you can't iterate through the TreeMap in the same manner as the TreeSet, and I will correct that next.

Let me know if anyone knows if I am heading in the right direction.
 
  • #7
Ok, Corrected the print class, and here is the code as it stands now.

Code:
package myInventory;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
import java.io.*;
import java.util.*;
/**
 *
 * @author Jonathan Smith
 */
public class InventoryTest {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
       
       int productID,productQuantity;
        
       Scanner scanner = null;  // scanner to read input
       FileOutputStream invOut; // declare a file output object
       PrintStream p1;  // declare a print stream

       TreeMap< Integer, Integer > invTree = new TreeMap< Integer, Integer >(); // Treeset to contain product data
       int[] invQuantity = null;   // integer array to hold quantity
       
       try{
           // Create new file output streams
        invOut = new FileOutputStream("currentInventory.txt", true); // output stream for current inventory with boolean value for appending to file

        // Connect print streams to the output stream
        p1 = new PrintStream( invOut );

	scanner = new Scanner(new File("inventory.txt")).useDelimiter("\t"); // Scanner construct that reads the input file

        while (scanner.hasNextLine())
            { //Checks if there's any more lines

                productID = scanner.nextInt();
                invTree.put(productID, new Integer(scanner.nextInt()));
                productQuantity = scanner.nextInt();
                invTree.put(productQuantity, new Integer(scanner.nextInt()));
                
                if (productQuantity !=0)
                {
                    productQuantity = productQuantity + scanner.nextInt(); // if product quantity contains value add new value to old value
                }
                else
                {
                    productQuantity = scanner.nextInt();   // else enter value for product quantity
                }

            }
                
            }
                catch (Exception e)
                {
                        System.err.println ("Error writing to file");  // print error to screen
                }
                printTreeMap(invTree);   // call print method to print the inventory tree set

    }

     // This method prints the elements of a given TreeSet object.
    public static void printTreeMap(TreeMap invTree) {
        System.out.print( "Inventory: " + "\n" );

        Object objOne = invTree.get("productID");
        Object objTwo = invTree.get("productQuantity");

        System.out.print(objOne + " " + objTwo);

    }
}

Output:

run:
Error writing to file
Inventory:
null nullBUILD SUCCESSFUL (total time: 0 seconds)
 
  • #8
Ok, I have made it far enough to be completely lost as to what to do next.

Here is the code as I have it now:

Code:
package myInventory;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
import java.io.*;
import java.util.*;
/**
 *
 * @author Jonathan Smith
 */
public class InventoryTest {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
       
       int productID,productQuantity;
        
       Scanner scanner = null;  // scanner to read input
       FileOutputStream invOut; // declare a file output object
       PrintStream p1;  // declare a print stream

       TreeMap< Integer, Integer > invTree = new TreeMap< Integer, Integer >(); // Treeset to contain product data
       int[] invQuantity = null;   // integer array to hold quantity
       
       try{
           // Create new file output streams
        invOut = new FileOutputStream("currentInventory.txt", true); // output stream for current inventory with boolean value for appending to file

        // Connect print streams to the output stream
        p1 = new PrintStream( invOut );

	scanner = new Scanner(new File("inventory.txt")).useDelimiter("\t"); // Scanner construct that reads the input file

        while (scanner.hasNextLine())
            { //Checks if there's any more lines

                productID = scanner.nextInt();
                invTree.put(productID, new Integer(scanner.nextInt()));
                productQuantity = scanner.nextInt();
                invTree.put(productQuantity, new Integer(scanner.nextInt()));

                if(invTree.containsKey(productID))
                {
                    productQuantity = invTree.get(productQuantity) + productQuantity;
                }
                else
                    invTree.put( productID, productQuantity );
            }
                
            }
                catch (Exception e)
                {
                        System.err.println ("Error writing to file");  // print error to screen
                }
                printTreeMap(invTree);   // call print method to print the inventory tree set

    }

     // This method prints the elements of a given TreeSet object.
    public static void printTreeMap(TreeMap invTree) {
        System.out.print( "Inventory: " + "\n" );

        Object objOne = invTree.get("productID");
        Object objTwo = invTree.get("productQuantity");

        System.out.print(objOne + " " + objTwo);

    }
}

Output:
run:
Inventory:
null nullError writing to file
BUILD SUCCESSFUL (total time: 1 second)
 
  • #9
Code:
       int[] invQuantity = null;   // integer array to hold quantity
Don't need that anymore (pretty sure you just haven't gotten around to removing it).

Code:
                productID = scanner.nextInt();
                invTree.put(productID, new Integer(scanner.nextInt()));
                productQuantity = scanner.nextInt();
                invTree.put(productQuantity, new Integer(scanner.nextInt()));
                
                if (productQuantity !=0)
                {
                    productQuantity = productQuantity + scanner.nextInt(); // if product quantity contains value add new value to old value
                }
                else
                {
                    productQuantity = scanner.nextInt();   // else enter value for product quantity
                }
I see some logic problems in here. Check the steps I posted. It should be something like that. You need to read both integers from the file. Before trying to add anything to the TreeSet, you need to see if the product ID is already there. If so, you want to read the quantity from the TreeSet entry, add the new quantity to it, and store it again.

If you didn't find the current ID, then you need to add the new entry. You're going to see some strange entries in the TreeSet as things are written. For example, after already adding an entry to the TreeSet, you add again, but with the quantity as the key. Probably not what you had in mind.

Code:
                catch (Exception e)
                {
                        System.err.println ("Error writing to file");  // print error to screen
                }
                printTreeMap(invTree);   // call print method to print the inventory tree set

    }
Small indentation problem aside, perhaps the Exception isn't from writing to the file. Maybe it failed opening the input file, or nextInt() failed to get an int. You should get different types of exceptions depending on the problem that you can catch to tell you more precisely what went wrong.

Also, I usually print the stack trace of the exception when one occurs so I can see where it failed and so on. So I usually have 'e.printStackTrace()' in there.

Code:
     // This method prints the elements of a given TreeSet object.
    public static void printTreeMap(TreeMap invTree) {
        System.out.print( "Inventory: " + "\n" );

        // Use an Iterator to print each element of the TreeSet.
        Iterator iterator = invTree.iterator();
        while (iterator.hasNext())
            System.out.print( iterator.next() + "\n" );
            System.out.println();

    }
As you say, that won't quite work. Here's a nice clean way to do it:
Code:
for (Map.Entry<Integer,Integer> entry : invTree.entrySet()) {
    System.out.println("key is " + entry.getKey()
                             + " and value is " + entry.getValue());
}
Didn't test the above, but that should work, I think. There's a case I figured it was much easier to just show you. Explaining that clearly without an example might get tricky. If you have trouble understanding that foreach construct or whatever, let us know.
 
  • #10
Yep, just hadn't gotten around to removing that array, it is gone now.

I have tried to go over the steps you placed, and here is what I now have:

Code:
package myInventory;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
import java.io.*;
import java.util.*;
/**
 *
 * @author Jonathan Smith
 */
public class InventoryTest {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
       
       int productID,productQuantity;
        
       Scanner scanner = null;  // scanner to read input
       FileOutputStream invOut; // declare a file output object
       PrintStream p1;  // declare a print stream

       TreeMap< Integer, Integer > invTree = new TreeMap< Integer, Integer >(); // TreeMap to contain product data
              
       try{
           // Create new file output streams
        invOut = new FileOutputStream("currentInventory.txt", true); // output stream for current inventory with boolean value for appending to file

        // Connect print streams to the output stream
        p1 = new PrintStream( invOut );

	scanner = new Scanner(new File("inventory.txt")).useDelimiter("\t"); // Scanner construct that reads the input file

        while (scanner.hasNextLine())
            { //Checks if there's any more lines

                productID = scanner.nextInt();
                productQuantity = scanner.nextInt();
               
                if(invTree.containsKey(productID))
                {
                    invTree.put(productID, productQuantity);
                }
                else
                    productQuantity = invTree.get(productQuantity) + productQuantity;
                    invTree.put(productID, productQuantity);
            }
            p1.print("Current Inventory:" + "\n");
            p1.print(invTree);
            }
                catch (Exception e)
                {
                    e.printStackTrace();
                    System.err.println ("Error writing to file");  // print error to screen
                }

                printTreeMap(invTree);   // call print method to print the inventory tree set

    }

     // This method prints the elements of a given TreeSet object.
    public static void printTreeMap(TreeMap invTree) {
        System.out.print( "Inventory: " + "\n" );

        Object objOne = invTree.get("productID");
        Object objTwo = invTree.get("productQuantity");

        System.out.print(objOne + " " + objTwo + "\n");


    }
}

You notice I added the stackTrace to figure out what the error is from and here is the output:

run:
java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:840)
at java.util.Scanner.next(Scanner.java:1461)
at java.util.Scanner.nextInt(Scanner.java:2091)
at java.util.Scanner.nextInt(Scanner.java:2050)
at myInventory.InventoryTest.main(InventoryTest.java:41)
Error writing to file
Inventory:
null null
BUILD SUCCESSFUL (total time: 0 seconds)

Which is just greek to me. Seems to me as if it is having a problem reading in the information from the text file, but I am not sure. Let me know what else I can do.
 
  • #11
The problem is likely your delimiter. The default delimiter is just whitespace, which is probably what you want anyways. So removing the call to setDelimiter should work as you want.

And that should get you to the next error. :biggrin:

And for that one, I'll point out that invTree.get(productID) will return null if there's no such key in the map. Which would be fine except you have the logic of the if/else block reversed. Also, there seems to be some problems there with curly braces. That else should have curly braces right? As it is, it will only consider the first line after the else as part of the else. Indentation problems make it hard to follow what curly brace goes where.
 
  • #12
It looks like the exception is being thrown at your two nextInt statements. If you have any sort of debugger, that would be the place to look, to see if productID and productQuantity are getting set as a result of those two statements.

Your indentation still makes it hard to follow the logic of your code. The try block and its catch block should be at the same level. Also, the usual practice is to put a try block around a small number of statements. If necessary, you can have several sets of try...catch blocks.
 
  • #13
OK, I removed the delimiter and altered the input file to reflect the change, so now it just uses the default white space delimiter.

Also, I switched around the if/else statement.

I also tried to fix my always horrible indentation, and added in the curly brackets around the else statement.

Here is the new code:

Code:
package myInventory;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
import java.io.*;
import java.util.*;
/**
 *
 * @author Jonathan Smith
 */
public class InventoryTest {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
       
       int productID,productQuantity;
        
       Scanner scanner = null;  // scanner to read input
       FileOutputStream invOut; // declare a file output object
       PrintStream p1;  // declare a print stream

       TreeMap< Integer, Integer > invTree = new TreeMap< Integer, Integer >(); // TreeMap to contain product data
              
       try{
           // Create new file output streams
        invOut = new FileOutputStream("currentInventory.txt", true); // output stream for current inventory with boolean value for appending to file

        // Connect print streams to the output stream
        p1 = new PrintStream( invOut );

	scanner = new Scanner(new File("inventory.txt")); // Scanner construct that reads the input file

        while (scanner.hasNextLine())
            { //Checks if there's any more lines

                productID = scanner.nextInt();
                productQuantity = scanner.nextInt();
               
                if(invTree.containsKey(productID))
                    {                   
                    productQuantity = invTree.get(productQuantity) + productQuantity;
                    invTree.put(productID, productQuantity);
                    }
                else
                    {
                    invTree.put(productID, productQuantity);
                    }
             }
                p1.print("Current Inventory:" + "\n");
                p1.print(invTree);
             }
          catch (Exception e)
            {
                e.printStackTrace();
                System.err.println ("Error writing to file");  // print error to screen
            }

                printTreeMap(invTree);   // call print method to print the inventory tree set

    }

     // This method prints the elements of a given TreeSet object.
    public static void printTreeMap(TreeMap invTree) {
        System.out.print( "Inventory: " + "\n" );

        Object objOne = invTree.get("productID");
        Object objTwo = invTree.get("productQuantity");

        System.out.print(objOne + " " + objTwo + "\n");
    }
}

and here is the output:

java.lang.NullPointerException
Inventory:
at myInventory.InventoryTest.main(InventoryTest.java:45)
Error writing to file
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at java.lang.String.compareTo(String.java:92)
at java.util.TreeMap.getEntry(TreeMap.java:328)
at java.util.TreeMap.get(TreeMap.java:255)
at myInventory.InventoryTest.printTreeMap(InventoryTest.java:70)
at myInventory.InventoryTest.main(InventoryTest.java:62)
Java Result: 1
BUILD SUCCESSFUL (total time: 0 seconds)

Which tells me somewhere instead of an int it is pulling a string value. I am running it in the debugger to try and catch the problem. Meanwhile, take a look and see if you guys have any additional input.
 
  • #14
I think the problem is probably here:
Code:
     // This method prints the elements of a given TreeSet object.
    public static void printTreeMap(TreeMap invTree) {
        System.out.print( "Inventory: " + "\n" );

        Object objOne = invTree.get("productID");
        Object objTwo = invTree.get("productQuantity");

        System.out.print(objOne + " " + objTwo + "\n");
    }
}

Look at the example code I wrote for going through the TreeMap and printing things. I believe the problem is you're passing a String to .get when it's expecting Integer types, since that's what you put in. Look up the entry from the productID's value to get the Entry object. Then get the key and value from that.
 
  • #15
Grep is looking at your printTreeMap method because of stack trace you showed:
java.lang.NullPointerException
Inventory:
at myInventory.InventoryTest.main(InventoryTest.java: 45)
Error writing to file
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at java.lang.String.compareTo(String.java:92)
at java.util.TreeMap.getEntry(TreeMap.java:328)
at java.util.TreeMap.get(TreeMap.java:255)
at myInventory.InventoryTest.printTreeMap(InventoryTe st.java:70)
at myInventory.InventoryTest.main(InventoryTest.java: 62)

Also, I believe you will have trouble printing an Object instance in this line:
Code:
System.out.print(objOne + " " + objTwo + "\n");

For one thing, if an object contains anything that can be printed, you should use objOne.ToString().

More importantly, why are you storing the result of get in an Object? Your TreeMap object is like a dictionary: you have a key (the word you're looking up) that you use to get a value (the definition of the word). In your case the key is the product ID and the value is the product quantity. You use the key to find how many of that product there are.
 
  • #16
Mark44 said:
Also, I believe you will have trouble printing an Object instance in this line:
Code:
System.out.print(objOne + " " + objTwo + "\n");

For one thing, if an object contains anything that can be printed, you should use objOne.ToString().

Just a small comment. The .toString will be called implicitly in those circumstances. There's rarely any need to call .toString explicitly in a print/println. Just to demonstrate:

Code:
class ToStringTest {
    int x = 42;

    public String toString() {
        return "x = " + x;
    }

    public static void main(String args[]) {
        ToStringTest test = new ToStringTest();

        System.out.println("ToStringTest.toString() is " + test);

        Object obj = (Object)test;
        System.out.println("Object.toString() is " + obj);
    }
}

And the output is:

ToStringTest.toString() is x = 42
Object.toString() is x = 42

So polymophism works here, as well. The correct .toString gets called.

However I should note to the OP that there's no need to include '\n' at the end of your print, since you can just use println instead. Not a big thing, but in those cases, you may as well use println.
 
  • #17
Ok, thanks to Mark44 and Grep, I have come a long way. I can now get the display on screen of productID and productQuantity from the TreeMap in a sorted order. The only problem that I am having is when it updates the productQuantity. Instead of adding the new scanned integer, it just doubles the existing value.

I have temporarily disabled writing to the file.

Code:
package myInventory;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
import java.io.*;
import java.util.*;
/**
 *
 * @author Jonathan Smith
 */
public class InventoryTest {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {                    
      
       FileOutputStream invOut; // declare a file output object
       PrintStream p1;  // declare a print stream

       TreeMap< String, Integer > invTree = new TreeMap< String, Integer >(); // TreeMap to contain product data
              
       try{
           // Create new file output streams
        invOut = new FileOutputStream("currentInventory.txt", true); // output stream for current inventory with boolean value for appending to file

        // Connect print streams to the output stream
        p1 = new PrintStream( invOut );

	Scanner scanner = new Scanner(new File("inventory.txt")); // Scanner construct that reads the input file

        while (scanner.hasNextLine())
            { //Checks if there's any more lines

                String productID = scanner.next();
                int productQuantity = scanner.nextInt();
               
                if(invTree.containsKey(productID))
                    {                   
                    invTree.get(productID);
                    invTree.put(productID, productQuantity + productQuantity);
                    }
                else
                    {
                    invTree.put(productID, productQuantity);
                    }
             }
               // p1.print("Current Inventory:" + "\n");
               // p1.print(invTree.values());
             }
          catch (Exception e)
            {
                e.printStackTrace();
                System.err.println ("Error writing to file");  // print error to screen
            }

                printTreeMap(invTree);   // call print method to print the inventory tree set

    }

      // This method prints the elements of a given TreeSet object.
    public static void printTreeMap(TreeMap < String, Integer > invTree) {

        Set< String > keys = invTree.keySet(); // get Keys

        System.out.print( "Inventory: " + "\n" );
        TreeSet < String > showInv= new TreeSet < String > (keys);
        for ( String key : showInv)
                System.out.printf("%-10s%10s\n",key, invTree.get(key));
        
    }

}

output:

run:
Inventory:
10001 6
10101 9
10203 38
10401 2
10402 56
10522 50
11011 77
BUILD SUCCESSFUL (total time: 1 second)

Take a look and help me figure out why it is doubling instead of adding the new if you could, thanks.
 
  • #18
You're quite welcome!

Anyways, I see the problem. It's because you're doubling the value. :biggrin:

Look closely at the following:
Code:
                if(invTree.containsKey(productID))
                    {                   
                    invTree.get(productID);
                    invTree.put(productID, productQuantity + productQuantity);
                    }
                else
...

You did a get on the product ID, but you didn't store the result. Then, you do the put with productQuantity + productQuantity as the new value. Thus, doubling the value you just read from the file and completely ignoring the value already stored in the map.
 
  • #19
Ok GOT IT! First of all, I made a little bit of change to the overall structure. I encapsulated the create part of the TreeMap in its own method. I then just created the TreeMap and called the creation and print methods for the output. I may end up splitting the methods off into their own class just to make the professor happy, but maybe not.

It now updates the treeMap correctly and prints the correct values to the screen.

The only thing I have to do now, is to print it to a file correctly. With the following code:

Code:
package myInventory;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
import java.io.*;
import java.util.*;
/**
 *
 * @author Jonathan Smith
 */
public class InventoryTest {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {  
    
    TreeMap< String, Integer > invTree = new TreeMap< String, Integer >(); // TreeMap to contain product data

    createMap( invTree );
    printTreeMap( invTree );
    
    } // end Main

    // This method creates the tree map from the file using scanner and the TreeMap collection
    private static void createMap( TreeMap < String, Integer > invTree){

       FileOutputStream invOut; // declare a file output object
       PrintStream p1;  // declare a print stream

                    
       try{
           // Create new file output streams
        invOut = new FileOutputStream("currentInventory.txt", true); // output stream for current inventory with boolean value for appending to file

        // Connect print streams to the output stream
        p1 = new PrintStream( invOut );

	Scanner scanner = new Scanner(new File("inventory.txt")); // Scanner construct that reads the input file

        while (scanner.hasNextLine())
            { //Checks if there's any more lines

                // Scan for values
                String productID = scanner.next();
                int productQuantity = scanner.nextInt();
               
                if(invTree.containsKey(productID))
                    {                   
                    int oldStock = invTree.get(productID);
                    invTree.put(productID, oldStock + productQuantity);
                    }
                else
                    {
                    invTree.put(productID, productQuantity);
                    }
             }
               p1.print("Current Inventory:" + "\n");
               p1.print(invTree.values());
             }
          catch (Exception e)
            {
                e.printStackTrace();
                System.err.println ("Error writing to file");  // print error to screen
            }

    }

      // This method prints the elements of a TreeSet Collection created from a previously created TreeMap
    public static void printTreeMap(TreeMap < String, Integer > invTree) {

        Set< String > keys = invTree.keySet(); // get Keys from the TreeMap

        System.out.print( "Inventory: " + "\n" );
        TreeSet < String > showInv= new TreeSet < String > (keys);
        for ( String key : showInv)  // for each key in the TreeSet showInv 
                System.out.printf("%-10s%10s\n",key, invTree.get(key)); // print to screen
        
    }

}

output to screen (correct :)

run:
Inventory:
10001 15
10101 9
10203 38
10401 33
10402 43
10522 50
11011 77
BUILD SUCCESSFUL (total time: 1 second)

However, the output to the file is :

Current Inventory:
[6, 9, 38, 2, 56, 50, 77]Current Inventory:
[3, 9, 38, 1, 28, 25, 77]Current Inventory:
[3, 9, 38, 1, 28, 25, 77]Current Inventory:
[24, 9, 38, 64, 30, 50, 77]Current Inventory:
[15, 9, 38, 33, 43, 50, 77]Current Inventory:
[15, 9, 38, 33, 43, 50, 77]Current Inventory:
[15, 9, 38, 33, 43, 50, 77]

The final Value is Correct, but I want it to mirror the screen output.
 
  • #20
If you want the same as you see printed also written to a file, you can use the exact same logic. But instead of printing to System.out, print it to the file's stream.

You could pass the output stream to the print method you wrote. To write to System.out, pass that. Otherwise, pass p1 or whatever the file's output stream is.

Note that System.out is of type PrintStream, which just happens to be the same type as your p1 stream, so you can add a parameter to that print method of that type. Then, to print to System.out, you could do this:

printTreeMap(invTree, System.out);

or to the file (opened properly and having created the PrintStream called p1, as you've already done):

printTreeMap(invTree, p1);

Anyways, that's what comes to mind as a good way to do it. It reuses the code nicely.
 
  • #21
Grep said:
If you want the same as you see printed also written to a file, you can use the exact same logic. But instead of printing to System.out, print it to the file's stream.

You could pass the output stream to the print method you wrote. To write to System.out, pass that. Otherwise, pass p1 or whatever the file's output stream is.

Note that System.out is of type PrintStream, which just happens to be the same type as your p1 stream, so you can add a parameter to that print method of that type. Then, to print to System.out, you could do this:

printTreeMap(invTree, System.out);

or to the file (opened properly and having created the PrintStream called p1, as you've already done):

printTreeMap(invTree, p1);

Anyways, that's what comes to mind as a good way to do it. It reuses the code nicely.

Ok, to be honest, you lost me with this part.

I have been up for 21 hours, I have to go to work in 3, I am going to go to bed and try this after work. I have just a little bit left. it is due after work, so maybe I can get it to print to the file before it is due.
 
  • #22
iamjon.smith said:
Ok, to be honest, you lost me with this part.

I have been up for 21 hours, I have to go to work in 3, I am going to go to bed and try this after work. I have just a little bit left. it is due after work, so maybe I can get it to print to the file before it is due.

21 hours... Ouch! Well, you've obviously put in good effort, so I will take pity on you and show you what I mean. lol Just make sure you understand what I'm doing and learn from it. If not tonight, then at least tomorrow or so.

First, the print function needs only small changes:

Code:
   public static void printTreeMap(TreeMap < String, Integer > invTree, PrintStream ps) {

        Set< String > keys = invTree.keySet(); // get Keys from the TreeMap

        ps.print( "Inventory: " + "\n" );
        TreeSet < String > showInv= new TreeSet < String > (keys);
        for ( String key : showInv)  // for each key in the TreeSet showInv 
                ps.printf("%-10s%10s\n",key, invTree.get(key)); // print to screen
        
    }

See what I did there? You can pass in the PrintStream object you want to print to. I just added a new parameter for it, and printed to that instead of System.out.

So now, you just need to call it differently from your main (and move the creation of the PrintStream for the file outside the create method, so obviously make sure to remove it from the create method).

Code:
    public static void main(String[] args) {  
    
        TreeMap< String, Integer > invTree = new TreeMap< String, Integer >(); // TreeMap to contain product data
        FileOutputStream invOut; // declare a file output object
        PrintStream p1;  // declare a print stream

        createMap( invTree );
        printTreeMap( invTree, System.out );

        try {
            // Create new file output streams
            invOut = new FileOutputStream("currentInventory.txt", true); // output stream for current inventory with boolean value for appending to file

            // Connect print streams to the output stream
            p1 = new PrintStream( invOut );

            printTreeMap(invTree, p1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    } // end Main

Note that I paid little attention to handling errors nicely, but just dump a stack trace for any exception. Technically, I should be looking for things like FileNotFoundException and such, and giving an error that says exactly what went wrong, and aborting the program or handling it some other more graceful way. But that should work. I didn't test it, but it looks good to me, and any mistakes should be small.

So just do us proud and make sure you fully understand what I did. You'd probably have figured it out from my description if you weren't sleep deprived.
 

FAQ: Develop Java App for Reading Inventory File: Total Inventory for Each Product ID

What is a Java app?

A Java app is a software program written in the Java programming language that can run on any platform that has a Java Virtual Machine (JVM) installed. It is used to perform specific tasks, such as reading and manipulating data.

What is an inventory file?

An inventory file is a document that contains a list of products and their corresponding information, such as product ID, name, quantity, and price. It is used to keep track of the available items in a store or warehouse.

How do I develop a Java app for reading an inventory file?

To develop a Java app for reading an inventory file, you will need to have a good understanding of the Java programming language and file handling concepts. You will also need to use Java libraries, such as File and Scanner, to read the data from the inventory file and manipulate it accordingly.

How can I calculate the total inventory for each product ID?

To calculate the total inventory for each product ID, you will need to read the data from the inventory file and store it in a data structure, such as a HashMap or ArrayList. Then, you can use a loop to iterate through the data and use conditional statements to calculate the total inventory for each product ID.

Can I customize the Java app to fit my specific needs?

Yes, you can customize the Java app to fit your specific needs. You can add more functionality, such as sorting the inventory data, generating reports, or exporting the data to other formats. You can also modify the user interface to make it more user-friendly. However, this may require a good understanding of Java programming and some additional coding.

Similar threads

Replies
1
Views
3K
Replies
1
Views
1K
Replies
6
Views
3K
Replies
10
Views
11K
Replies
31
Views
11K
Replies
2
Views
3K
Replies
4
Views
3K
Replies
1
Views
4K
Replies
1
Views
3K
Back
Top