I get an error - "missing return statement" - on line 26, which in this case is the last curly bracket in the code. I know that it literally means that I have to return somewhere in the method (can you call it function?), but I'm not sure where - nor why. Here's the code:
public String[] OpenFile() throws IOException {
Map<String, Double> map = new HashMap();
FileReader fr = new FileReader("money.txt");
BufferedReader br = new BufferedReader(fr);
try{
while (br.ready()){
String str = br.readLine();
String[] list = str.split(" ");
System.out.println(list);
}
} catch (IOException e){
System.err.println("Error - IOException!");
}
}
Ok first of all please note that this is not really a beginners forum for learning any programming language. You will find it very hard to get a very basic question answered here without approximately 20 people pointing you in the direction of Google (myself included)
That being said please look for java tutorials, beginners guides, or simply the docs. The answer will almost everytime jump you straight in the face since there is just so much material on the java programming language
Stackoverflow is much more a question and answer site for more abstract problems, never-seen-before issues and tricky nuts for experts - all things that are likely to cater to a general audience and to help many people, not just yourself. Admittedly you posed your question quite nicely and formatted it well, so kudos to you and welcome to the site
As for this very specific problem you have the following options:
Declare a void return type
public void openFile() throws Exception {
}
Return a preliminary null until you're sure what to return
public String[] openFile() throws Exception {
return null;
}
(But make sure that the calling entity knows what's coming back ;))
Return some valid data to the entity that called the method
public String[] openFile() throws Exception {
String[] myArray = new String[5];
return myArray;
}
If you just want to print the file as you are doing right now, change the return type to void as follows:
public void OpenFile() throws IOException {
Otherwise, since you are just opening and reading in a text file, you might want another String variable that you append the file's lines to and then return, as opposed to a String[]. Maybe something like this:
public String openFile(String fileName) throws IOException {
String output = "";
FileReader fr = new FileReader(fileName);
BufferedReader br = new BufferedReader(fr);
try {
while (br.ready()) {
String line = br.readLine();
output += line + "\n";
}
} catch (IOException e) {
System.err.println("Error - IOException!");
}
return output;
}
public String[] OpenFile() // expected return type is String array
But you didn't return that from your method.
If you don't want to return that change your method return type to void(no return)
public void OpenFile() throws IOException {
}
Or if you want to return as expected use
public String[] OpenFile() throws IOException {
String[] arr=new String[5];
// implementation
return arr;
}
Related
So I have a text file that looks like this...
4234
Bob
6858
Joe
I am trying to read the file with java and insert the data into an array. I want to separate the data by that empty line (space). Here is the code that I have come up with to solve the issue, but I am not quite there.
public class Main {
public static void main(String[] args) {
// This name is used when saving the file
BufferedReader input;
String inputLine;
try {
input = new BufferedReader(new FileReader("test.txt"));
while ((inputLine = input.readLine()) != null) {
System.out.println(Arrays.toString(inputLine.split(" ")));
}
} catch (IOException e) {
System.out.println(e.getMessage());
System.exit(1);
}
}
}
The issue that I am coming across is that the output from the code above looks something like this
[4234]
[Bob]
[]
[6858]
[Joe]
The outcome that I would like to achieve, and for the life of me can't think of how to accomplish, is
[4234, Bob]
[6858, Joe]
I feel like with many things that it is a relatively simple code change; I am just not sure what that is.
You need:
2D array
Logic to keep track of where you are in the array position
If your Line is a Number/String
This sounds like hw :) so I wont be solving it, I will just help a bit.
String[][] myData = define your 2D array;
//You need to create a consumer. This is what will take the String line, figure out where to put it into your 2D array.
Consumer<String> processLine = (line) -> {
if(StringUtils.isNumeric(line)){
//Put into array[counter][1]
}
else{
//its a String
//Put into array[counter][0]
}
};
The below try/catch, Opens a File, Reads its Lines, and goes over each one in order (forEachOrdered), ignoring all empty lines, and send it to your processLine consumer.
try (Stream<String> lines = Files.lines(Paths.get("C:/example.txt"), Charset.defaultCharset())) {
lines.filter(line -> !line.isEmpty()).forEachOrdered(processLine);
}
catch (Exception e){
//Handle Exception
}
Used Apache StringUtils http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html
IF you dont want to use any external Libs. You can probably do
Integer.parseInt(line) <-- If that throws an exception, its not a number
Your way of reading the file is not most convenient, in this case.. Scanner would have eased all this work; however, if you insist, that you want to use BufferedReader and FileReader, it's going to be a bit verbose, boilerplate and even ugly code, something like this:
public class Main {
public static void main(String[] args) {
// This name is used when saving the file
BufferedReader input;
String inputLine;
String answer = "";
try {
input = new BufferedReader(new FileReader("path\\to\\your\\test.txt"));
while ((inputLine = input.readLine()) != null) {
answer = answer + "[" + inputLine + ", ";
while ((inputLine = input.readLine()) != null && !inputLine.equals("")) {
answer += inputLine;
}
answer += "]";
System.out.println(answer);
answer = "";
}
} catch (IOException e) {
System.out.println(e.getMessage());
System.exit(1);
}
}
}
This code, with test.txt containing:
4234
Bob
6858
Joe
4234
John
5352
Martin
will output:
[4234, Bob]
[6858, Joe]
[4234, John]
[5352, Martin]
I don't know if it's an actual requirement for you to use arrays of strings, but the better way in the long run is to create a class.
class Person {
public String id;
public String name;
public String toString() { return String.format("[%s, %s]", id, name); }
}
(note: It's a bad idea to actually make the fields public, but this makes the code shorter. You should probably use getters and setters).
Now you can create Persons while reading the file.
List<Person> allInFile = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new FileReader("path\\to\\your\\test.txt"))) {
String line = reader.readLine();
while (line != null) {
line = line.trim();
// ignore empty lines
if (line.length() == 0) {
continue;
}
// this is an id; create a person and assign id
Person person = new Person();
person.id = line;
// read consecutive field, which is the name
person.name = reader.readLine();
// add the person to the list
allInFile.add(person);
}
}
allInFile.forEach(System.out::println);
Lots of improvements to be done on this, but the main point is to put the two data points into a class.
Try with this code:
it work only when file contains number followed by name otherwise pair would be different format
pair : [number, string]
public static void main(String[] args) {
BufferedReader input;
String inputLine;
List<String> pair = new ArrayList<String>();
List<String> list = new ArrayList<String>();
try {
input = new BufferedReader(new FileReader("Test.txt"));
while ((inputLine = input.readLine()) != null) {
if (!inputLine.isEmpty()) {
pair.add(inputLine);
}
if (pair.size() == 2) {
list.add(pair.toString());
pair.clear();
}
}
for (String s : list) {
System.out.println(s);
}
} catch (IOException e) {
System.out.println(e.getMessage());
System.exit(1);
}
}
After looking at the answers posted by my fellow Stack Overflow members I figured out that there was a very simple way of solving this issue and that was by using Scanner rather than using BufferedReader. I am not sure why I didn't think of this before, but hindsight is 2020. Anyway, the code below is what I used to solve my issue.
public static void main(String[] args) {
ArrayList<String> test = new ArrayList<>();
File file = new File("test.txt");
try {
Scanner sc = new Scanner(file);
while (sc.hasNextLine()) {
test.add(sc.next()); // The id
test.add(sc.next()); // The name
}
sc.close();
System.out.println(test.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
All this is doing is getting each line with the different data on it and is skipping the blank. From there it is adding it to an ArrayList for later processing. Remember K.I.S.S (Keep It Simple Stupid) no need to overcomplicate anything.
I am trying to setup a highscore system to sort the scores from a file and seperate the names from the numbers. But when I try to use readline twice it skips 1 line because of the other readline method. Can somebody help me please, it's for school!
Example of the file:
kevin:50 dustin:31 nobody:71 imax:23
Here is the code:
public class Main {
public static void main(String[] args) {
ArrayList<Integer> result = new ArrayList<>();
String name="";
try (BufferedReader br= new BufferedReader(new FileReader("res/highscore.txt"))){
while (br.ready()){
result.add(Integer.parseInt(br.readLine().split(":")[1]));
name = br.readLine().split(";")[0];
System.out.println(name);
}
Collections.sort(result);
Collections.reverse(result);
for (Integer integer : result) {
System.out.println(integer);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
A bit of explanation on #thewho69's answer.
You have fallen into the trap of side-effects. A method might not only do what its name would intuitively suggest. In this example, the readLine() method does not only read the upcoming line, but also sets the cursor position to the beginning of the next line.
This makes the readLine method not idempotent, which means that calling the method twice with the same parameters (in this case none) will not necessarily return the same output.
In order not to fall into this trap, you have to find a way to use the current one line multiple times, while calling the br.readLine() method only once - thus setting the cursor position only once in an iteration, which is desirable in this case. A good solution to this problem is what #thewho69 suggested ~20mins ago.
Simply store each line in a variable:
public class Main {
public static void main(String[] args) {
ArrayList<Integer> result = new ArrayList<>();
String name="";
try (BufferedReader br= new BufferedReader(new FileReader("res/highscore.txt"))){
String line;
while ((line = br.readLine()) != null){
result.add(Integer.parseInt(line.split(":")[1]));
name = line.split(";")[0];
System.out.println(name);
}
Collections.sort(result);
Collections.reverse(result);
for (Integer integer : result) {
System.out.println(integer);
}
} catch (IOException e) {
e.printStackTrace();
}
}
I'm writing a java program that I'm running on the CMD line that copies several .txt files into one. For example I have three .txt files that I created. Chapter1.txt, chapter2.txt Chapter3.txt. All the contents of these files needs to be copied to book.txt. I ran the code and it ran fine until I entered the command.
java CatFiles chapter1.txt chapter2.txt chapter3.txt book.txt
The book.txt file is created but only the contents of one file are copied and I get this error code
java.land.illeglStateException: Scanner
at java.util.Scanner.ensureOpen(unknown Source)
at java.util.Scanner.findWithinHorizon(unknown Source)
at java.util.Scanner.hasNextLine(unknown Source)
at CatFiles.main(CatFiles.java)
Here's my code
public class CatFiles {
public static void main(String[] args) throws IOException {
if (args.length < 2) {
System.out.println("Usage: CatFiles sourcefile1 sourcefile2 . . . targetfile");
return;
}
String target = args[args.length - 1];
FileReader reader = null;
PrintWriter out = new PrintWriter(target);
for (int i = 0; i < args.length - 1; i++) {
String source = args[i];
reader = new FileReader(source);
}
Scanner in = new Scanner(reader);
while ( in .hasNextLine()) {
try {
String line = in .nextLine();
out.println(line);
} finally { in .close();
out.close();
}
}
}
}
Use this (note: checks about arguments are left as an exercise):
public static void main(final String... args)
{
final List<String> list = new ArrayList<>();
Collections.addAll(list, args);
final Path dstFile = Paths.get(list.remove(list.size() - 1));
try (
final OutputStream out = Files.newOutputStream(dstFile);
) {
for (final String s: list)
Files.copy(Paths.get(s), out);
}
}
You should put the while loop inside of the try block and not the contrary. Otherwise you're closing the Scanner at the first loop and you can not use it anymore. Close your Scanner once you're never using it again.
I honestly think correct indentation would have helped here.
JavaDoc
Throws: NoSuchElementException if no line was found
java.lang.IllegalStateException if this scanner is closed
Solution
Scanner in = new Scanner(reader);
try{
while (in.hasNextLine()) {
String line = in.nextLine();
out.println(line);
}
} finally {
in.close();
out.close();
}
Idiomatic Solution using Guava:
This includes basic error checking on valid number of arguments. This does not do robust idiomatic exception handling for brevity and scope control.
This solution also uses Immutable data throughout making it immune to logic errors because of side effects and state mutation.
Q33846584.java
Import statements are available in the link above.
public class Q33846584
{
public static void main(final String[] args) throws Exception
{
checkArgument(args.length > 2, "You must supply at least 3 file paths as arguments dest, src, src, ...");
final List<Path> paths = Lists.transform(Arrays.asList(args), new Function<String, Path>()
{
#Nullable #Override public Path apply(#Nullable String input)
{
return Paths.get(checkNotNull(input));
}
});
final Path destination = paths.get(0);
try (final OutputStream fos = new FileOutputStream(destination.toFile()))
{
for (final Path p : paths.subList(1, paths.size()))
{
if (p.toFile().exists())
{
System.out.format("Reading %s and writing to %s", p.toAbsolutePath(), destination.toAbsolutePath());
final FileInputStream fis = new FileInputStream(p.toFile());
ByteStreams.copy(fis, fos);
System.out.println();
}
else
{
System.err.format("%s does not exist skipping!", p.toAbsolutePath());
System.err.println();
}
}
}
}
}
Without Guava:
You would have to implement the transformation of the String[] yourself in a imperative loop which is straightforward.
You would have to implement copying the InputStream to the OutputStream which is well documented on the internet in general but is basically boilerplate code. You will end up with a possibly buggy or inefficient version of what Guava does. It would only be useful as a learning exercise at best.
Both of these activities are easy to find on Stackoverflow and are left as exercises for the reader.
I'm tasked, by my professor, to write a program to read a .csv file (778 rows (including header row), 8 columns).
I need to:
1. Write a method to receive the name of the file as its argument and then print the number of lines in the file.
public void printNumberOfLinesInFile(String fileName)
Write a method to receive the name of the file as its argument and then print the number of private and non-private colleges.
public void printNumberOfPrivateNonPrivateCollegesInFile(String fileName)
Write a method to receive the name of the file as its argument and then print the private college name with largest out of state tuition.
public void printMostExpensivePrivateCollegeInFile(String fileName)
Write a method to receive the name of the file as its argument and then print the non-private college with largest out of state tuition.
public void printMostExpensiveNonPrivateCollegeInFile(String fileName)
Write a method to receive the name of the file as its argument and then print the number of applications and the number of applicants that are accepted for private and non-private colleges.
public void printNumberOfApplications(String fileName)
Write a method to receive the name of the file as its argument and then print following information for private and non-private colleges.
Average of expenses for books.
Average of expenses for room.
Average of personal expenses.
public void printAverageOfExpenses(String fileName)
Disclaimer: I do not want anyone to do my homework for me. I need to learn so I can apply my knowledge when I graduate and enter industry. I'm simply asking for a hint or a better way at writing the code.
My code thus far:
public class Week14
{
public String data;
public void printNumberOfLinesInFile(String inFile) throws IOException
{
int collegeCount = 0;
FileReader fileRead = new FileReader(inFile);
BufferedReader bufferRead = new BufferedReader(fileRead);
while(true)
{
String line = bufferRead.readLine();
if(line == null)
{
break;
}
collegeCount++;
//System.out.println(line);
}
System.out.println(collegeCount-1 + " Colleges total.");
}
public void printNumberOfPrivateNonPrivateCollegesInFile(String inFile) throws IOException
{
int privateCount = 0;
int nonprivateCount = 0;
int count = 0;
FileReader fileRead = new FileReader(inFile);
BufferedReader bufferRead = new BufferedReader(fileRead);
while((data = bufferRead.readLine())!= null)
{
String line = bufferRead.readLine();
String [] lineItems = line.split(",");
for(int i = 0; i < line.length(); i++)
{
if(lineItems[i].equals("Yes"))
{
privateCount++;
}
}
break;
}
System.out.println(privateCount+" private Colleges.");
System.out.println(nonprivateCount+ " non-private Colleges.");
}
public void printMostExpensivePrivateCollegeInFile(String inFile) throws FileNotFoundException, IOException
{
int mostExpensive = 0;
int currentExpensive = 0;
FileReader fileRead = new FileReader(inFile);
BufferedReader bufferRead = new BufferedReader(fileRead);
while((data = bufferRead.readLine())!= null)
{
String line = bufferRead.readLine();
if(line.equals("OutstateTuition"))
{
System.out.println(line);
}
else
{
System.out.println(line);
}
}
}
public void printMostExpensiveNonPrivateCollegeInFile(String fileName)
{
}
public void printNumberOfApplications(String fileName)
{
}
public void printAverageOfExpenses(String fileName)
{
}
public static void main(String[] args) throws FileNotFoundException, IOException
{
File inFile = new File("College.csv");
FileReader fileReader = new FileReader(inFile);
BufferedReader buffReader = new BufferedReader(fileReader);
Week14 w1 = new Week14();
//w1.printNumberOfLinesInFile("College.csv");
w1.printNumberOfPrivateNonPrivateCollegesInFile("College.csv");
//^^^The above line goes into an infinite loop^^^
//w1.printMostExpensivePrivateCollegeInFile("College.csv");
}
}
The problem is, I'm stuck on trying to count the amount of private and nonprivate colleges. In my method, printNumberOfPrivateNonPrivateCollegesInFile (line 39), I'm running into an exception: java.lang.ArrayIndexOutOfBoundsException: 8
I've asked my professor how I can avoid this, I've looked online and the problem seems to lie with the iterator int 'i'. I'm trying to traverse the array, and 'i' is out of bounds. When I put a '1' in
if(lineItems[i].equals("Yes"))
for my privateCount, there is an output of 67 from privateCount, (I think it is counting the individual characters for some reason).
My question, what would be the most effective way to traverse the entire .csv file, and to access individual columns so I can count them and output them?
Any help would be greatly appreciated.
edit:
I have changed the while loop:
while(true)
{
String line = bufferRead.readLine();
String [] lineItems = line.split(",");
if(line == null)
{
break;
}
for (String lineItem : lineItems) {
privateCount++;
}
}
Now I can traverse the entire .csv file, but I'm receiving a java.lang.NullPointerException when I try and count.
edit 2:
I've redone my while loop again,
while(true)
{
String line = bufferRead.readLine();
String [] lineItems = line.split(",");
for (String lineItem : lineItems) {
if (lineItem.equals("Yes")) {
privateCount++;
}
}
System.out.println(privateCount);
}
I'm now counting the right value for privateCount, but there's a NullPointerException at :
String [] lineItems = line.split(",");
and the loop will not let me put my 'echo' outside of the while-loop without a 'break' statement.
With respect to actual industry-level code, and assuming that assignment did not specifically focus on actual CSV decoding, I would recommend finding and using a library to handle low-level decoding, such as OpenCSV, SuperCSV or CSV-module for Jackson.
This way your code can focus on more interesting part of finding specific values, and not on intricate details like possible escaping and/or quoting of contents.
If the focus is on CSV edge cases this is not the approach to use; but for real production code one hopefully rarely if ever writes the actual low-level decoding part, given the existence of multiple good libraries for the task.
if(lineItems != null && lineItems.length>0){
// do your loop
}
if (lineItem!= null && !lineItem.trim().equals("") && lineItem.equals("Yes")) {
privateCount++;
}
most likely will prevent your null issue
public void printNumberOfPrivateNonPrivateCollegesInFile(String inFile) throws IOException
{
int privateCount = 0;
int nonprivateCount = 0;
FileReader fileRead = new FileReader(inFile);
BufferedReader bufferRead = new BufferedReader(fileRead);
try
{
while(true)
{
String line = bufferRead.readLine();
String [] lineItems = line.split(",");
//System.out.println(Arrays.toString(lineItems));
for (String lineItem : lineItems)
{
if (lineItem!= null && !lineItem.trim().isEmpty() && lineItem.equals("No"))
{
nonprivateCount++;
}
if (lineItem!= null && !lineItem.trim().isEmpty() && lineItem.equals("Yes"))
{
privateCount++;
}
}
//System.out.println(privateCount);
}
}
catch(NullPointerException npe)
{
}
System.out.println(privateCount);
System.out.println(nonprivateCount);
}
Fixed it. I'm now just catching the exception so it isn't as annoying. Thanks all for the help.
I keep getting this same exception when I compile. Can anyone explain why I keep getting this error and what it means or what I need to do?
I would like to know what I am doing wrong for future references.
public static void Second()
{
int n = stringList.listSize();
for(int i=0; i<n-1; i=i+2)
{
System.out.println(stringList.retrieveAt(i) + " " + stringList.retrieveAt(i+1));
}
}
public static void Display()throws IOException, FileNotFoundException
{
Scanner infile = new Scanner(new FileReader("D:\\DataFile.txt"));
StringTokenizer token = new StringTokenizer(infile.nextLine());
StringElement str = new StringElement();
while(infile.hasNext())
{
str.setString(token.nextToken());
stringList.insert(str);
}
stringList.print();
}
The exception:
Exception in thread "main" java.util.NoSuchElementException
at java.util.StringTokenizer.nextToken(StringTokenizer.java:349)
at Programmmmmm.Display(Programmmmmm.java:121)
at Programmmmmm.main(Programmmmmm.java:67)
You're calling token.nextToken() without checking whether there are in fact more tokens in token.
Instead of checking whether there infile has more elements, you should check whether token has more tokens.
Instead of
while (infile.hasNext()) { ...
You should do
while (token.hasMoreTokens()) { ...
See Oracle's Java documentation on StringTokenizer for more information and code examples.
You're crossing the streams.
You're looping over the Scanner, but checking nextToken() on the StringTokenizer.
You aren't following the Sun Java coding standards: method names should start with a lower case letter.
That one method is doing far too much:
Reading a hard coded file path.
Tokenizing each line
Printing a list of strings.
Bad idea.
Try something more like this:
public static List<String> tokenizeTextFile(String path) throws IOException, FileNotFoundException {
List<String> words = new ArrayList<String>();
BufferedReader br = null;
if (path != null && path.length() > 0) {
try {
br = new BufferedReader(new FileReader(path));
String line;
while ((line = br.nextLine()) != null) {
String [] tokens = line.split("\\s+");
for (String token : tokens) {
words.add(token);
}
} finally {
close(br); // add this method.
}
}
return words;
}