用 sax 解析器的 endElement 覆盖 HashMap 变量
Overrided HashMap variable with endElement of sax parser
我一直在使用 SAX 解析器从 Excel sheet 中读取数据,但我遇到了问题。我需要保存前四行然后迭代其他行,但是当我将初始行保存到不同的 HashMap
时,这些被覆盖,我在所有结构中获得相同的字段。
这是endElement
方法的代码:
public void endElement(String uri, String localName, String name)
throws SAXException {
String cellValue = null;
//String thisStr = null;
// v => contents of a cell
if ("v".equals(name)) {
// Process the value contents as required.
// Do now, as characters() may be called more than once
switch (nextDataType) {
case BOOL:
char first = value.charAt(0);
cellValue=first == '0' ? "false" : "true";
break;
case ERROR:
cellValue=new String(value.toString());
break;
case FORMULA:
// A formula could result in a string value,
// so always add double-quote characters.
cellValue=new String(value.toString());
break;
case INLINESTR:
XSSFRichTextString rtsi = new XSSFRichTextString(value.toString());
cellValue=new String(rtsi.toString());
break;
case SSTINDEX:
String sstIndex = value.toString();
try {
int idx = Integer.parseInt(sstIndex);
XSSFRichTextString rtss = new XSSFRichTextString(sharedStringsTable.getEntryAt(idx));
cellValue=new String(rtss.toString());
}
catch (NumberFormatException ex) {
System.out.println("Failed to parse SST index '" + sstIndex + "': " + ex.toString());
}
break;
case NUMBER:
String n = value.toString();
if (this.formatString != null && n.length() > 0){
cellValue = formatter.formatRawCellContents(Double.parseDouble(n), this.formatIndex, this.formatString);
}
else{
cellValue=new String(n);
}
break;
default:
cellValue="";
break;
}
// Output after we've seen the string contents
// Emit commas for any fields that were missing on this row
if (lastColumnNumber == -1) {
lastColumnNumber = 0;
}
// Might be the empty string.
rowValues.put(cellCoordinate,cellValue);
// Update column
if (thisColumn > -1)
lastColumnNumber = thisColumn;
} else if ("row".equals(name)) {
// We're onto a new row
databaseServices.archiveAcquisition(rowValues,rowCount);
//Clear the structure used to store row data
rowValues.clear();
rowCount++;
lastColumnNumber = -1;
}
}
和archiveAcquisition
方法:
@Override
public void archiveAcquisition(HashMap<String,String> actualRowValues, int index) {
switch(index){
case 1:
firstRowValues=actualRowValues;
break;
case 2:
secondRowValues=actualRowValues;
break;
case 3:
thirdRowValues=actualRowValues;
break;
default:
//CREATE ALL THE OBJECT TO STORE THE ACQUISITION
//Create shift object, if it already exists, it'll be updated
Shift shift=new Shift(actualRowValues.get(ExcelMappingCoordinate.shift.getCoordinate()+index));
shiftServices.create(shift);
我不明白问题出在哪里,SAX 库的隐藏行为?我也尝试过将外部对象存储在哪里,但问题是一样的。
问题是重复添加了同一个 HashMap 对象 (rowValues),在中间清除了它。
一个快速的破解方法是每次都制作地图的副本:
databaseServices.archiveAcquisition(new HashMap<>(rowValues),rowCount);
最好从一个新的 rowValues
开始,也许作为局部变量。
我一直在使用 SAX 解析器从 Excel sheet 中读取数据,但我遇到了问题。我需要保存前四行然后迭代其他行,但是当我将初始行保存到不同的 HashMap
时,这些被覆盖,我在所有结构中获得相同的字段。
这是endElement
方法的代码:
public void endElement(String uri, String localName, String name)
throws SAXException {
String cellValue = null;
//String thisStr = null;
// v => contents of a cell
if ("v".equals(name)) {
// Process the value contents as required.
// Do now, as characters() may be called more than once
switch (nextDataType) {
case BOOL:
char first = value.charAt(0);
cellValue=first == '0' ? "false" : "true";
break;
case ERROR:
cellValue=new String(value.toString());
break;
case FORMULA:
// A formula could result in a string value,
// so always add double-quote characters.
cellValue=new String(value.toString());
break;
case INLINESTR:
XSSFRichTextString rtsi = new XSSFRichTextString(value.toString());
cellValue=new String(rtsi.toString());
break;
case SSTINDEX:
String sstIndex = value.toString();
try {
int idx = Integer.parseInt(sstIndex);
XSSFRichTextString rtss = new XSSFRichTextString(sharedStringsTable.getEntryAt(idx));
cellValue=new String(rtss.toString());
}
catch (NumberFormatException ex) {
System.out.println("Failed to parse SST index '" + sstIndex + "': " + ex.toString());
}
break;
case NUMBER:
String n = value.toString();
if (this.formatString != null && n.length() > 0){
cellValue = formatter.formatRawCellContents(Double.parseDouble(n), this.formatIndex, this.formatString);
}
else{
cellValue=new String(n);
}
break;
default:
cellValue="";
break;
}
// Output after we've seen the string contents
// Emit commas for any fields that were missing on this row
if (lastColumnNumber == -1) {
lastColumnNumber = 0;
}
// Might be the empty string.
rowValues.put(cellCoordinate,cellValue);
// Update column
if (thisColumn > -1)
lastColumnNumber = thisColumn;
} else if ("row".equals(name)) {
// We're onto a new row
databaseServices.archiveAcquisition(rowValues,rowCount);
//Clear the structure used to store row data
rowValues.clear();
rowCount++;
lastColumnNumber = -1;
}
}
和archiveAcquisition
方法:
@Override
public void archiveAcquisition(HashMap<String,String> actualRowValues, int index) {
switch(index){
case 1:
firstRowValues=actualRowValues;
break;
case 2:
secondRowValues=actualRowValues;
break;
case 3:
thirdRowValues=actualRowValues;
break;
default:
//CREATE ALL THE OBJECT TO STORE THE ACQUISITION
//Create shift object, if it already exists, it'll be updated
Shift shift=new Shift(actualRowValues.get(ExcelMappingCoordinate.shift.getCoordinate()+index));
shiftServices.create(shift);
我不明白问题出在哪里,SAX 库的隐藏行为?我也尝试过将外部对象存储在哪里,但问题是一样的。
问题是重复添加了同一个 HashMap 对象 (rowValues),在中间清除了它。
一个快速的破解方法是每次都制作地图的副本:
databaseServices.archiveAcquisition(new HashMap<>(rowValues),rowCount);
最好从一个新的 rowValues
开始,也许作为局部变量。