如何在Java中读取带有^ M行字符的文件时解决问题

问题描述 投票:1回答:1

我是Java的新手,下面是我的Java文件。当我退出这个Java程序时,出现了java.lang.IndexOutOfBoundsException: Index: 4, Size: 4这样的异常。

@Service
public class TEImporter{
    private final static Logger log = LoggerFactory.getLogger(TEImporter.class);

    //Tabellenname auf Spalten in der Tabelle
    Map < String, List < ColumnData >> columnDataCache = new HashMap < > ();

    private final JdbcTemplate jdbcTemplate;

    public TEImporter(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
    /**
     * Be careful: Deletes all the data from the given table.
     * @param tableName the name of the table the data of which should be deleted.
     */
    public void deleteTableData(String tableName) {
        jdbcTemplate.update("delete from " + tableName);
    }

    public void importFile(BufferedReader bufferedReader, String tableName, String fileName,
        Map < Integer, Function < String, String >> COLUMN_TYPE_MAPPINGS,
        Map < String, Function < String, String >> COLUMN_NAME_MAPPINGS) throws IOException {
        importFile(bufferedReader, tableName, fileName, COLUMN_TYPE_MAPPINGS, COLUMN_NAME_MAPPINGS, new ArrayList < > ());
    }

    public void importFile(BufferedReader bufferedReader, String tableName, String fileName,
        Map < Integer, Function < String, String >> COLUMN_TYPE_MAPPINGS,
        Map < String, Function < String, String >> COLUMN_NAME_MAPPINGS,
        List < FixedValue > fixedValues) throws IOException {
        String firstLine = bufferedReader.readLine();
        List < String > headings = Splitter
            .on(";")
            .trimResults()
            .splitToList(firstLine)
            .stream()
            .map(str - > str.replace("XXX-", ""))
            .map(str - > str.replace("-", ""))
            .map(str - > str.replaceAll("\\.", ""))
            .map(str - > str.equals("ORDER") ? "ORDERID" : str) // to work for ORDER columns in CSV files
            .map(String::toUpperCase)
            .filter(str - > str.length() > 0) // to suppress empty columns at the end of the line
            .collect(toList());

        List < ColumnData > columnData = getColumns(tableName)
            .stream()
            .filter(cd - > !cd.getName().equals("SYSTEM_INSERTED_AT") && !cd.getName().equals("DATEINAME"))
            .collect(toList());

        List < String > columnNames = columnData.stream().map(ColumnData::getName).collect(toList());

        //Nur Spalten, die sowohl in der Datenbank als auch in der CSV-Datei enthalten sind, werden verarbeitet
        List < String > matchingColumns = intersection(headings, columnNames);

        List < String > columnsInDbButNotInCsv = subtract(columnNames, headings);
        columnsInDbButNotInCsv = subtract(columnsInDbButNotInCsv, fixedValues.stream().map(f - > f.getColumnName()).collect(toList()));
        columnsInDbButNotInCsv.forEach(s - > log.warn("Spalte '" + s + "' in Datenbank vorhanden, wird jedoch nicht in der CSV bereitgestellt"));

        //Index to columnData
        Map < Integer, ColumnData > columnsToInsert = new HashMap < > ();

        for (String column: matchingColumns) {
            columnsToInsert.put(headings.indexOf(column), columnData.stream().filter(cd - > cd.getName().equals(column)).findAny().get());
        }

        int counter = 0;
        while (true) {
            String line = bufferedReader.readLine();
            if (line == null) {
                break;
            }

            counter++;

            List < String > columns = Splitter
                .on(";")
                .splitToList(line);

            StringBuilder columnSqlFragment = new StringBuilder();
            StringBuilder valuesSqlFragment = new StringBuilder();

            for (int i = 0; i < headings.size(); i++) {
                String columnName = headings.get(i);
                String value = columns.get(i);


                if (!columnsToInsert.containsKey(i)) {
                    continue;
                }

                if (i != 0) {
                    columnSqlFragment.append(", ");
                    valuesSqlFragment.append(", ");
                }

                int columnType = columnsToInsert.get(i).getType();
                java.util.function.Function < String, String > mapping = COLUMN_NAME_MAPPINGS.containsKey(columnName) ? COLUMN_NAME_MAPPINGS.get(columnName) : COLUMN_TYPE_MAPPINGS.get(columnType);
                if (mapping == null) {
                    throw new IllegalStateException("Kein Mapping für Spalte mit dem Namen " + columnName + " aus der Tabelle " + tableName + " mit Typ " + columnType + " gefunden");
                }

                columnSqlFragment.append("\"" + columnName + "\"");
                valuesSqlFragment.append(mapping.apply(value));
            }

            for (FixedValue fv: fixedValues) {
                columnSqlFragment.append(", ");
                columnSqlFragment.append(fv.getColumnName());

                valuesSqlFragment.append(", ");
                valuesSqlFragment.append(fv.getValueSQLFragment());
            }

            String sql = "insert into " + tableName + " (SYSTEM_INSERTED_AT, DATEINAME, " + columnSqlFragment + ") VALUES (sysdate, '" + fileName + "', " + valuesSqlFragment + ")";
            log.info("Insert values to table" + sql);
            jdbcTemplate.update(sql);
        }

        log.info(counter + " Zeilen erfolgreich eingelesen.");
    }

    private List < ColumnData > getColumns(String tableName) {
        if (columnDataCache.containsKey(tableName)) {
            return columnDataCache.get(tableName);
        }

        List < ColumnData > result = new ArrayList < > ();
        try (Connection connection = jdbcTemplate.getDataSource().getConnection()) {
            ResultSet rs = connection.getMetaData().getColumns(null, null, tableName, null);

            boolean anyResults = false;
            while (rs.next()) {
                anyResults = true;
                String columnName = rs.getString(4).toUpperCase();
                int type = rs.getInt(5);
                result.add(new ColumnData(columnName, type));
            }
            columnDataCache.putIfAbsent(tableName, result);

            if (!anyResults) {
                throw new RuntimeException("Could not retrieve columns for table " + tableName);
            }

            return result;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

我已经找出我出错的原因。

当我在普通文本编辑器中打开此csv文件时,我看不到数据有任何问题。但是,当我尝试在Ubuntu的VI编辑器中打开文件时,我可以看到存在^ M行字符,这是导致异常的原因。当我编辑文件并删除^ M并再次运行程序时,它的工作正常,并将数据插入表中。

这是Windows PC上的换行符,在基于VIM的编辑器中被读取为^ M,我从Windows获取此文件,并在ubuntu中阅读。

下面是我文件中的数据,在这里我可以看到^ M,它位于索引4。

enter image description here

我在Java中看到replaceAll函数,但我不知道如何使用它以及我到底需要在哪里使用它。我只需要删除^M并读取文件即可。请帮助

我是Java的新手,下面是我的Java文件。当我退出这个Java程序时,我得到一个异常,如java.lang.IndexOutOfBoundsException:索引:4,大小:4. @Service公共类...

java ubuntu file-read control-m
1个回答
0
投票

只需将您的while循环更改为此,就可以最小化对代码的更改,以实现您的情况下的全部替换方法;

© www.soinside.com 2019 - 2024. All rights reserved.