Unity中使用ExcelDataReader实现Excel文件读取功能的坑

首先,这次在Unity中实现读取Excel文件(.xls .xlsx)功能是通过这个开源.Net库:https://github.com/ExcelDataReader/ExcelDataReader,感谢ExcelDataReader的作者和contributors!写这篇脱坑文时的ExcelDataReader版本是3.6.0,使用的Unity版本是2019.4.12f1。可以看到,这个库的Github上Release中提供的是NuGet包和源码,当然,自行源码编译出dll使用也是可以的,或者解包nupkg,但其实在Unity中也是可以使用NuGet管理第三方库的,在Unity中通过NuGet安装ExcelDataReader的完整过程可以参考这里:https://qiita.com/tani-shi/items/b155858f07c7350d3e2d,用到的Unity NuGet插件是这个https://github.com/GlitchEnzo/NuGetForUnity/releases,同样感谢做和贡献者们!一切准备就绪后,开始码代码:

        FileStream stream = File.Open("d:\\test.xlsx", FileMode.Open, FileAccess.Read, FileShare.Read);
        IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
        Debug.Log(excelReader.IsClosed);

        DataSet result = excelReader.AsDataSet();
        int columnNum = result.Tables[0].Columns.Count;
        int rowNum = result.Tables[0].Rows.Count;

很简单的一段代码,测试下功能,在Unity Editor中运行一切正常,顺利读取出了test.xlsx中的信息,结果在Build了下Standalone执行程序后,再试,神奇的事情发生了,ExcelReaderFactory.CreateOpenXmlReader返回了null!

打开Development Build,再次运行,查看异常信息,发现是这么个错:

