0

My goal is to have a String that stores the contents of a file. I literally ripped the algorithm for reading a file from W3 schools (https://www.w3schools.com/java/java_files_read.asp) and simply changed a few things.

public class Fileparser { 
    
    public void fileParse(String filename) {
        
        
        try {
              File myObj = new File("C:\\Users\\(myname)\\Desktop\\" + filename);
              Scanner myReader = new Scanner(myObj);
              String output = "";
              while (myReader.hasNextLine()) {
                String data = myReader.nextLine();
                output.concat(data);
              }
              myReader.close();
              System.out.println(output);
              
              
            } catch (FileNotFoundException e) {
              System.out.println("An error occurred.");
              e.printStackTrace();
            }
        
        
    
    }

}

In main, of course, I have a Fileparser object that does the method with a file I have on my desktop, but it prints absolutely nothing. I had to wrestle with Java because I am unfamiliar with the scope of local variables. How come output prints nothing, when I am concatenating line by line to it?

1
  • 2
    The String javadoc states that: "Strings are constant; their values cannot be changed after they are created." Thus, output.concat(data); returns a new String, representing the concatenation. replace this line with output = output.concat(data);.
    – Turing85
    Commented Dec 23, 2020 at 16:30

4 Answers 4

1

Because output.concat() doesn't add anything to the string output is pointing at: That's not possible; strings in java are immutable and cannot be changed.

Instead, concat() constructs a new string that is the concatenation of the receiver and the parameter, and returns a reference to that. Something as simple as output = output.concat(data) would get the job done, but note that concatting like this is incredibly inefficient. Better:

try {
              File myObj = new File("C:\\Users\\(myname)\\Desktop\\" + filename);
              Scanner myReader = new Scanner(myObj);
              StringBuilder output = new StringBuilder();
              while (myReader.hasNextLine()) {
                String data = myReader.nextLine();
                output.append(data);
              }
              myReader.close();
              System.out.println(output);
              
              
            } catch (FileNotFoundException e) {
              System.out.println("An error occurred.");
              e.printStackTrace();
            }

and now let's fix your bugs / styilistic faux-passes:

  1. Failure to safely close the resource.
  2. Failure to specify charset encoding, making this code OS-dependent (so, a bug, and one you can't test for - quite bad)
  3. Very silly exception handling
private static final String HOMEDIR = "C:\\Users\\yourname\\Desktop\\";
public String fileParse(String filename) throws IOException {
    try (var s = new Scanner(new File(HOMEDIR + filename, StandardCharsets.UTF_8));
    StringBuilder out = new StringBuilder();
    for (String line = s.nextLine(); line != null; line = s.nextLine()) {
        out.append(line);
    }
    return line.toString(); 
}

A method named parseFile should obviously be declared to throws IOException. It's inherent in what the method is supposed to do.

And then for an encore, use modern API and naming conventions:

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

private static final Path HOME = Paths.get(System.getProperty("user.home"), "Desktop");
public String parseFile(String fileName) {
    return Files.readString(HOME.resolve(fileName));
}

Look at how short and pretty that is. one-liner!

NB: The methods in 'Files' use UTF_8 as a default, vs the old stuff that uses the useless 'platform default'.

0
1

Change the program like below to make it work as you want. Here, the behavior of string is when you create a new object it always keeps those objects in the string pool and returns a new one hence you need to assign to the existing string object to concatenate all string objects.

It is always recommended to use StringBuilder when having multiple concatenations.

public class Fileparser { 
    
    public void fileParse(String filename) {
    
    
    try {
          File myObj = new File("C:\\Users\\(myname)\\Desktop\\" + filename);
          Scanner myReader = new Scanner(myObj);
          String output = "";
          while (myReader.hasNextLine()) {
            String data = myReader.nextLine();
           output= output.concat(data);
          }
          myReader.close();
          System.out.println(output);
          
          
        } catch (FileNotFoundException e) {
          System.out.println("An error occurred.");
          e.printStackTrace();
        }
}

}

0

The return value of "concat" must be used.

Refer to the .concat javadocs. It provides the following:

Examples:
"cares".concat("s") returns "caress"
"to".concat("get").concat("her") returns "together"
It's not a void method. It's a method that returns the result of the concaconated String. So in this case, you should be doing:
while (myReader.hasNextLine()) {
    String data = myReader.nextLine();
    output=output.concat(data);
}

Although for better efficiency, I would recommending using a StringBuilder, since you are concatenating very often:

StringBuilder str = new StringBuilder();
while (myReader.hasNextLine()) {
    String data = myReader.nextLine();
    str.append(data);
}
myReader.close();
System.out.println(str.toString());

Or just better off, printing every line inside the loop instead of outside, which will (for the most part) keep the original formatting of the file:

Scanner myReader = new Scanner(myObj);
while (myReader.hasNextLine()) {
    String data = myReader.nextLine();
    System.out.println(data);
}
myReader.close();
0

Rather than concat, you’d generally write += to append to a string:

output += data;

However, both += and concat (once fixed as shown in the other answer) inside a loop are slow. A much more efficient way is to use a StringBuilder:

final StringBuilder sb = new StringBuilder();

while (myreader.hasNextLine()) {
    sb.append(myreader.readNextLine());
}

System.out.println(sb);
// or:
final String output = sb.toString();
System.out.println(output);

But there’s actually really no need for this here: just print the lines directly:

while (myReader.hasNextLine()) {
    System.out.println(myReader.nextLine());
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.