While with incomprehensible format

4

My knowledge of java is very basic, and I came across a question that I have not yet answered. The code snippet below is used in some of my applications:

File arquivo = new File("ip.txt");  
FileInputStream fis = new FileInputStream(arquivo);  

while ( (ln = fis.read()) != -1 ) {  
    st += (char)ln;  
}  

fis.close();

However, I can not understand this short excerpt:

while ( (ln = fis.read()) != -1 ) {  
    st += (char)ln;  
}

Would anyone explain me what it means?

    
asked by anonymous 12.11.2015 / 03:26

2 answers

13

You need to understand what expressions are. And that they can be formed by subexpressions. Java is a reasonably well written language and does not do magic. Everything has one criterion. If you understand these criteria, you can understand anything in the language, even without knowing what it is. That's the difference between learning how to program and following cake recipe.

A while statement experiments a Boolean result to decide whether to continue executing that block of code or not. And this, in this case, is obtained by the != operator. This operator always returns a Boolean, that is, true or false . Like most operators, it has two operands. And these operands together with the operator forms an expression. One of them is easily identifiable, it is -1 - a literal. The other one may sound weird, but it's another expression. Obviously the result of it is that it will be considered as operating. So this expression needs to be executed first to get the result.

In this expression we find the code (ln = fis.read()) . There is another operator, it is = , which is the value assignment for a variable. An operand is ln , the variable (this operator only accepts variable on the left side) and the other, which is the value that will be attributable to the variable is also an (other) expression. The result of this expression is that it will be assigned to the variable. So it needs to be run first.

Maybe you were surprised that the assignment is being used as an expression. But it is an expression, it is not a command. So it can be used anywhere that expects an expression. Parentheses are required to avoid some problem of operator precedence or associativity.

This expression takes a variable that contains an object and applies the . operator that allows you to invoke a member of the object, in this case it is a method called read() . It returns -1 if you have nothing else to read. The return of this method will be the result that will be assigned to ln and that, finally, will be used to compare with the literal -1 , producing the expected boolian by while .

This could have been written like this:

ln = fis.read()
while ( ln != -1 ) {  
    st += (char)ln;
    ln = fis.read() //repetição de código que deveria ser canônico
}

Or

while (true) {  
    ln = fis.read()
    if (ln != -1) { //if horroroso
        break;
    }
    st += (char)ln;
}
    
12.11.2015 / 03:43
6

Basically you are reading a text file character by character and concatenating it to a string. This method FileInputStream#read() returns -1 when the end of the file is reached, so what you are doing is to go through all the content, character by character as long as there is data to be read.

Because FileInputStream implements the < strong> AutoCloseable , you can use try- with-resources and dispense the call to the close method:

File arquivo = new File("ip.txt");
try (FileInputStream fis = new FileInputStream(arquivo)) {
    while ((ln = fis.read()) != -1) {
        st += (char) ln;
    }
} // O que seria o "close" do FileInputStream.

If there is no need to do something special with each character read (in the code, it is only being concatenated to a string), you can choose to read the entire contents of the file at once without a loop :

String content = new String(Files.readAllBytes(Paths.get("ip.txt")), StandardCharsets.UTF_8);
System.out.println(content);
    
12.11.2015 / 03:57