How to search for name in file and extract value - java

I have a file that looks like this:
Dwarf remains:0
Toolkit:1
Cannonball:2
Nulodion's notes:3
Ammo mould:4
Instruction manual:5
Cannon base:6
Cannon base noted:7
Cannon stand:8
Cannon stand noted:9
Cannon barrels:10
...
What is the easiest way to open this file, search for name and return the value of the field? I cannot use any external libraries.
What i have tried/is this ok?
public String item(String name) throws IOException{
String line;
FileReader in = new FileReader("C:/test.txt");
BufferedReader br = new BufferedReader(in);
while ((line = br.readLine()) != null) {
if(line.contains(name)){
String[] parts = line.split(":");
return parts[1];
}
}
return null;
}

As a followup to your code - it compiles and works ok. Be aware though, that / is not the correct path separator on Windows (\ is). You could've created the correct path using, for example: Paths.get("C:", "test.txt").toString(). Correct separator is defined as well in File.separator.

The task can be easily achieved using basic Java capabilities. Firstly, you need to open the the file and read its lines. It can be easily achieved with Files.lines (Path.get ("path/to/file")). Secondly, you need to iterate through all the lines returned by those instructions. If you do not know stream API, you can change value returned from Files.lines (...) from Stream to an array using String[] lines = Files.lines(Paths.get("path/to/file")).toArray(a -> new String[a]);. Now lines variable has all the lines from the input file.
You have to then split each line into two parts (String.split) and see whether first part equals (String.equals) what you're looking for. Then simply return the second one.

Related

Reading data and storing in array Java

