Return null in method?

6

I have a method in which the function of it is, read a file and store the value written to the file in a variable and return the variable, here's the method:

public String addItemCreative(File f){
    String line = null;
    try{
        BufferedReader br = new BufferedReader(new FileReader(f));
        while( (line = br.readLine()) != null){
            line = br.readLine();
        }
    }catch(Exception e){
        e.getMessage();
    }
  return line;
}

The return value is null, because?

    
asked by anonymous 24.11.2015 / 11:57

5 answers

12

Read a file to a String

You do not need to create a method for this. The recommended way to read an entire file for a String is next :

String dados = new String(Files.readAllBytes(file.toPath()));

Preferably, specify an encoding to avoid problems with special characters:

String dados = new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8);

Problems with some implementations

Concatenating Strings

One of the answers offers:

public static String addItemCreative(File f) {
    String line, lines = "";
    try {
        BufferedReader br = new BufferedReader(new FileReader(f));
        while ((line = br.readLine()) != null) {
            lines += line;
        }
    } catch (Exception e) {
        e.getMessage();
    }
    return lines;
}

This is not good because each concatenation of two strings generates a third and the memory is consumed exponentially. If the file is large, this will force the garbage collector to run multiple times, pausing the execution of the program and leading to very poor performance.

Correct is to use StringBuilder in local implementations, which is a class that allows you to concatenate strings without the need for object synchronization. @Cantoni's answer provides an example of how to do this.

Line breaks

If the file has line breaks, you are ignoring them when joining in the String. When calling the readLine method Java does not include breaks.

If you want the contents of the String to be the same as the one in the file, you must concatenate the breaks manually.

Calling readLine more than once

In the question implementation, the readLine method is called twice. If the file contains a single line, the second call will return null .

If the file has more rows, the result will be a String with the odd rows of the file.

Handling Exceptions

The exception that should be caught is IOException . Do not capture more generic exceptions unnecessarily. You may end up covering up for errors.

In addition, calling the getMessage method does nothing. At a minimum vocie should print the error log to understand what is happening. For example:

} catch(IOException e) {
    e.printStackTrace();
}

Or catch the error and do something about it

} catch(IOException e) {
    String erro = e.getMessage();
    mostraErro(erro);
}

Failed to close file

In Java it's easy to forget that not all allocated resources are automatically released.

When opening a file for reading or writing, remember to close the file afterwards.

This can be done using the close method of one of the Reader ployments used or automatically through try-with-resources of Java 6. Example:

try (BufferedReader br = new BufferedReader(new FileReader(f))) {
    ...
}

In the code above, the close method of BufferedReader will be automatically invoked at the end of block try .

Good practices in general

Use variables in the smallest possible scope. Instead of declaring the variable line at the beginning of the method, it can be inside the block try and in catch you return null directly. Reusing variables can be confusing.

A possible implementation putting together everything I described above would be:

String quebra = System.getProperty("line.separator");

public String addItemCreative(File f) {
    try (BufferedReader br = new BufferedReader(new FileReader(f))) {
        StringBuilder sb = new StringBuilder();
        String line;
        while((line = br.readLine()) != null){
            sb.append(line);
            sb.append(quebra);
        }
        return sb.toString();
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}

Optional return

If you want to go beyond and semantically reinforce that the method has an optional return, for example if the file does not exist or is empty, you can use the new Java 8 interfaces as Optional .

These interfaces prevent you from using null to specify no value. This avoids many NullPointerException s for lack of attention, since it forces the client code to check if a value returned by the method exists.

Example:

String quebra = System.getProperty("line.separator");

public Optional<String> addItemCreative(File f) {
    try (BufferedReader br = new BufferedReader(new FileReader(f))) {
        StringBuilder sb = new StringBuilder();
        String line;
        while((line = br.readLine()) != null){
            sb.append(line);
            sb.append(quebra);
        }
        return sb.length() > 0 ? Optional.of(sb.toString()) : Optional.empty();
    } catch (IOException e) {
        e.printStackTrace();
        return Optional.empty();
    }
}

Now it's easy for someone who calls the method to know that it can not return some value.

Assuming you wanted to print the content. The method could be used like this:

Optional<String> conteudo = addItemCreative(arquivo);
if (conteudo.isPresent()) {
    imprimir(conteudo.get());
} else {
    imprimir("[arquivo vazio]");
}

Still, if you prefer a more functional format:

imprimir(addItemCreative(arquivo).orElse("[arquivo vazio]"));
    
25.11.2015 / 07:31
7

As far as I understand, the intention of your code is to read the contents of the entire file, such as text, and return it, is that right? If so, I have three observations:

  • Start with the empty string, so if the file is empty it will return "" , not null ;
  • Use a different variable to store the return value and the line being read;
  • When reading something and testing with null , do not read again , because if you do this you will be reading the next line that was read, not the same line. And worse, this new line may come with null ...
  • Example:

    public String addItemCreative(File f) throws IOException {
        String ret = "";
        BufferedReader br = new BufferedReader(new FileReader(f));
        while( (line = br.readLine()) != null){
            ret = line;
        }
        return ret;
    }
    

    (Note: cantoni example with StringBuilder is better than mine, as it avoids getting created new objects String no need)

        
    24.11.2015 / 12:50
    4

    The fact that you are doing a silent exception treatment is harming you to understand what is happening. Exceptions can be handled quietly, but as long as they do not detract from further code execution.

    Remove the exception handling and see what is happening when you do:

    BufferedReader br = new BufferedReader(new FileReader(f));
    

    Your mistake happens on this line. Probably the file passed as a parameter to FileReader does not exist.

    UPDATE

    One way to iterate over a text file can be seen below:

    public String addItemCreative(File f){
        StringBuilder lines = new StringBuilder();
        String line;
    
        BufferedReader br = new BufferedReader(new FileReader(f));
    
        while( (line = br.readLine()) != null){
            lines.append(line);
        }
    
        return lines.toString();
    }
    
        
    24.11.2015 / 12:06
    1

    You can not know exactly why you did not show the file.

    But it is very likely that the file has no line, so the code inside while (which is the part giving line ) is not executed.

    At the end of everything is returned line was assigned as null and received no value.

    There may also be an error when trying to open the file, and you are not seeing this because it is silencing the exception . If you take this try-catch you will see what is happening. It may be that the file does not exist, that you do not have permission to open it, etc.

        
    24.11.2015 / 12:02
    0

    Try to do this by concatenating row by row:

    public static String addItemCreative(File f) {
        String line, lines = "";
        try {
            BufferedReader br = new BufferedReader(new FileReader(f));
            while ((line = br.readLine()) != null) {
                lines += line;
            }
        } catch (Exception e) {
            e.getMessage();
        }
        return lines;
    }
    

    Or also do the following with StringBuilder:

    public String addItemCreative(File f) {
    
        StringBuilder lines = new StringBuilder();
        String line;
        try {
            BufferedReader br = new BufferedReader(new FileReader(f));
            while ((line = br.readLine()) != null) {
                lines.append(line);
            }
        } catch (Exception e) {
            e.getMessage();
        }
        return lines.toString();
    
    }
    
        
    24.11.2015 / 12:10