NotSupportedException: Encoding 1252 data could not be found. Make sure you have correct international codeset assembly installed and enabled.
at System.Text.Encoding.GetEncoding (System.Int32 codepage) [0x0023f] in <9577ac7a62ef43179789031239ba8798>:0
at ExcelDataReader.ExcelReaderConfiguration..ctor () [0x00000] in :0
at ExcelDataReader.ExcelReaderFactory.CreateOpenXmlReader (System.IO.Stream fileStream, ExcelDataReader.ExcelReaderConfiguration configuration) [0x00003] in :0
at Test.ReadExcel (System.String filePath) [0x0000b] in J:\Projects\Unity2019\BigDataVisualization\Assets\Scripts\Test.cs:35
at Test.Read() [0x0009d] in J:\Projects\Unity2019\BigDataVisualization\Assets\Scripts\Test.cs:27
at UnityEngine.Events.InvokableCall.Invoke () [0x00010] in C:\buildslave\unity\build\Runtime\Export\UnityEvent\UnityEvent.cs:166
at UnityEngine.Events.UnityEvent.Invoke () [0x00022] in C:\buildslave\unity\build\Runtime\Export\UnityEvent\UnityEvent\UnityEvent_0.cs:58
at UnityEngine.UI.Button.Press () [0x00027] in D:\Program Files\UnityEditors\2019.4.12f1\Editor\Data\Resources\PackageManager\BuiltInPackages\com.unity.ugui\Runtime\UI\Core\Button.cs:68
at UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) [0x00010] in D:\Program Files\UnityEditors\2019.4.12f1\Editor\Data\Resources\PackageManager\BuiltInPackages\com.unity.ugui\Runtime\UI\Core\Button.cs:110
at UnityEngine.EventSystems.ExecuteEvents.Execute (UnityEngine.EventSystems.IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) [0x00001] in D:\Program Files\UnityEditors\2019.4.12f1\Editor\Data\Resources\PackageManager\BuiltInPackages\com.unity.ugui\Runtime\EventSystem\ExecuteEvents.cs:50
at UnityEngine.EventSystems.ExecuteEvents.Execute[T] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.ExecuteEvents+EventFunction1[T1] functor) [0x0006c] in D:\Program Files\UnityEditors\2019.4.12f1\Editor\Data\Resources\PackageManager\BuiltInPackages\com.unity.ugui\Runtime\EventSystem\ExecuteEvents.cs:261 UnityEngine.DebugLogHandler:Internal_LogException(Exception, Object) UnityEngine.DebugLogHandler:LogException(Exception, Object) UnityEngine.Logger:LogException(Exception, Object) UnityEngine.Debug:LogException(Exception) UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction1) (at D:\Program Files\UnityEditors\2019.4.12f1\Editor\Data\Resources\PackageManager\BuiltInPackages\com.unity.ugui\Runtime\EventSystem\ExecuteEvents.cs:265)
UnityEngine.EventSystems.StandaloneInputModule:ReleaseMouse(PointerEventData, GameObject) (at D:\Program Files\UnityEditors\2019.4.12f1\Editor\Data\Resources\PackageManager\BuiltInPackages\com.unity.ugui\Runtime\EventSystem\InputModules\StandaloneInputModule.cs:195)
UnityEngine.EventSystems.StandaloneInputModule:ProcessMousePress(MouseButtonEventData) (at D:\Program Files\UnityEditors\2019.4.12f1\Editor\Data\Resources\PackageManager\BuiltInPackages\com.unity.ugui\Runtime\EventSystem\InputModules\StandaloneInputModule.cs:644)
UnityEngine.EventSystems.StandaloneInputModule:ProcessMouseEvent(Int32) (at D:\Program Files\UnityEditors\2019.4.12f1\Editor\Data\Resources\PackageManager\BuiltInPackages\com.unity.ugui\Runtime\EventSystem\InputModules\StandaloneInputModule.cs:552)
UnityEngine.EventSystems.StandaloneInputModule:ProcessMouseEvent() (at D:\Program Files\UnityEditors\2019.4.12f1\Editor\Data\Resources\PackageManager\BuiltInPackages\com.unity.ugui\Runtime\EventSystem\InputModules\StandaloneInputModule.cs:532)
UnityEngine.EventSystems.StandaloneInputModule:Process() (at D:\Program Files\UnityEditors\2019.4.12f1\Editor\Data\Resources\PackageManager\BuiltInPackages\com.unity.ugui\Runtime\EventSystem\InputModules\StandaloneInputModule.cs:289)
UnityEngine.EventSystems.EventSystem:Update() (at D:\Program Files\UnityEditors\2019.4.12f1\Editor\Data\Resources\PackageManager\BuiltInPackages\com.unity.ugui\Runtime\EventSystem\EventSystem.cs:377)

(Filename: <9577ac7a62ef43179789031239ba8798> Line: 0)

搜索这个错误,很快查到了Unity论坛上的这个帖子:https://forum.unity.com/threads/solved-application-crash-with-notsupportedexception.415325/,大意是Editor中带了全编码的Assembly,而出Player时默认不会带入,应该是为了减小体积吧,也可以理解。解决方法就是手动把Unity Editor自带的dll拷今项目里,这个1252需要的是I18N.dll和I18N.West.dll,本地搜索Editor安装文件夹,找到了这里:“D:\Program Files\UnityEditors\2019.4.12f1\Editor\Data\MonoBleedingEdge\lib\mono\unity”,拷贝两个dll到项目Assets里后,重新Build运行,测试,本以为应该没问题了,结果暴出了本篇记录的最终boss坑:“InvalidProgramException: Invalid IL code in I18N.Common.Manager:get_PrimaryManager (): IL_0000: ret”,又是一通搜索,最终查到了Unity Answers有人问到的同样问题:https://answers.unity.com/questions/1756912/invalid-il-code-in-build.html,看了下终于发现了出坑要领,原来要拷贝的dll应该是“D:\Program Files\UnityEditors\2019.4.12f1\Editor\Data\MonoBleedingEdge\lib\mono\unityjit”这个文件夹中的(别问为什么,我也不知道!),于是照做,重考两个dll,再次Build,测试,这下终于ok了!

博主友情提示:

如您在评论中需要提及如QQ号、电子邮件地址或其他隐私敏感信息,欢迎使用>>博主专用加密工具v3<<处理后发布,原文只有博主可以看到。