Reading from a text file as an arraylist/hashmap - java

Okay so here's an explanation of what I have to write:
getBreadInfo - reads bread.txt into an array list (containing bread
name, $, and price) and then assigns to an array breadInfo[], then
return this array for SandwichApp to display bread menu.
getBread - is similar to getBreadInfo, except it only contains the
bread name, and return another array bread[] for SandwichApp to figure
out which bread the user selected because user type in a number
associate with the bread (index+1), rather than bread name.
getMapBreadPrice - is similar to the above two, except it returns a
hash map containing pair values for bread name (key) and price (value)
for SandwichApp to figure out what is the price for the bread user
selected.
This is what I have written. Just wondering if this is correct or not?
public class SandwichDB {
private ArrayList<String> breadsList = null;
public String[] getBreadInfo()
{
breadsList = new ArrayList<>();
try (BufferedReader in =
new BufferedReader(
new FileReader("bread.txt")))
{
String line = in.readLine();
while (line != null)
{
String[] elems = line.split("~");
breadsList.add(elems[0]+ " $" + elems[1]);
}
}
catch(IOException e)
{
System.out.println(e);
return null;
}
String[] breadInfo = breadsList.toArray(new String[]{});
return breadInfo;
}
public String[] getBread()
{
breadsList = new ArrayList<>();
try (BufferedReader in =
new BufferedReader(
new FileReader("bread.txt")))
{
String line = in.readLine();
while (line != null)
{
String[] elems = line.split("~");
breadsList.add(elems[0]);
}
}
catch(IOException e)
{
System.out.println(e);
return null;
}
String[] bread = breadsList.toArray(new String[]{});
return bread;
}
public HashMap<String, String> getMapBreadPrice()
{
HashMap<String, String> mapBreadPrice = new HashMap<>();
String line, elems[];
try
{
FileReader fr = new FileReader("bread.txt");
BufferedReader br = new BufferedReader(fr);
while ((line=br.readLine()) != null)
{
elems = line.split("~");
mapBreadPrice.put(elems[0], elems[1]);
}
}
catch(IOException e)
{
System.out.println(e);
return null;
}
return mapBreadPrice;
}
}

