Implemented and tested a more robust report type parsing

This commit is contained in:
U-BASIS\dsmyda 2019-12-04 14:25:46 -05:00
parent 9130076558
commit ed1c2ad31c

View File

@ -52,7 +52,11 @@ final class XRYFileReader implements AutoCloseable {
//Assume UTF_16LE
private static final Charset CHARSET = StandardCharsets.UTF_16LE;
//Assume all XRY reports have the type on the 3rd line.
//Assume the header begins with 'xry export'.
private static final String START_OF_HEADER = "xry export";
//Assume all XRY reports have the type on the 3rd line
//relative to the start of the header.
private static final int LINE_WITH_REPORT_TYPE = 3;
//Assume all headers are 5 lines in length.
@ -91,8 +95,12 @@ final class XRYFileReader implements AutoCloseable {
reader = Files.newBufferedReader(xryFile, CHARSET);
xryFilePath = xryFile;
//Advance the reader to the start of the first XRY entity.
for (int i = 0; i < HEADER_LENGTH_IN_LINES; i++) {
//Advance the reader to the start of the header.
advanceToHeader(reader);
//Advance the reader past the header to the start
//of the first XRY entity.
for (int i = 1; i < HEADER_LENGTH_IN_LINES; i++) {
reader.readLine();
}
@ -298,8 +306,11 @@ final class XRYFileReader implements AutoCloseable {
*/
private static Optional<String> getType(Path file) throws IOException {
try (BufferedReader reader = Files.newBufferedReader(file, CHARSET)) {
//Header may not start at the beginning of the file.
advanceToHeader(reader);
//Advance the reader to the line before the report type.
for (int i = 0; i < LINE_WITH_REPORT_TYPE - 1; i++) {
for (int i = 1; i < LINE_WITH_REPORT_TYPE - 1; i++) {
reader.readLine();
}
@ -310,4 +321,51 @@ final class XRYFileReader implements AutoCloseable {
return Optional.empty();
}
}
/**
* Advances the reader to the start of the header. The XRY Export header may
* not be the first n lines of the file. It may be preceded by new lines or
* white space.
*
* This function will consume the first line of the header, which will be
* 'XRY Export'.
*
* @param reader BufferedReader pointing to the xry file
* @throws IOException if an I/O error occurs
*/
private static void advanceToHeader(BufferedReader reader) throws IOException {
String line;
if((line = reader.readLine()) == null) {
return;
}
String normalizedLine = line.trim().toLowerCase();
if (normalizedLine.equals(START_OF_HEADER)) {
return;
}
/**
* The first line may have 0xFFFE BOM prepended to it, which will cause
* the equality check to fail. This bit a logic will try to remove those
* bytes and attempt another check.
*/
byte[] normalizedBytes = normalizedLine.getBytes(CHARSET);
if (normalizedBytes.length > 2) {
normalizedLine = new String(normalizedBytes, 2,
normalizedBytes.length - 2, CHARSET);
if (normalizedLine.equals(START_OF_HEADER)) {
return;
}
}
/**
* All other lines will need to match completely.
*/
while ((line = reader.readLine()) != null) {
normalizedLine = line.trim().toLowerCase();
if (normalizedLine.equals(START_OF_HEADER)) {
return;
}
}
}
}