error creating FileOutputStream file using Stream API and Lambda expressions

Viewed 22

I am trying to create a file through the FileOutputStream stream, if I use the for-loop, it does it correctly:

public class EjemploFileOutputStream {

/**
 * @param args
 */
public static void main(String[] args) {
    
    OutputStream fOut = null;
    
    try {
        fOut = new FileOutputStream("primero.dat");
        for(int i = 0; i < 1000; i++) {
            fOut.write(i);
        }           
    } catch (FileNotFoundException e) {         
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (fOut != null)
            try {
                fOut.close();
            } catch (IOException e) {                   
                e.printStackTrace();
            }
    }
    
    

}

}

but using the Stream API and Lambda expressions, it gives me an error

this would be the code:

public class EjemploFileOutputStream {

static OutputStream fOut2 = null;


/**
 * @param args
 * @throws FileNotFoundException 
 */
public static void main(String[] args) throws FileNotFoundException {
  
    List<Number> cantidades = Arrays.asList(10, 20, 30, 40, 50);
    try {
        fOut2 = new FileOutputStream("primero3.dat");
    } catch (FileNotFoundException e1) {            
        e1.printStackTrace();
    }
    cantidades.stream().map(cantidad->cantidad.intValue()).forEach(cantidad -> {
        try {
            fOut2.write(cantidad);

        } catch (IOException e1) {
            e1.printStackTrace();
        } finally {
            if (fOut2 != null)
                try {
                    fOut2.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }

    });
}

}

the error trace in the console (Eclipse):

the error trace in the console (Eclipse)

the sequence in debugger mode: The first value of the list enters apparently OK , cantidad=10

first value of the list enters apparently

The next value in the list enters apparently OK, cantidad=20:

next value in the list enters apparently OK

but when processing it, it catches the error exception:

it catches the error exception

I am trying different options, but while I wanted to know could any of you know how to avoid this error

1 Answers

The problem is that you have the finally block to close the OutputStream on the inside of the stream block, where it gets executed after each iteration. You need to move the finally to after the catch block instead, and it will work:

public class EjemploFileOutputStream {
    static OutputStream fOut2 = null;
    
    /**
     * @param args
     * @throws FileNotFoundException 
     */
    public static void main(String[] args) throws FileNotFoundException {
      
        List<Number> cantidades = Arrays.asList(1, 2, 3, 4, 5);
        try {
            fOut2 = new FileOutputStream("primero3.dat");
            cantidades.stream().map(cantidad->cantidad.intValue()).forEach(cantidad -> {
                try {
                    fOut2.write(cantidad);
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
        
            });
        } catch (FileNotFoundException e1) {            
            e1.printStackTrace();
        } finally {
            if (fOut2 != null)
                try {
                    fOut2.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }
}

Note that you can also clean up the code by using the try-with construct, which takes care of closing the stream automatically:

public class EjemploFileOutputStream {
    
    /**
     * @param args
     * @throws FileNotFoundException 
     */
    public static void main(String[] args) throws FileNotFoundException {
      
        List<Number> cantidades = Arrays.asList(1, 2, 3, 4, 5);
        try (OutputStream fOut2 = new FileOutputStream("primero3.dat")){
            cantidades.stream().map(cantidad->cantidad.intValue()).forEach(cantidad -> {
                try {
                    fOut2.write(cantidad);
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
        
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

One last thing. Using an IntStream instead of a List removes the need to call stream() or the map() call:

public class EjemploFileOutputStream {
    
    /**
     * @param args
     * @throws FileNotFoundException 
     */
    public static void main(String[] args) throws FileNotFoundException {
      
        IntStream cantidades = IntStream.of(10, 20, 30, 40, 50);
        try (OutputStream fOut2 = new FileOutputStream("primero3.dat")){
            cantidades.forEach(cantidad -> {
                try {
                    fOut2.write(cantidad);
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Related