I'm having trouble with my scanner when it's reading a file. It's suppose to make a new token when there's a comma followed by a space or when a new line is created, but after the 4 tokens, it throws the NoSuchElementException.
private Map<String, Double> createElementMassMap(String filePath) {
Map<String, Double> elementMap = new HashMap<>();
try (Scanner sc = new Scanner(new FileReader(filePath))) {
sc.useDelimiter(Pattern.compile("(, ) | (\r\n)"));
sc.useLocale(Locale.US);
while(sc.hasNext()) {
String name = sc.next();
System.out.println(name);
double mass = sc.nextDouble();
System.out.println(mass);
elementMap.put(name, mass);
}
} catch (IOException e) {
e.printStackTrace();
JOptionPane.showMessageDialog(self, "Error loading ElementMasses file.", "IOException", JOptionPane.ERROR_MESSAGE);
}
return elementMap;
}
Here's the file it's trying to read
H, 1.00
O, 16.00
and i made sure there isn't an empty line in the file.
Well im an idiot, my pattern was messed up.
//instead of
sc.useDelimiter(Pattern.compile("(, ) | (\r\n)"));
//it should be this
sc.useDelimiter(Pattern.compile("(, )|(\r\n)"));
thank you guys for the helpful answers though!
What platform are you using? The line separator differs from platform to platform. Use this for supporting both(and of course remove the extra spaces surrounding the '|' in the regex).
sc.useDelimiter("(, )|(\r\n)|(\n)");
I tried running this code on my computer like so:
import javax.swing.JOptionPane;
import java.util.Scanner;
import java.util.Locale;
import java.util.regex.Pattern;
import java.io.FileReader;
import java.util.HashMap;
import java.util.Map;
import java.io.IOException;
import java.awt.Component;
public class Test {
public static void main(String[] args) {
createElementMassMap("file.txt");
}
private static Map<String, Double> createElementMassMap(String filePath) {
Map<String, Double> elementMap = new HashMap<>();
try (Scanner sc = new Scanner(new FileReader(filePath))) {
sc.useDelimiter(Pattern.compile("(, ) | (\r\n) | (\n)"));
sc.useLocale(Locale.US);
while(sc.hasNext()) {
String name = sc.next();
System.out.println(name);
System.out.println("hi");
double mass = sc.nextDouble();
System.out.println(mass);
elementMap.put(name, mass);
}
} catch (IOException e) {
e.printStackTrace();
JOptionPane.showMessageDialog((Component)new Object(), "Error loading ElementMasses file.", "IOException", JOptionPane.ERROR_MESSAGE);
}
return elementMap;
}
}
and what I got was
H, 1.00
O, 16.00
hi
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1485)
at java.util.Scanner.nextDouble(Scanner.java:2413)
at Test.createElementMassMap(Test.java:25)
at Test.main(Test.java:13)
So, it looked like the first match matched the entire file. If you remove the spaces around the pipes:
import javax.swing.JOptionPane;
import java.util.Scanner;
import java.util.Locale;
import java.util.regex.Pattern;
import java.io.FileReader;
import java.util.HashMap;
import java.util.Map;
import java.io.IOException;
import java.awt.Component;
public class Test {
public static void main(String[] args) {
createElementMassMap("file.txt");
}
private static Map<String, Double> createElementMassMap(String filePath) {
Map<String, Double> elementMap = new HashMap<>();
try (Scanner sc = new Scanner(new FileReader(filePath))) {
sc.useDelimiter(Pattern.compile("(, ) | (\r\n) | (\n)"));
sc.useLocale(Locale.US);
while(sc.hasNext()) {
String name = sc.next();
System.out.println(name);
System.out.println("hi");
double mass = sc.nextDouble();
System.out.println(mass);
elementMap.put(name, mass);
}
} catch (IOException e) {
e.printStackTrace();
JOptionPane.showMessageDialog((Component)new Object(), "Error loading ElementMasses file.", "IOException", JOptionPane.ERROR_MESSAGE);
}
return elementMap;
}
}
The message disappears and it works perfectly
I don't like scanner, and avaid it as much as I can.
If yo want to try bufferedReader, here's the way to do it:
BufferedReader in = new BufferedReader(new FileReader(filePath));
StringTokenizer st;
String line;
try {
while((line = in.readLine()) != null) {
st = new StringTokenizer(line,", " );
String name = st.nextToken();
System.out.println(name);
double mass = Double.parseDouble(st.nextToken());
System.out.println(mass);
}
} catch (Exception e) {
// kaboom... something happened
e.printStackTrace();
}
EDIT:
You can tweak the delimeter in StringTokenizer constructor to suit your needs
Related
The purpose of this program is to take the graphics constants from a separate Java source code file and write an updated file with the graphics constants in that same Java program either scaled up or down.
However, I'm not sure how to only change numbers in certain lines and ignore others. For example, I don't want to change the numbers for the RGB values so the colors would remain the same.
So how would I exclude certain lines from changing the number values?
import java.io.File;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Scanner;
import java.util.Arrays;
public class ScaleUpOrDown {
public static void main() {
File myFile = new File("SampleGraphics2.java");
try {
Scanner filereader = new Scanner(myFile);
do {
BufferedWriter OutputF = new BufferedWriter(new FileWriter("OutputForDouble.txt", true));
String line = filereader.nextLine();
int nu = 0;
String[] diffArray;
String sp[] = line.split(" ");
Pattern patternP = Pattern.compile("-?\\d+");
for (int i = 0; i < sp.length; i++) {
Matcher matchN = patternP.matcher(sp[i]);
while (matchN.find()) {
sp[i] = String.valueOf(Integer.parseInt(matchN.group()) * 2);
}
}
Arrays.stream(sp).forEach(string -> extraFunction(string));
OutputF.append("\n");
OutputF.close();
} while (filereader.hasNextLine());
filereader.close();
} catch (IOException e) {
System.out.println("Error, file not found!");
}
}
public static void extraFunction(String Bigstring) {
try {
BufferedWriter writingT = new BufferedWriter(new FileWriter("OutputForDouble.txt", true));
writingT.append(Bigstring + " ");
writingT.close();
System.out.print(Bigstring);
} catch (IOException e) {
System.out.println("Unable to write to file.");
}
}
}
Currently, I'm at the point where I have only sorted the names within the file but I want to also make it so that ages can be sort. Another problem would be trying to get names that are the same but have different ages to sort. Right now my code looks something like this:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class MultiKey {
public static void main(String[] args) {
File textFile = new File("H:\\Names_ages.txt");
FileReader in;
BufferedReader readFile;
String lineOfText;
try {
in = new FileReader(textFile);
readFile = new BufferedReader(in);
BufferedReader reader = new BufferedReader(new FileReader(textFile));
List<String> results = new ArrayList<String>();
while ((lineOfText = readFile.readLine()) != null) {
results.add(lineOfText);
}
Collections.sort(results);
System.out.println(results);
readFile.close();
in.close();
} catch (FileNotFoundException e){
System.out.println("File does not exist or could not be found");
System.err.println("FileNotFoundException: "+ e.getMessage());
} catch (IOException e){
System.out.println("Problem reading file");
System.err.println("IOException: " + e.getMessage());
}
}
}
Logic:
Create a separate holder for the attributes you want to have the sorting on.
Apply Comparator on that Person object.
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class MultiKey {
public static void main(String[] args) {
File textFile = new File("H:\\Names_ages.txt");
FileReader in;
BufferedReader readFile;
String lineOfText;
try {
in = new FileReader(textFile);
readFile = new BufferedReader(in);
BufferedReader reader = new BufferedReader(new FileReader(textFile));
List<Person> results = new ArrayList<Person>();
while ((lineOfText = readFile.readLine()) != null) {
//split here the line into name and age separate variables basedon delimiter available between them.
Person p = new Person(name,age);
results.add(p);
}
order(results);
System.out.println(results);
readFile.close();
in.close();
} catch (FileNotFoundException e){
System.out.println("File does not exist or could not be found");
System.err.println("FileNotFoundException: "+ e.getMessage());
} catch (IOException e){
System.out.println("Problem reading file");
System.err.println("IOException: " + e.getMessage());
}
}
}
private static void order(List<Person> persons) {
Collections.sort(persons, new Comparator<Person>() {
public int compare(Object o1, Object o2) {
String x1 = ((Person) o1).getName();
String x2 = ((Person) o2).getName();
int sComp = x1.compareTo(x2);
if (sComp != 0) {
return sComp;
} else {
Integer x1 = ((Person) o1).getAge();
Integer x2 = ((Person) o2).getAge();
return x1.compareTo(x2);
}
}});
}
public class Person{
private String name;
private int age;
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
public int getAge(){
return this.age;
}
public vois setAge(int age){
this.age = age;
}
}
Typical Approach would be:
Parse each line and create an encapsulation object for it
(in your example a class "Person" with two fields for "name" and "age")
How you do this parsing depends on the format of the lines in the file
e.g. you can use String.split(",") for this, if the values in the line
are separated by comma.
Add the encapsulation objects to a list and then e.g. sort using
a Comparator. Use java.util.Collections.sort(Comparator).
Of course, with that list of encapsulation objects you can do much more very easily, e.g. find Persons with same Name but different Ages.
You can use the thenComparing to chain Comparators
Comparator<String> byName = Comparator.comparing(s -> s.split(" ")[0]);
Comparator<String> byAge = Comparator.comparingInt(s -> Integer.parseInt(s.split(" ")[1]));
try (BufferedReader br = new BufferedReader(new FileReader("filePath"))) {
List<String> sorted = br.lines().sorted(byName.thenComparing(byAge)).collect(Collectors.toList());
return sorted;
} catch (IOException e) {
e.printStackTrace();
}
If more than one space also expected try pattern \\s+ instead of white space
or we can create a Comparator like below instead of creating two Comparators
Comparator<String> c = Comparator.<String, String> comparing(s -> s.split("\\s+")[0])
.thenComparingInt(s -> Integer.parseInt(s.split("\\s+")[1]));
I cannot figure out how to make this txt file with numbers into an array, I am able to get it to read and print the screen but I need to be able to organize the numbers and delete the duplicates. This is what my code looks like so far
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class File {
public static void main(String[] args) {
String filename = "C:/input.txt";
File rfe = new File();
rfe.readFile(filename);
}
private void readFile(String name) {
String input;
try (BufferedReader reader = new BufferedReader(new FileReader(name))) {
while((input = reader.readLine()) != null) {
System.out.format(input); // Display the line on the monitor
}
}
catch(FileNotFoundException fnfe) {
}
catch(IOException ioe) {
}
catch(Exception ex) { // Not required, but a good practice
}
}
}
I would recommend using an ArrayList rather than an Array.
With an array you would have to parse through the list and calculate the line count before you could even initialize it. An ArrayList is much more flexible as you don't have to declare how many values will be added to it.
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class File {
private List<Integer> data = new ArrayList<Integer>(); //Create ArrayList
public static void main(String[] args) {
String filename = "C:/input.txt";
File rfe = new File();
rfe.readFile(filename);
}
private void readFile(String name) {
String input;
try (BufferedReader reader = new BufferedReader(new FileReader(name))) {
while((input = reader.readLine()) != null) {
data.add(Integer.parseInt(input));//Add each parsed number to the arraylist
System.out.println(input); // Display the line on the monitor
}
}
catch(FileNotFoundException fnfe) {
}
catch(IOException ioe) {
}
catch(Exception ex) { // Not required, but a good practice
ex.printstacktrace(); //Usually good for general handling
}
}
}
For example we have a .txt file:
Name smth
Year 2012
Copies 1
And I want to replace it with that:
Name smth
Year 2012
Copies 0
Using java.io.*.
Here is the code that does that. Let me know if you have any question.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.LinkedHashMap;
import java.util.Map;
public class Test2 {
Map<String, String> someDataStructure = new LinkedHashMap<String, String>();
File fileDir = new File("c:\\temp\\test.txt");
public static void main(String[] args) {
Test2 test = new Test2();
try {
test.readFileIntoADataStructure();
test.writeFileFromADataStructure();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
private void readFileIntoADataStructure() throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(
new FileInputStream(fileDir)));
String line;
while ((line = in.readLine()) != null) {
if (line != null && !line.trim().isEmpty()) {
String[] keyValue = line.split(" ");
// Do you own index and null checks here this is just a sample
someDataStructure.put(keyValue[0], keyValue[1]);
}
}
in.close();
}
private void writeFileFromADataStructure() throws IOException {
Writer out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(fileDir)));
for (String key : someDataStructure.keySet()) {
// Apply whatever business logic you want to apply here
myBusinessMethod(key);
out.write(key + " " + someDataStructure.get(key) + "\n");
out.append("\r\n");
out.append("\r\n");
}
out.flush();
out.close();
}
private String myBusinessMethod(String data) {
if (data.equalsIgnoreCase("Copies")) {
someDataStructure.put(data, "0");
}
return data;
}
}
Read your original text file line by line and separate them into string tokens delimited by spaces for output, then when the part you want replaced is found (as a string), replace the output to what you want it to be. Adding the false flag to the filewrite object ("filename.txt", false) will overwrite and not append to the file allowing you to replace the contents of the file.
this is the code to do that
try {
String sCurrentLine;
BufferedReader br = new BufferedReader(new FileReader("yourFolder/theinputfile.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("yourFolder/theinputfile.txt" , false));
while ((sCurrentLine = br.readLine()) != null) {
if(sCurrentLine.indexOf("Copies")>=0){
bw.write("Copies 0")
}
System.out.println(sCurrentLine);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close()bw.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
hopefully that help
Trying to read a file when the user enters the file name into the console. The program compiles and runs with no errors. Once you enter the file name and press enter, you get this error. Can't figure out why. Any help would be appreciated.
Exception in thread "main" java.lang.NullPointerException
at java.io.Writer.<init>(Writer.java:88)
at java.io.PrintWriter.<init>(PrintWriter.java:113)
at java.io.PrintWriter.<init>(PrintWriter.java:100)
at propertylistings.propertylistings.main(propertylistings.java:34)
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeSet;
public class propertylistings {
public static void main(String[] args)
throws FileNotFoundException
{
// Prompt for the input file name
Scanner console = new Scanner(System.in);
System.out.print("Input file: ");
String inputFileName = console.next();
BufferedWriter pwfo = null;
try {
pwfo = new BufferedWriter(new FileWriter("C:\\agentReport.txt",
true));
} catch (IOException e) {
}
//next line is LINE 34
PrintWriter pwo = new PrintWriter(pwfo);
// Construct property type treeSet
Set<String> propertyTypes = pTypes(inputFileName);
// Print property types from treeSet
for (String type : propertyTypes) {
System.out.println(type);
pwo.println(type);
}
// Construct agent ids and values treeSet
Set<String> agentRpt = agentValue(inputFileName);
// Print agent Ids and values from key set
for (String tail : agentRpt) {
{
System.out.println(tail);
pwo.println(tail);
}
}
pwo.flush();
pwo.close();
}
// Reads the input file.
// #return the alphabetized property types in uppercase.
public static Set<String> pTypes(String inputFileName)
throws FileNotFoundException
// Construct a tree set to return property types
{
Set<String> type = new TreeSet<String>();
Scanner in = new Scanner(new File(inputFileName));
// Use delimiters to select specific chars for set
in.useDelimiter("[1234567890. ]");
while (in.hasNext()) {
type.add(in.next().toUpperCase());
}
in.close();
return type;
}
// Reads the input file.
// #returns the Agent id's and corresponding property values.
public static Set<String> agentValue(String inputFileName)
throws FileNotFoundException {
TreeSet<String> tail = new TreeSet<String>();
SortedMap<String, Number> agentValues = new TreeMap<String, Number>();
Scanner in = new Scanner(new File(inputFileName));
String line = inputFileName;
while (in.hasNextLine()) {
try {
line = in.nextLine();
String[] fields = line.split("[\\s}]");
String agentId = (fields[3]);
Double pValue = Double.parseDouble(fields[2]);
if (agentValues.containsKey(agentId)) {
pValue += agentValues.get(agentId).doubleValue();
}
agentValues.put(agentId, pValue);
} catch (Exception e) {
}
// Create keyMap with all keys and values
Set<String> keySet = agentValues.keySet();
for (String key : keySet) {
Number value = agentValues.get(key);
// System.out.println(key + ":" + value);
tail.add(key + ":" + value);
}
}
return tail;
}
}
Put a stacktrace in your catch block and you'll know the exact error.
try {
pwfo = new BufferedWriter(new FileWriter("C:\\agentReport.txt", true));
} catch (IOException e) {
e.printstacktrace();
}