I am writing a program which will allow users to reserve a room in a hotel (University Project). I have got this problem where when I try and read data from the file and store it in an array I receive a NumberFormatException.
I have been stuck on this problem for a while now and cannot figure out where I am going wrong. I've read up on it and apparently its when I try and convert a String to a numeric but I cannot figure out how to fix it.
Any suggestions, please?
This is my code for my reader.
FileReader file = new FileReader("rooms.txt");
Scanner reader = new Scanner(file);
int index = 0;
while(reader.hasNext()) {
int RoomNum = Integer.parseInt(reader.nextLine());
String Type = reader.nextLine();
double Price = Double.parseDouble(reader.nextLine());
boolean Balcony = Boolean.parseBoolean(reader.nextLine());
boolean Lounge = Boolean.parseBoolean(reader.nextLine());
String Reserved = reader.nextLine();
rooms[index] = new Room(RoomNum, Type, Price, Balcony, Lounge, Reserved);
index++;
}
reader.close();
This is the error message
This is the data in my file which I am trying to read:
Change your while loop like this
while (reader.hasNextLine())
{
// then split reader.nextLine() data using .split() function
// and store it in string array
// after that you can extract data from the array and do whatever you want
}
You're trying to parse the whole line to Integer. You can read the whole line as a String, call
.split(" ")
on it. This will split the whole line into multiple values and put them into an array. Then you can grab each item from the array and parse separately as you intended.
Please avoid posting screenshots next time, use proper formatting and text so someone can easily copy your code or test data to IDE and reproduce the scenario.
Use next() instead of nextLine().
With Scanner one must use hasNextLine, nextLine, hasNext, next, hasNextInt, nextInt etcetera. I would do it as follows:
Using Path and Files - the newer more general classes i.o. File.
Files can read lines, here I use Files.lines which gives a Stream of lines, a bit like a loop.
Try-with-resources: try (AutoCloseable in = ...) { ... } ensures that in.close() is always called implicitly, even on exception or return.
The line is without line ending.
The line is split into words separated by one or more spaces.
Only lines with at least 6 words are handled.
Create a Room from the words.
Collect an array of Room-s.
So:
Path file = Paths.get("rooms.txt");
try (Stream<String> in = Files.lines(file)) {
rooms = in // Stream<String>
.map(line -> line.split(" +")) // Stream<String[]>
.filter(words -> words.length >= 6)
.map(words -> {
int roomNum = Integer.parseInt(words[0]);
String type = words[1];
double price = Double.parseDouble(words[2]);
boolean balcony = Boolean.parseBoolean(words[3]);
boolean lounge = Boolean.parseBoolean(words[4]);
String reserved = words[5];
return new Room(roomNum, type, price, balcony, lounge, reserved);
}) // Stream<Room>
.toArray(Room[]::new); // Room[]
}
For local variables use camelCase with a small letter in front.
The code uses the default character encoding of the system to convert the bytes in the file to java Unicode String. If you want all Unicode symbols,
you might store your list as Unicode UTF-8, and read them as follows:
try (Stream<String> in = Files.lines(file, StandardCharsets.UTF_8)) {
An other issue is the imprecise floating point double. You might use BigDecimal instead; it holds a precision:
BigDecimal price = new BigDecimal(words[2]);
It is however much more verbose, so you need to look at a couple of examples.

Removing duplicate lines from a text file

I have a text file that is sorted alphabetically, with around 94,000 lines of names (one name per line, text only, no punctuation.
Example:
Alice
Bob
Simon
Simon
Tom
Each line takes the same form, first letter is capitalized, no accented letters.
My code:
try{
BufferedReader br = new BufferedReader(new FileReader("orderedNames.txt"));
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("sortedNoDuplicateNames.txt", true)));
ArrayList<String> textToTransfer = new ArrayList();
String previousLine = "";
String current = "";
//Load first line into previous line
previousLine = br.readLine();
//Add first line to the transfer list
textToTransfer.add(previousLine);
while((current = br.readLine()) != previousLine && current != null){
textToTransfer.add(current);
previousLine = current;
}
int index = 0;
for(int i=0; i<textToTransfer.size(); i++){
out.println(textToTransfer.get(i));
System.out.println(textToTransfer.get(i));
index ++;
}
System.out.println(index);
}catch(Exception e){
e.printStackTrace();
}
From what I understand is that, the first line of the file is being read and loaded into the previousLine variable like I intended, current is being set to the second line of the file we're reading from, current is then compared against the previous line and null, if it's not the same as the last line and it's not null, we add it to the array-list.
previousLine is then set to currents value so the next readLine for current can replace the current 'current' value to continue comparing in the while loop.
I cannot see what is wrong with this.
If a duplicate is found, surely the loop should break?
Sorry in advance when it turns out to be something stupid.
Use a TreeSet instead of an ArrayList.
Set<String> textToTransfer = new TreeSet<>();
The TreeSet is sorted and does not allow duplicates.
Don't reinvent the wheel!
If you don't want duplicates, you should consider using a Collection that doesn't allows duplicates. The easiest way to remove repeated elements is to add the contents to a Set which will not allow duplicates:
import java.util.*;
import java.util.stream.*;
public class RemoveDups {
public static void main(String[] args) {
Set<String> dist = Arrays.asList(args).stream().collect(Collectors.toSet());
}
}
Another way is to remove duplicates from text file before reading the file by the Java code, in Linux for example (far quicker than do it in Java code):
sort myFileWithDuplicates.txt | uniq -u > myFileWithoutDuplicates.txt
While, like the others, I recommend using a collection object that does not allow repeated entries into the collection, I think I can identify for you what is wrong with your function. The method in which you are trying to compare strings (which is what you are trying to do, of course) in your While loop is incorrect in Java. The == (and its counterpart) are used to determine if two objects are the same, which is not the same as determining if their values are the same. Luckily, Java's String class has a static string comparison method in equals(). You may want something like this:
while(!(current = br.readLine()).equals(previousLine) && current != null){
Keep in mind that breaking your While loop here will force your file reading to stop, which may or may not be what you intended.

Regex to match a String with asterisk

I'm coding in Java and I want to split my string. I want to split it at.
/* sort */
Yes I plan to split a .java file that I have read as a string so I need it to include "/* sort */". I'm creating a code that sorts Arrays that are predefined in java class file.
Exactly that and do another split at
}
and then I wanted help how to go about splitting up the array since I'll be left with
an example would be this
final static String[] ANIMALS = new String[] /* sort */ { "eland", "antelope", "hippopotamus"};
My goal would be to sort that Array inside a .java file and replace it. This is my current code
private void editFile() throws IOException {
//Loads the whole Text or java file into a String
try (BufferedReader br = new BufferedReader(new FileReader(fileChoice()))) {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
}
everything = sb.toString();
}
arrayCutOff = everything.split("////* sort *////");
for(int i = 0; i < arrayCutOff.length; i++){
System.out.println(arrayCutOff[i]);
}
}
This basically reads the whole .txt or .java file completely with the exact same formatting into one string. I planned to split it at /* sort */ and sort the array inside but I realized if I did that I probably can't replace it.
Considered your're using java 8 you might go this direction:
private void editFile() throws IOException {
List<String> lines = Files.readAllLines(Paths.get(fileChoice()));
String content = lines.stream().collect(Collectors.joining(System.lineSeparator()));
Stream.of(content.split(Pattern.quote("/* sort */"))).forEach(System.out::println);
}
However, the trick you're asking for is Pattern.quote, which dates back Java 5. It'll qoute a literal so it can be used as a literal in regExs and is a bit more convenient (and reliable I think) than wrestling around with backslashes...

