当前位置: 首页 > 知识库问答 >
问题:

读取excel时如何跳过一些无效字符

柳英资
2023-03-14

使用poi读取某些excel失败,遇到此错误

Caused by: org.xml.sax.SAXParseException; systemId: file://; lineNumber: 105; columnNumber: 147342; An invalid XML character (Unicode: 0xffff) was found in the element content of the document.
    at java.xml/com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:204)
    at java.xml/com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:178)
    at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:400)

xl/sharetrings.xml,存在

如何能成功读取并忽略这些无效字符?

aaa <ffff> bbb ==> aaa bbb

共有2个答案

弘烨烁
2023-03-14

在我下面的例子中,文件都有无效字符

xl/sharedStrings.xml
xl/worksheets/sheet1.xml
xl/worksheets/sheet8.xml

应该处理所有这些xml

opcPackage.getPartsByName(Pattern.compile("(/xl/sharedStrings.xml)|(/xl/worksheets/.+\\.xml)"))
董琦
2023-03-14

这些无效字符不应该在XML中,Excel本身不会将它们放入其中。因此,有人可能在使用Excel以外的其他东西创建该文件时做错了什么。应该避免该错误,而不是试图忽略症状。

但我知道依赖别人的工作是什么感觉,即使是在遥远的将来,也会有其他的工作要做。所以一个人需要即兴发挥。但在这种情况下,只有使用丑陋的低级方法才能做到这一点。由于XML无效,因此无法解析XML。因此,只能更换字符串。

在APACHE POI EXCEL XmlException:中是无效的XML字符,有什么方法可以预处理excel文件吗?我已经介绍过了。在这种情况下,要替换在XML中也无效的UTF-16-代理-对数字字符引用。

在下面,我将展示一个代码,如果需要,它可以更灵活地将多个其他修复操作添加到/xl/share dStrings.xml

原理是使用OPCPackage,即。xlsx压缩包,用于取出共享字符串。xml作为文本字符串。然后进行所需的更换,并将修复后的字符串放入。xml返回到OPCPackage中。然后从修复后的OPCPackage创建XSSFWorkbook,而不是从损坏的文件创建。

import java.io.*;

import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.openxml4j.opc.*;

import java.util.regex.Pattern;
import java.util.regex.Matcher;

class RepairSharedStringsTable {
    
 static String removeInvalidXmlCharacters(String string) {
  String xml10pattern = "[^"
                    + "\u0009\r\n"
                    + "\u0020-\uD7FF"
                    + "\uE000-\uFFFD"
                    + "\ud800\udc00-\udbff\udfff"
                    + "]";
  string = string.replaceAll(xml10pattern, "");
  return string;     
 }
    
 static void repairSharedStringsTable(OPCPackage opcPackage) {
  for (PackagePart packagePart : opcPackage.getPartsByName(Pattern.compile("/xl/sharedStrings.xml"))) {
   
   String sharedStrings = "";
   try (BufferedInputStream inputStream = new BufferedInputStream(packagePart.getInputStream());
        ByteArrayOutputStream sharedStringsBytes = new ByteArrayOutputStream() ) {
    byte[] buffer = new byte[1024];
    int length;
   
    while ((length = inputStream.read(buffer)) != -1) {
     sharedStringsBytes.write(buffer, 0, length);
    }
    sharedStrings = sharedStringsBytes.toString("UTF-8");
   } catch (Exception ex) {
    ex.printStackTrace();
   }
    
   System.out.println(sharedStrings);
   //sharedStrings = replaceUTF16SurrogatePairs(sharedStrings);
   sharedStrings = removeInvalidXmlCharacters(sharedStrings);
   //sharedStrings = doSomethingElse(sharedStrings);
   System.out.println(sharedStrings);

   try (BufferedOutputStream outputStream = new BufferedOutputStream(packagePart.getOutputStream()) ) {
    outputStream.write(sharedStrings.getBytes("UTF-8"));
   } catch (Exception ex) {
    ex.printStackTrace();
   }
  }  
 }

 public static void main(String[] args) throws Exception {
  try (XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream("./Excel.xlsx"))) {
   System.out.println("success");
  } catch (Exception ex) {
   System.out.println("failed");
   ex.printStackTrace();
  }

  OPCPackage opcPackage = OPCPackage.open(new FileInputStream("./Excel.xlsx"));
  repairSharedStringsTable(opcPackage);
  opcPackage.flush();
  
  try (XSSFWorkbook workbook = new XSSFWorkbook(opcPackage);
       FileOutputStream out = new FileOutputStream("./ExcelRepaired.xlsx");) {
   workbook.write(out);
   System.out.println("success");
  } catch (Exception ex) {
   System.out.println("failed");
   ex.printStackTrace();
  }
 }
}
 类似资料:
  • 问题内容: 我有一个笨拙的csv文件,我需要跳过第一行来阅读它。 我正在使用python / pandas轻松做到这一点 但是我不知道如何在Go中做到这一点。 错误: : 问题答案: 读取csv文件时跳过第一行 例如, 输出:

  • 我试图编写一个简单的复数计算器,可以计算以下表达式: 输入1:(10 30i)(90 20i) 预期输出:(100 50i) 输入2:(10 30i)-(90 20i) 预期输出:(-80 10i) 编辑:我注意到第一次前瞻读取是10而不是40(ascii值 '(' ) . 我如何解决这个问题? 我的代码: 但它总是输出“对不起,我帮不了你。”

  • 问题内容: 例如我有以下代码 并引发异常 我不在乎是否未读取某些行,但是如何跳过无效字符并继续读取行? 问题答案: 您可以通过调用来影响字符集解码处理无效输入的方式。 通常, 您永远不会直接看到对象,因为它将在后台为您创建。因此,如果需要访问它,则需要使用API​​,该API允许您直接指定(而不是仅编码名称或)。 此类API的最基本示例是: 请注意,此代码使用了Java 7类,对于早期版本,你可以

  • 问题内容: 我正在尝试使用PHP解析XML文件,但出现错误消息: 解析器错误:字符0x0超出允许的范围 我认为这是因为XML的内容所致,我认为有一个特殊的符号“☆”,我有什么想法可以解决该问题? 我也得到: 解析器错误:标签项目行中的数据过早结束 是什么导致该错误? 我正在使用。 更新: 我尝试找到错误行并将其内容粘贴为单个xml文件,它可以正常工作!所以我仍然不知道是什么使xml文件解析失败。P

  • 我的C#. Net应用程序通过使用excel公式字符串加载和读取excel工作表单元格值。 例如,excel工作表位置和选项卡名称及其单元格行/列将作为公式字符串提供。 'D:\DataX[数据.Xls]EOD'$A5级 根据上述公式-C#应用程序加载数据。Xls,并打开EOD选项卡,应读取第5行A列值。 寻找在C#中完成的最佳方式。Net框架。