Issue
I have looked at two different ways of reading MultipartFile.
Using the forEach method works, but I can not break out of the forEach loop. I understand I can throw exceptions in the forEach loop to exit the loop but from what I have read it is not good practice.
private boolean validateFile(MultipartFile idFile) {
AtomicBoolean validated = new AtomicBoolean(true);
try {
InputStream inputStream = idFile.getInputStream();
new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))
.lines()
.forEach(
line -> {
line = line.trim();
if (line.length() != 3 || !line.matches("^[a-zA-Z0-9]*$")) {
validated.set(false);
}
}
);
} catch (Exception ex) {
validated.set(false);
}
return validated.get();
}
The problem with using forEach is that I can not break out of the loop after executing validated.set(false)
I have also tried using the method below in order to use breaks
private boolean validateFile(MultipartFile idFile) {
boolean validated = true;
InputStream inputStream = null;
BufferedReader br = null;
try {
inputStream = idFile.getInputStream();
br = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
String line;
while ((line = br.readLine()) != null) {
line = line.trim();
if (line.length() != 3 || !line.matches("^[a-zA-Z0-9]*$")) {
validated = false;
break;
}
}
} catch (Exception e) {
validated = false;
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
return validated;
}
The problem I am facing with the method above is that throw new RuntimeException(e);
in the finally block causing sonar errors.
How can I read MultipartFile and being able to break out of the loop? I also don't want to use throws in the finally block since it causes sonar errors.
Solution
For your stream-based solution, you can use Stream.noneMatch(). On the first element, which matches the predicate it will stop evaluating the rest of the elements in the stream and return false.
private boolean validateFile(MultipartFile idFile) {
try {
InputStream inputStream = idFile.getInputStream();
return new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))
.lines()
.noneMatch(line -> line.length() != 3 || !line.matches("^[a-zA-Z0-9]*$"));
} catch (Exception ex) {
return false;
}
}
For the loop based solution, you can use try-with-resouces statement. It will automatically close the resources for you, so you don't need to do it manually.
private boolean validateFile(MultipartFile idFile) {
boolean validated = true;
try (InputStream inputStream = idFile.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
String line;
while ((line = br.readLine()) != null) {
line = line.trim();
if (line.length() != 3 || !line.matches("^[a-zA-Z0-9]*$")) {
validated = false;
break;
}
}
} catch (IOException exc) {
return false;
}
return validated;
}
Answered By - Chaosfire
Answer Checked By - David Goodson (JavaFixing Volunteer)