How do I get rid of these empty strings?

My constructor takes a filename of a text file and converts it to an ArrayList of all the words in lowercase, without punctuation or white space. These specs, along with the constructor's argument are specified by my homework assignment, so don't suggest I change them.
private ArrayList<String> list;
public Tokenizer(String file) throws IOException {
list = new ArrayList<>();
String thisLine;
BufferedReader br = new BufferedReader(new FileReader(file));
while ((thisLine = br.readLine()) != null)
list.addAll(Arrays.asList(thisLine.replaceAll("\\p{Punct}+"," ").toLowerCase().split("\\s+")));
}
My problem is that there are many empty strings that appear. I've tried using "-1" as the second argument in "split", but it doesn't seem to do anything.
My other question is if its inefficient to do Arrays.asList, or if I should just create an iterator, plus if you think I do anything else wrong. eg, is there another way to input a filename into the BufferedReader?
Thanks
Edit 1:
Below is test I used for an online book (it is a text file and there are not problems with the text file) I found on project Gutenberg. I also get similar results when using a text file that I personally create, so don't think its a problem with the text file itself.
In fact, I'll just reproduce my entire code since its pretty simple:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
public class Tokenizer {
private ArrayList<String> list;
public Tokenizer(String file) throws IOException {
list = new ArrayList<>();
String thisLine;
BufferedReader br = new BufferedReader(new FileReader(file));
while ((thisLine = br.readLine()) != null)
list.addAll(Arrays.asList(thisLine.replaceAll("\\p{Punct}+"," ").toLowerCase().trim().split("\\s+")));
}
public ArrayList<String> wordList() {
return list;
}
public static void main(String[] args) throws IOException {
Tokenizer T = new Tokenizer("C:\\...\\1898amongmyb00loweuoft_djvu.txt");
ArrayList<String> array = T.wordList();
for(int i = 0; i < 20; i++) {
System.out.println(array.get(i));
}
}
}
And here is my output:
i
9
digitized
by
the
internet
archive
in
2007
with
funding
from
microsoft
corporation
No, those empty lines are not white space. They are empty strings. As in, "". I hope I am as clear as possible.
Since it will probably cause confusion, no that is not the actual argument I use for the path name of the file. The ellipsis (the "...") is just a shorthand, so I don't have to reveal my computer directories to the internet.
Also, yes there is another empty string at the end, but this website's interface will not let me put it there.
Edit 2:
I always forget something, here is the first few lines of the text file:
I 9
Digitized by the Internet Archive
in 2007 with funding from
Microsoft Corporation
http://www.archive.org/details/1898amongmyb00loweuoft
James Ettsscll Lotocll.
COMPLETE POETICAL AND PROSE WORKS. Riverside
Edition, n vols, crown 8vo, gilt top, each, $ 1.50 ; the set,
$ 1 6. 50.
1-4. Literary Essays (including My Study Windows, Among
My Books, Fireside Travels) ; 5. Political Essays ; 6. Literary
and Political Addresses ; 7. Latest Literary Essays and Ad-
dresses, The Old English Dramatists ; 8-1 1. Poems.
PROSE WORKS. Riverside Edition. With Portraits. 7 vols,
crown 8vo, gilt top, $10.50.
POEMS. Riverside Edition. With Portraits. 4 vols, crown
8vo, gilt top, $6.00.
COMPLETE POETICAL WORKS. Cambridge Edition.
Printed from clear type on opaque paper, and attractively
bound. With a Portrait and engraved Title-page, and a
Vignette of Lowell's Home, Elmwood. Large crown 8vo, $2.00.
Household Edition. With Portrait and Illustrations. Crown
8vo, $1.50.
Cabinet Edition. i8
I think I now see the problem. The empty strings correspond to the empty lines.
Edit 3:
So I ended up answering my own problem. I ended up doing this:
while ((thisLine = br.readLine()) != null) {
ArrayList<String> newList = new ArrayList(Arrays.asList(thisLine.replaceAll("\\p{Punct}+"," ").toLowerCase().split("\\s+")));
while(newList.remove(""));
list.addAll(newList);
}
I did try using an if statement, but then you are comparing the line before the split. This could be problematic because the split may produce some empty lines you would then miss. Therefore, I made the list I was going to add to my main list, but before adding it, I just went through it and deleted all of the instances of empty strings.
I don't really know if this is the most efficient way of doing things... if its not let me know!
Your problem most likely is that there is a space at the beginning or end of your thisLine read from the file. Which is very common for a text document to have lines like this. So if you call split on \s+ and the line ends with a space, the very last thing will be an empty string.
To fix this, I would suggest to add a trim on your string before you do the split.
Using your code change it to:
list.addAll(Arrays.asList(thisLine.replaceAll("\\p{Punct}+"," ").toLowerCase().trim().split("\\s+")));
Try that and see if it doesn't get rid of most if not all of your empty strings. Also, you should consider breaking this statement up into multiple operations so that it is easier to read.
How about replacing while ((thisLine = br.readLine()) != null)
list.addAll(Arrays.asList(thisLine.replaceAll("\\p{Punct}+"," ").toLowerCase().trim().split("\\s+")));
with: while ((thisLine = br.readLine()) != null )
if (thisLine.length() > 0)
list.addAll(Arrays.asList(thisLine.replaceAll("\\p{Punct}+", " ").toLowerCase().trim().split("\\s+")));