The first readLine stands before the while and hence is not repeated. Hence the while does not end.
for (;;) {
String line = in.readLine();
if (line == null) {
break;
}

It seems like you're reading the same file 3 times in order to build 3 structures. You should build your data structures with one read of the file.

Related

Returning Strings from a file between 2 specified strings in java

I've been searching the web and I can't seem to find a working solution.
I have a file containing theses lines:
Room 1
Coffee
Iron
Microwave
Room_end
Room 2
Coffee
Iron
Room_end
I want to print all Strings between Room 1 and Room_end. I want my code to start when it find Room 1, print line after Room 1 and stop when it get to the first Room_end it find.
private static String LoadRoom(String fileName) {
List<String> result = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
result = reader.lines()
.dropWhile(line -> !line.equals("Room 1"))
.skip(1)
.takeWhile(line -> !line.equals("Room_end"))
.collect(Collectors.toList());
} catch (IOException ie) {
System.out.println("Unable to create " + fileName + ": " + ie.getMessage());
ie.printStackTrace();
}
for (int i = 0; i < result.size(); i++) {
System.out.println(result.get(i).getname());//error on getname because it cant work with Strings
}
}
class Model {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I am able to get a method to print all Strings of the file but not specific range of Strings. I also tried to work with Stream. My code feel quite messy, but I've been working on it for a while an it seems it only get messier.
I think there is a problem if you want to use lambda expression here:
lambda expressions are functional programming, and functional programming requires immutability, that means there should not be state related issue, you can call the function and give it same parameters and the result always will be the same, but in your case, there should be a state indicating whether you should print the line or not.
can you try this solution? I write it in python, but mainly it is just about a variable should_print that located outside of the scope
should_print = False
result = reader.lines()
for line in result:
if line == "Room end":
break
if should_print:
print(line)
if line == "Room 1":
should_print = True
keep a boolean value outside of the iteration, and check/update the value in each iteration
public static Map<String, List<String>> getRooms(String path) throws IOException {
Map<String, List<String>> result = new HashMap<>();
try (Scanner sc = new Scanner(new File(path))) {
sc.useDelimiter("(?=Room \\d+)|Room_end");
while (sc.hasNext()) {
Scanner lines = new Scanner(sc.next());
String room = lines.nextLine().trim();
List<String> roomFeatures = new ArrayList<>();
while (lines.hasNextLine()) {
roomFeatures.add(lines.nextLine());
}
if (room.length() > 0) {
result.put(room, roomFeatures);
}
}
}
return result;
}
is one way of doing it for your 'rooms file' though it should really be made more OO by making a Room bean to hold the data. Output with your file: {Room 2=[Coffee, Iron ], Room 1=[Coffee, Iron, Microwave]}
Switched my code and used this:
private static String loadRoom(String fileName) {
BufferedReader reader = null;
StringBuilder stringBuilder = new StringBuilder();
try {
reader = new BufferedReader(new FileReader(fileName));
String line = null; //we start with empty info
String ls = System.getProperty("line.separator"); //make a new line
while ((line = reader.readLine()) != null) { //consider if the line is empty or not
if (line.equals("Room 1")) { //condition start on the first line being "Room 1"
line = reader.readLine(); // read the next line, "Room 1" not added to stringBuilder
while (!line.equals("Room_end")) { //check if line String is "Room_end"
stringBuilder.append(line);//add line to stringBuilder
stringBuilder.append(ls);//Change Line in stringBuilder
line = reader.readLine();// read next line
}
}
}
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return stringBuilder.toString();
}
Here's a solution that uses a scanner and a flag. You may choose to break the loop when it reads "Room_end"
import java.util.Scanner;
import java.io.*;
public class Main{
private static String loadRoom(String fileName) throws IOException {
Scanner s = new Scanner(new File(fileName));
StringBuilder sb = new StringBuilder();
boolean print = false;
while(s.hasNextLine()){
String line = s.nextLine();
if (line.equals("Room 1")) print = true;
else if (line.equals("Room_end")) print = false;
else if (print) sb.append(line).append("\n");
}
return sb.toString();
}
public static void main(String[] args) {
try {
String content = loadRoom("content.txt");
System.out.println(content);
}catch(IOException e){
System.out.println(e.getMessage());
}
}
}

How to read a file into a hashmap that has a list as the value?

I have an assignment for my data structures class where we are required to store different subjects as the keys and teachers as the data using a built in data structure using map however its not possible to have duplicate keys so I have to store the values as a list. The data has to be read as a file. At first I mistakenly did the assignment by reading in the file and storing the students as keys but am unsure how i would do it in this case. Here is the function i used to read the file into a hashmap:
public static Map<String, String> getteachers(){
Map<String, String> teachers = new HashMap<String, String>();
BufferedReader buffer = null;
try{
File file = new File(filePath1);
buffer = new BufferedReader( new FileReader(file) );
String line = null;
while ( (line = buffer.readLine()) != null ){
String[] parts = line.split(", ");
String teacher = parts[0].trim();
String subject = parts[1].trim();
if( !subject.equals("") && !teacher.equals("") )
teachers.put(teacher, subject);
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(buffer != null){
try {
buffer.close();
}catch(Exception e){};
}
}
return teachers;
}
public static Map<String, List<String>> getTeachers(String filePath1) {
Map<String, List<String>> teachers = new HashMap<>();
BufferedReader buffer = null;
try {
File file = new File(filePath1);
buffer = new BufferedReader(new FileReader(file));
String line = null;
while ((line = buffer.readLine()) != null) {
String[] parts = line.split(", ");
String teacher = parts[0].trim();
String subject = parts[1].trim();
if (!subject.equals("") && !teacher.equals("")) {
if (!teachers.containsKey(teacher)) {
List<String> list = new ArrayList<>();
list.add(subject);
teachers.put(teacher, list);
} else {
teachers.get(teacher).add(subject);
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (buffer != null) {
try {
buffer.close();
} catch (Exception e) {
}
}
}
return teachers;
}

Press any key with BufferedReader

I created a java file called Product.java. I also created a text file called Items.txt. Basically when the user enter the word using sequential search to search the data what they are looking from Items.txt. My main problem is when I enter 3 to display all the records or enter x to exit the program, it keeps on looping. But I don't how to resolve this problem. Can anyone solved this for me?
Items.txt
1000|Cream of Wheat|Normal Size|Breakfast|NTUC|5|3.00
1001|Ayam Brand|Small Size|Canned|NTUC|4|4.00
Product.java
import java.io.*;
import java.util.*;
public class Product {
public static void main(String[] args) {
ArrayList<Item> prdct = new ArrayList<Item>();
String inFile = "items.txt";
String line = "";
FileReader fr = null;
BufferedReader br = null;
StringTokenizer tokenizer;
int quantity;
String id, brandname, desc, category, supplier;
float price;
try{
fr = new FileReader(inFile);
br = new BufferedReader(fr);
line = br.readLine();
while(line!=null)
{
tokenizer = new StringTokenizer(line,"|");
id = tokenizer.nextToken();
brandname = tokenizer.nextToken();
desc = tokenizer.nextToken();
category = tokenizer.nextToken();
supplier = tokenizer.nextToken();
quantity = Integer.parseInt(tokenizer.nextToken());
price = Float.parseFloat(tokenizer.nextToken());
Item itm = new Item(id,brandname,desc,category,supplier,quantity,price);
prdct.add(itm);
line = br.readLine();
}
br.close();
}
catch(FileNotFoundException e){
System.out.println("The file " + inFile + " was not found.");
}
catch(IOException e){
System.out.println("Reading error!");
}
finally
{
if (fr!=null){
try
{
fr.close();
}
catch(IOException e)
{
System.out.println("Error closing file!");
}
}
}
String INPUT_PROMPT = "\nPlease enter 3 to display all records, 4 to insert record, 5 to remove old records " + "or enter 'x' to quit.";
System.out.println(INPUT_PROMPT);
try
{
BufferedReader reader = new BufferedReader
(new InputStreamReader (System.in));
line = reader.readLine();
while(reader != null)
{
for(int i=0; i<prdct.size(); i++)
{
if(prdct.get(i).id.contains(line) || prdct.get(i).brandname.contains(line) || prdct.get(i).desc.contains(line)
|| prdct.get(i).category.contains(line) || prdct.get(i).supplier.contains(line))
{
System.out.println(prdct.get(i));
}
System.out.println(INPUT_PROMPT);
line = reader.readLine();
}
}
while("3".equals(line))
{
for(int i=0; i<prdct.size(); i++)
{
System.out.println(prdct.get(i));
}
System.out.println(INPUT_PROMPT);
line = reader.readLine();
}
while(!line.equals("x"))
{
System.out.println(INPUT_PROMPT);
line=reader.readLine();
}
}
catch(Exception e){
System.out.println("Input Error!");
}
}
}
The problem is with this loop:
while(reader != null)
{
for(int i=0; i<prdct.size(); i++)
{
if(prdct.get(i).id.contains(line) || prdct.get(i).brandname.contains(line) || prdct.get(i).desc.contains(line)
|| prdct.get(i).category.contains(line) || prdct.get(i).supplier.contains(line))
{
System.out.println(prdct.get(i));
}
System.out.println(INPUT_PROMPT);
line = reader.readLine();
}
}
It keeps on looping while reader is not null and it will never be. You might want to try checking something else that suits your problem better, maybe:
While(!line.equals("3"))
While(!line.equals("x"))
While(line != null)
Otherwise, even if there is an 'x', '3' or simply nothing, still (reader != null) and therefore the loop is infinite.
I suspect that the newline character is what causes the comparison to fail.
Instead of checking if:
"3".equals(line)
Try:
"3".equals(line.trim())
Same applies to the following comparison.
Try changing this..
line = reader.readLine();
while(reader != null)
{
to this..
line = reader.readLine();
while(line != null)
{
You are looping on the reader being not null, which it always will be.
you have to define these functions:
public void showAllRecords() {
// show all record here
}
public void insertRecord() {
// insert record here
}
public void removeRecord() {
// insert record here
}
public void exit() {
// insert record here
}
then
do{
System.out.println(INPUT_PROMPT);
switch(line)
{
case "3":
showAllRecords();
break;
case "4":
insertRecord();
break;
case "5":
removeRecord();
}
}while(!line.equals('x'));

How to create item objects from reading a text file?

I'm trying to read data from a text file and create Item Objects with it.
Item Objects have fields String title, String formatt, boolean onLoan, String loanedTo and String dateLoaned. In my save()method, I print every object to a text file in a new line and the fields are seperated by "$" (dollar sign). How can I read the text file line by line and create a new object from each line and add it to an array.
TextFile Example:
StarWars$DVD$false$null$null
Aliens$Bluray$true$John$Monday
public void save() {
String[] array2 = listForSave();
PrintWriter printer = null;
try {
printer = new PrintWriter(file);
for (String o : array2) {
printer.println(o);
}
printer.close();
} catch ( IOException e ) {
e.printStackTrace();
}
}
public void open(){
try{
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
StringBuffer stringBuffer = new StringBuffer();
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuffer.append(line);
stringBuffer.append("\n");
}
fileReader.close();
System.out.println("Contents of file:");
System.out.println(stringBuffer.toString());
}catch ( IOException e ) {
e.printStackTrace();
}
}
Thanks everyone. Here's my final code:
public void open(){
try{
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
String line;
String[] strings;
while ((line = bufferedReader.readLine()) != null) {
strings = line.split("\\$");
String title = strings[0];
String format = strings[1];
boolean onLoan = Boolean.parseBoolean(strings[2]);
String loanedTo = strings[3];
String dateLoaned = strings[4];
MediaItem superItem = new MediaItem(title,format, onLoan,loanedTo,dateLoaned);
items.add(superItem);
}
fileReader.close();
}catch ( IOException e ) {
e.printStackTrace();
}
}
String line = // input line e.g. "Aliens$Bluray$true$John$Monday"
String[] strings = line.split("\\$"); // use regex matching "$" to split
String title = strings[0];
String formatt = strings[1];
boolean onLoan = Boolean.parseBoolean(strings[2]);
String loanedTo = strings[3];
String dateLoaned = strings[4];
// TODO: create object from those values
Maybe you need to handle null differently (in case you want the String "null" to be converted to null); note that you can't distinguish if null or "null" was saved.
This function converts "null" to null and returns the same string otherwise:
String convert(String s) {
return s.equals("null") ? null : s;
}
Reading the objects to an array
Since you don't know the number of elements before reading all lines, you have to work around that:
Write the number of objects in the file as first line, which would allow you to create the array before reading the first object. (Use Integer.parseInt(String) to convert the first line to int):
public void save() {
String[] array2 = listForSave();
PrintWriter printer = null;
try {
printer = new PrintWriter(file);
printer.println(array2.length);
for (String o : array2) {
printer.println(o);
}
printer.close();
} catch ( IOException e ) {
e.printStackTrace();
}
}
public void open(){
try{
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
StringBuffer stringBuffer = new StringBuffer();
int arraySize = Integer.parseInt(stringBuffer.readLine());
Object[] array = new Object[arraySize];
int index = 0;
String line;
while ((line = bufferedReader.readLine()) != null) {
// split line and create Object (see above)
Object o = // ...
array[index++] = o;
}
//...
}catch ( IOException e ) {
e.printStackTrace();
}
//...
}
or
Use a Collection, e.g. ArrayList to store the objects and use List.toArray(T[]) to get an array.
quick and dirty solution might be...
public void open(){
try{
ArrayList<Item> list = new ArrayList<Item>(); //Array of your ItemObject
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
StringBuffer stringBuffer = new StringBuffer();
String line;
while ((line = bufferedReader.readLine()) != null) {
Item itm = new Item(); //New Item Object
String [] splitLine = line.split("\\$");
item.title = splitLine[0];
item.format = splitLine[1];
item.onLoan = Boolean.parseBoolean(splitLine[2]);
item.loanedTo = splitLine[3];
item.dateLoaned = splitLine[4];
list.add(itm);
stringBuffer.append(line);
stringBuffer.append("\n");
}
fileReader.close();
System.out.println("Contents of file:");
System.out.println(stringBuffer.toString());
}catch ( IOException e ) {
e.printStackTrace();
}
}
But this is won't scale if you need to re-arrange or add new fields.
You could try this to "parse" every line of your file
String[] result = "StarWars$DVD$false$null$null".split("\\$");
for (int i=0; i<result.length; i++) {
String field = result[i]
... put the strings in your object ...
}

read and find string from text file

I am loading text file contents to GUI using this code:
try {
BufferedReader br = new BufferedReader(new FileReader ("text.txt"));
String line;
while ((line = br.readLine()) != null) {
if (line.contains("TITLE")) {
jTextField2.setText(line.substring(11, 59));
}
}
in.close();
} catch (Exception e) {
}
Then contents of text.txt file:
JOURNAL journal name A12340001
TITLE Sound, mobility and landscapes of exhibition: radio-guided A12340002
tours at the Science Museum A12340003
AUTHOR authors name A12340004
On jTextField2 I am getting this line: "Sound, mobility and landscapes of exhibition: radio-guided".
The problem is I don't know how to get to jTextField2 the string of next line "tours at the Science Museum".
I would like to ask how can I get both line on jTextField2 i.e. "Sound, mobility and landscapes of exhibition: radio-guided tours at the Science Museum"?
Thank you in advance for any help.
If you are using Java 8 and assuming that the columns have a fixed number of characters, you could something like this:
public static void main(String args[]) throws IOException {
Map<String, String> sections = new HashMap<>();
List<String> content = (List<String>)Files.lines(Paths.get("files/input.txt")).collect(Collectors.toList());
String lastKey = "";
for(String s : content){
String k = s.substring(0, 10).trim();
String v = s.substring(10, s.length()-9).trim();
if(k.equals(""))
k=lastKey;
sections.merge(k, v, String::concat);
lastKey=k;
}
System.out.println(sections.get("TITLE"));
}
The first column is the key. When the keys does not exist, the last key is used. A Map is used to store the keys and the values. When the key already exist, the value is merged with the existing one by concatenation.
This code outputs the expected String: Sound, mobility and landscapes of exhibition: radio-guidedtours at the Science Museum.
EDIT: For Java 7
public static void main(String args[]) {
Map<String, String> sections = new HashMap<>();
String s = "", lastKey="";
try (BufferedReader br = new BufferedReader(new FileReader("files/input.txt"))) {
while ((s = br.readLine()) != null) {
String k = s.substring(0, 10).trim();
String v = s.substring(10, s.length() - 9).trim();
if (k.equals(""))
k = lastKey;
if(sections.containsKey(k))
v = sections.get(k) + v;
sections.put(k,v);
lastKey = k;
}
} catch (IOException e) {
System.err.println("The file could not be found or read");
}
System.out.println(sections.get("TITLE"));
}
Why not create a MyFile class that does the parsing for you, storing key-value-pairs in a Map<String, String>, which you can then access. This will make your code more readable and will be easier to maintain.
Something like the following:
public class MyFile {
private Map<String, String> map;
private String fileName;
public MyFile(String fileName) {
this.map = new HashMap<>();
this.fileName = fileName;
}
public void parse() throws IOException {
BufferedReader br = new BufferedReader(new FileReader(fileName));
String line = br.readLine();
String key = "";
while (line != null) {
//Only update key if the line starts with non-whitespace
key = line.startsWith(" ") ? title : line.substring(0, line.indexOf(" ")).trim();
//If the key is contained in the map, append to the value, otherwise insert a new value
map.put(key, map.get(key) == null ? line.substring(line.indexOf(" "), 59).trim() : map.get(key) + line.substring(line.indexOf(" "), 59).trim());
line = br.readLine();
}
}
public String getEntry(String key) {
return map.get(key);
}
public String toString() {
StringBuilder sb = new StringBuilder();
for (Entry entry:map.entrySet()) {
sb.append(entry.getKey()).append(" : ").append(entry.getValue()).append("\n");
}
return sb.toString();
}
}
This will parse the entire file first. The expected format of the file is:
0 ... 59
[KEY][WHITE SPACE][VALUE]
0 ... 59
[WHITE SPACE][VALUE TO APPEND TO PREVIOUS KEY]
This allows for variable length keys.
Allowing you to handle exceptions separately, and then easily reference the contents of the file like so:
MyFile journalFile = new MyFile("text.txt");
try {
journalFile.parse();
} catch (IOException e) {
System.err.println("Malformed file");
e.printStackTrace();
}
jTextField2.setText(journalFile.getEntry("TITLE"));
An empty (all spaces) first column indicates that a line is the continuation of the previous one. So you can buffer the lines and repeatedly concatenate them, until you get a non-empty first column, and then write/print the whole line.
try {
BufferedReader br = new BufferedReader(new FileReader("text.txt")) ;
String line ;
String fullTitle = "" ;
while ((line = br.readLine()) != null) {
//extract the fields from the line
String heading = line.substring(0, 9) ;
String titleLine = line.substring(10, 69) ;
//does not select on "TITLE", prints all alines
if(heading.equals(" ")) {
fullTitle = fullTitle + titleLine ;
} else {
System.out.println(fullTitle) ;
fullTitle = titleLine ;
}
}
System.out.println(fullTitle) ; //flush the last buffered line
} catch (Exception e) {
System.out.println(e) ;
}
you can do this
First of all read the entire file into a string object.
then get the indexes of the TITLE and AUTHOR
like int start=str.indexOf("TITLE"); and int end=str.indexOf("AUTHOR");
then add the length of TITLE into start index start+="TITLE".length();
and subtract the length of AUTHOR from end index end-="AUTHOR".length();
at last you have the start and end index of text that you want.
so get the text like.
String title=str.subString(start,end);

Categories