Using useDelimiter() in Java to isolate a piece of text - java

I have a text file with content that looks like this:
Event=ThermostatNight,time=0
Event=LightOn,time=2000
Event=WaterOff,time=8000
Event=ThermostatDay,time=10000
Event=Bell,time=9000,rings=5
Event=WaterOn,time=6000
Event=LightOff,time=4000
Event=Terminate,time=12000
I have to use a Scanner to grab the file and then loop through each of the lines of text and isolate each event. For example I need to isolate "ThermostatNight" in the first line and then put it in an array, the next one would be "LightOn", and so on. It's a small piece of a large project that I am working on for an intermediate Java course. I have been able to get exactly the opposite of what I want with the useDelimiter argument shown below. Is there a quick fix to this. Note that I must use the useDelimiter() method.
public void readFile2() {
array2 = new ArrayList<String>();
while (s.hasNext()) {
s.useDelimiter("=(.*?),");
array2.add(s.next());
}

You can use multiples delimiter.
//scanner.useDelimiter("Event=|,time=([0-9]*)");
scanner.useDelimiter("Event=|,(.)+[\\r\\n]*Event=|,(.)+[\\r\\n]*");
//for better you can use this
//scanner.useDelimiter("Event=|,time=([0-9]**)[\\r\\n]**Event=|,time=([0-9]*)");
while (scanner.hasNext())
{
System.out.println(scanner.next());
}

Probably not the best , but it will work
Since you have requirement to use only useDelimeter and if the structure not changed.
then
public static void main(String[] args) {
Scanner sc;
try {
sc = new Scanner(new File("/home/xxx/text.txt"));
sc.useDelimiter(",time=(.*?)\\nEvent=");
ArrayList<String> eventlist = new ArrayList<String>();
String tmp = null;
if (sc.hasNext()) {
tmp = sc.next();
tmp = tmp.split("=")[1]; // Just First line
}
while (sc.hasNext()) {
eventlist.add(tmp);
System.out.println(tmp); // for test only remove it
tmp = sc.next();
}
tmp = tmp.split(",")[0];
eventlist.add(tmp);
System.out.println(tmp); // for test only , remove it
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

Related

ArrayList of Integers inside a while loop is refusing to print

I am solving a problem from Advent of Code, and trying to put the content of the input file into an arraylist, here's my code for that:
ArrayList<Integer> arrayList = new ArrayList<>();
try (Scanner s = new Scanner(new File("input.txt")).useDelimiter(",")) {
while (s.hasNext()) {
int b = Integer.parseInt(s.next());
arrayList.add(b);
}
}
catch (FileNotFoundException e) {
// Handle the potential exception
}
System.out.println(arrayList);
and when I run it, it does not print the arraylist. I can't understand why, could someone tell me what I did wrong?
I used StringTokenizer and it works perfectly. I am not familiar with using Scanner to split items, so I converted it over into a StringTokenizer. Hope you're okay with that.
public static void main(String[] args) throws IOException {
ArrayList<Integer> arrayList = new ArrayList<>();
Scanner s = new Scanner(new File("input.in"));
StringTokenizer st = new StringTokenizer(s.nextLine(), ",");
while (st.hasMoreTokens()) {
int b = Integer.parseInt(st.nextToken());
arrayList.add(b);
}
s.close();
System.out.println(arrayList);
}
This fills your ArrayList with the values you want
You can validate if you are able to read the file or not. Your code can be modifed something like this. Please check if it prints "File found". If not it means that file you are trying to read is not in classpath. You might want to refer https://mkyong.com/java/java-how-to-read-a-file/
...
File source = new File("input.txt");
if(source.exists()) {
System.out.println("File found");
}
try (Scanner s = new Scanner(source).useDelimiter(",")) {
...

How to develop the code to save more than word in the selected file?

The goal of my program is to give the user the opportunity to add something in a new or old file.
Because of my code the user can add only one word to the file.
I wrote down where the problem is.
I do not know how to make the saving of the words in the file unlimited.
I tried with a for loop... Unfortunately it did not make any sense.
public class AddAndSave {
private static Scanner scanner = new Scanner(System.in);
private static Formatter formatter = null;
private static Scanner reader;
public static void main(String args[]) {
System.out.println("In which file do you want to add?");
String fileName = scanner.next();
File myFile = new File("C://Meine Dateien// " + fileName + ".txt");
if (myFile.exists() == true) {
try {
reader = new Scanner(myFile);
String fileContent = "";
while (reader.hasNext() == true) {
fileContent = fileContent + reader.next();
}
formatter = new Formatter(myFile);
formatter.format("%s", fileContent + " ");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
try {
formatter = new Formatter(myFile);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("What do you want to add?");
String newInput = scanner.next();//hier is the problem
formatter.format("%s", newInput);
System.out.println();
System.out.println("Finish! Thank you for using our programm!");
formatter.close();
}
}
Your problem is the fact that you are utilizing the wrong Scanner method for retrieving String line data from both file and User.
Use the Scanner#nextLine() method instead of the Scanner#next() method and use it in conjunction with the Scanner#HasNextLine() method in your while loop condition (instead of the Scanner#hasNext() method):
String newInput = scanner.nextLine();
Use the Scanner#nextLine() method where you prompt for a file name and prompt for what to add to file!. Also use it within your while loop for reading the file (in conjuction with the Scanner#hasNextLine() method). Carefully read about the differences between all these methods!
Scanner#hasNext() and Scanner#next() methods are more geared towords Token (word) based situations (one word at a time) whereas the Scanner#hasNextLine() and Scanner#nextLine() methods are used for entire string lines. This is what I believe you really want.
Other Notes:
You may want to remove the white-space after your last forward slashes (//):
"C://Meine Dateien// " + fileName + ".txt";
unless of course you want t0 add a white-space at the beginning of every every name for every file created by your application.
When using boolean variables in conditions such as those in if statements, you can just use:
if (myFile.exists()) { // IF true
instead of:
if (myFile.exists() == true) { // IF true
and:
if (!myFile.exists()) { // IF false
instead of:
if (myFile.exists() == false) { // IF false
Either way works just fine but you will later find that the shorter way is less prone to errors due to typo's and I think it's easier to read but that's just my opinion.
Don't forget to close your file reader. Use Try With Resources to take care of this sort of thing for you with regards to both your reader and writer.

Scanning integer and string from file in Java

I'm new to Java and I have to read from a file, and then convert what I have read into variables. My file consists of a fruit, then a price and it has a long list of this. The file looks like this:
Bananas,4
Apples,5
Strawberry,8
...
Kiwi,3
So far I have created two variables(double price and String name), then set up a scanner that reads from the file.
public void read_file(){
try{
fruits = new Scanner(new File("fruits.txt"));
print_file();
}
catch(Exception e){
System.out.printf("Could not find file\n");
}
}
public void print_file(){
while(fruits.hasNextLine()){
String a = fruits.nextLine();
System.out.printf("%s\n", a);
return;
}
}
Currently I am only able to print out the entire line. But I was wondering how I could break this up to be able to store the lines into variables.
So your string a has an entire line like Apples,5. So try to split it by comma and store it into variables.
String arr[] = a.split(",");
String name = arr[0];
int number = Integer.parseInt(arr[1]);
Or if prices are not integers, then,
double number = Double.parseDouble(arr[1]);
Using java 8 stream and improved file reading capabilities you can do it as follows. it stores item and count as key value pair in a map. It is easy to access by key afterwards.
I know this Maybe too advance but eventually this will help you later when getting to know new stuff in java.
try (Stream<String> stream = Files.lines(Paths.get("src/test/resources/items.txt"))) {
Map<String, Integer> itemMap = stream.map(s -> s.split(","))
.collect(toMap(a -> a[0], a -> Integer.valueOf(a[1])));
System.out.println(itemMap);
} catch (IOException e) {
e.printStackTrace();
}
output
{Apples=5, Kiwi=3, Bananas=4, Strawberry=8}
You can specify a delimiter for the scanner by calling the useDelimiter method, like:
public static void main(String[] args) {
String str = "Bananas,4\n" + "Apples,5\n" + "Strawberry,8\n";
try (Scanner sc = new Scanner(str).useDelimiter(",|\n")) {
while (sc.hasNext()) {
String fruit = sc.next();
int price = sc.nextInt();
System.out.printf("%s,%d\n", fruit, price);
}
} catch (Exception e) {
e.printStackTrace(System.out);
}
}
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Test {
public static void main(String[] args) {
BufferedReader reader;
try {
reader = new BufferedReader(new FileReader(
"C://Test/myfile.txt")); //Your file location
String line = reader.readLine(); //reading the line
while(line!=null){
if(line!=null && line.contains(",")){
String[] data = line.split(",");
System.out.println("Fruit:: "+data[0]+" Count:: "+Integer.parseInt(data[1]));
}
//going over to next line
line = reader.readLine();
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

How to read a file with delimiters

If I have a file like this, in which each section is delimited by "**". How can I read each section and put them into different data structures?
AAA
BBB
CCC
**
ccc:cc
ddd:dd
**
xyz;XYZ
abc;ABC
**
Name: John
Email: john#gmail.com
Name: Jack
Email: jack#gmail.com
Name: kate
Email: kake#hotmail.com
**
In a while loop, I can test whether the line equals "**". But since the number of lines in each section is unknown, it seems hard to recognize which section a particular line belongs to?
String line;
while((line=reader.readline()) != null){
if(!line.equals("**"){
// the line has to be parsed and built into different data structures.
For the first section, AAA,BBB,CCC will be added into an ArrayList.
}
}
IMO you should just make the reading method a little bit more clever.
Here is an example (a kind of pseudo code, assuming you have a reader that does an actual IO):
void main() {
List<List<String>> sections = ...
while(reader.hasMoreDataToProcess()) {
sections.add(processSection(reader));
}
}
List<String> processSection(reader) {
List<String> section = ...
do {
String line = reader.readLine();
if(line.equals("**")) { // end of section or whatever delimiter you have
return section;
}
section.addLine(line);
}while(true);
}
Sorry, in a hurry, so pseudocode:
currentSection = []
sections = [currentSection]
for each line:
if line is the separator:
currentSection = []
add currentSection to sections
else:
add line to currentSection
You can use split method of the string class in Java.
String string = "a-b,b-d,c-s,d-w,e-e,f-e";
String[] parts = string.split(",");
String part1 = parts[0]; // a-b
String part2 = parts[1]; // b-d
You should use scanner for this scenario. Here's how you do it. This code is not tested.
File file = new File("somefile.txt");
try {
Scanner sc = new Scanner(file);
sc.useDelimeter("\\*\\*");
while (sc.hasNext()) {
String s = sc.next();
}
sc.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
You can use a Scanner with a FileInputStream to scan the file, using setDelimiter(String) (which accepts a regex pattern) to set your delimiter.
public class Test {
public static void main(String[] args) {
ArrayList<String> firstList = new ArrayList<>();
ArrayList<String> secondList = new ArrayList<>();
try(Scanner scanner = new Scanner(new FileInputStream(new File("yourFile.txt"))).useDelimiter("[*]+")) {
firstList.add(scanner.next());
secondList.add(scanner.next());
// and so on
scanner.close();
} catch(FileNotFoundException e) {
e.printStackTrace();
}
}
}
This will take everything above ** and create a String out of it. If you want, you can then split the String, and grab the data from each line.
String[] split = scanner.next().split("\n");
for(String string : split) {
firstList.add(string);
}
In the first example, the regex [*]+ searches for multiple *. Learn more about regex (regular expressions) to add flexibility.

Scanner to reset pointer at previous line

My problem could be solved if Scanner class had previous() method on it. I am asking this question to know if there are any methods to achieve this functionality.
Input:
a file with contents like
a,1
a,2
a,3
b,1
c,1
c,2
c,3
c,4
d,1
d,2
d,3
e,1
f,1
I need to create a list of all lines that has same alphabet.
try {
Scanner scanner = new Scanner(new File(fileName));
List<String> procList = null;
String line =null;
while (scanner.hasNextLine()){
line = scanner.nextLine();
System.out.println(line);
String[] sParts = line.split(",");
procList = new ArrayList<String>();
procList.add(line);
boolean isSamealpha = true;
while(isSamealpha){
String s1 = scanner.nextLine();
if (s1.contains(sParts[0])){
procList.add(s1);
}else{
isSamealpha = false;
System.out.println(procList);
}
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
I get output like
a,1
[a,1, a,2, a,3]
c,1
[c,1, c,2, c,3, c,4]
d,2
[d,2, d,3]
f,1
[f,1]
As you can see it missed list for b and e. If I has scanner.previous() method, I would have put it in else of second while loop. Because there is no previous method, I am stuck.
Please let me know if there are any methods I can use. I can't use FileUtils.readLines() because its a 3GB file and I don't want to use my java memory to store all the file.
I would suggest reconsidering your algorithm instead. You are missing tokens because your algorithm involves reading ahead to determine when the sequence has broken, yet you aren't collecting that next line of input into the same structures that you are placing "duplicate" entries.
You can solve this without needing to read backwards. If you know that the input is always sorted, just read line by line and keep a reference to the last line (to compare with the current one).
Below is some sample code that should help. (I only typed this; I did no checking.)
Scanner scanner = new Scanner(new File(fileName));
List<String> procList = null;
String line = null;
String previousAlpha = null;
while (scanner.hasNextLine()){
line = scanner.nextLine();
if (previousAlpha == null) {
// very first line in the file
procList = new ArrayList<String>();
procList.add(line);
System.out.println(line);
previousAlpha = line.split(",")[0];
}
else if (line.contains(previousAlpha)) {
// same letter as before
procList.add(line);
}
else {
// new letter, but not the very first
// line
System.out.println(procList);
procList = new ArrayList<String>();
procList.add(line);
System.out.println(line);
previousAlpha = line.split(",")[0];
}
}

Categories