Finding a word and copying the line it's in in Java

I'm trying to create a small program that allows you to search for a word in a text file, and then the program should print out the whole line the text is in.
Example:
test.txt
don't mind this text
don't mind this either
and then when you let the program search for the word "text", it should print out "Don't mind this text".
What's the best way to do this?
This is what I have;
public boolean findFileInCache(){
try (BufferedReader br = new BufferedReader(new FileReader("direct.txt")))
{
while ((name = br.readLine()) != null)
{
Process p = Runtime.getRuntime().exec(name);
}
}
catch (IOException e1) { }
return true;
}
Use BufferedReader to read the file line by line using the BufferedReader.readLine() method.
For each line, check if the word is in it using a regular expression, or by splitting the line into a String[] (using String.split()), and iterating the entries in the resulting array to check if any of them is the desired word. If the desired word is there - print the entire line.
If you chose the 2nd suggestion, don't forget to check equality of two strings by using equals() and NOT by using ==
There are a couple of things you need to do:
Learn the basics by going through an introductory Java book, or course notes, from the beginning, making sure you understand each step as it comes.
Read the Javadocs of likely classes, to find methods that could be useful for the task.
You have already found two core pieces of the solution:
You are getting a line at a time using BufferedReader.readLine()
You are doing it in a while loop, so you handle one line at a time
Now, you need to work out how to deal with each line. Although you didn't include the type, name is a String. It would be better as:
while ((String name = br.readLine()) != null) {
... do something with `line`
}
If your code compiled without String there, it means you declared name as a global. Don't do that, until you know what you're doing.
Breaking things into methods is good; so let's make "do something with line" use a method now:
while ((String name = br.readLine()) != null) {
if(matches(line,"text")) {
System.out.println(line);
}
}
Now you need to write matches():
private boolean matches(String line, String word) {
boolean result = // work out whether it's a match
return result;
}
So, how do you write the guts of matches()?
Well, start by looking at the methods available in String. It has methods like contains() and split(). Some of those methods return other types, like arrays. Your teaching material and reference materials tell you how to look in arrays. The answers are there.

Categories

Resources