DataPort's Text File Import Byte Order Mark Requirement
Ever since DataPort was released I've heard people grumble about the requirement that text files include a Byte Order Mark. Eventually, I too found it annoying. Might as well create a new data port import formatter that solves the problem.
The easiest solution is to add a Byte Order Mark when there isn't one. That takes 4-5 lines of code, so rather simple. Once that's been done Data Port needs to be updated to reflect the new option and we're all set.
Feel free to use my copy. Or follow the instructions to recreate this yourself.
Here's how I accomplished this....
First I decompiled the out-of-the-box Data Port Import Formatter (ImportDataFormatterTab) using IL Spy, copying the contents to my clipboard:
Next I launched Visual Studio and created a new class library project named "ImportDataFormatterTabAutoBOM":
I removed the default class Visual Studio gave me:
I added a new class named "ImportDataFormatterTabAutoBOM":
I replaced the content of the new class file with the content from IL Spy and immediately add "AutoBOM" to the class name:
I removed unnecessary references and imported those required:
Two errors have to be fixed before continuing:
Replace the assert with code which shows the assert message via the windows forms message box:
if (this.m_reader == null) { System.Windows.Forms.MessageBox.Show("m_reader == null. StartImport must be called prior to calling GetNextItem"); return null; }
Replace the Browse method as follows:
public string Browse(Form parentForm, string searchPrefix, Point bottomRight, Dictionary<AdditionalDataKeys, DescriptiveData> additionalData) { string fileName = searchPrefix; using ( OpenFileDialog ofd = new OpenFileDialog() ) { if ( ofd.ShowDialog() == DialogResult.OK ) { this.VerifyBOM(fileName = ofd.FileName); } } return fileName; //string text = Helper.BrowseForFileOpen(parentForm, searchPrefix, "Text Files|*.txt|All Files|*.*"); //this.VerifyBOM(text); //return text; }
Add code to the VerifyBOM method that adds a BOM if it's not detected in the file:
private void VerifyBOM(string fileName) { if (!string.IsNullOrWhiteSpace(fileName)) { if (this.m_fileHasBom.HasValue && (string.IsNullOrWhiteSpace(this.m_fileName) || this.m_fileName == fileName)) { this.m_fileHasBom = new bool?(this.m_fileHasBom.Value); } else { if (!HP.HPTRIM.Framework.IO.IOHelper.FileHasBOM(fileName)) { // no byte order mark.... let's fix that and try again String fileContent = System.IO.File.ReadAllText(fileName); using (TextWriter writer = File.CreateText(fileName)) { writer.Write("\xfeff"); writer.Write(fileContent); writer.Close(); } } this.m_fileHasBom = new bool?(HP.HPTRIM.Framework.IO.IOHelper.FileHasBOM(fileName)); } if (!this.m_fileHasBom.Value) { throw new Exception(TrimApplicationBase.GetMessage(MessageIds.dp_err_noBOM, fileName)); } } }
Compile the solution, open windows explorer to the debug output folder, and copy the output file to the clipboard:
Past the compiled class library into the Content Manager installation directory:
Navigate to the AppData directory for Data Port preferences:
Edit the Import Data Formatters configuration file and duplicate the existing Import Formatter section:
<DataFormatterDefinition> <DisplayName>Tab Delimited</DisplayName> <AssemblyName>HP.HPTRIM.DataPort.Common.dll</AssemblyName> <ClassName>HP.HPTRIM.DataPort.Framework.DataFormatters.ImportDataFormatterTab</ClassName> </DataFormatterDefinition>
Tweak the values to reflect what was just built in the class library:
<ArrayOfDataFormatterDefinition xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <DataFormatterDefinition> <DisplayName>Tab Delimited</DisplayName> <AssemblyName>HP.HPTRIM.DataPort.Common.dll</AssemblyName> <ClassName>HP.HPTRIM.DataPort.Framework.DataFormatters.ImportDataFormatterTab</ClassName> </DataFormatterDefinition> <DataFormatterDefinition> <DisplayName>Tab Delimited (Auto BOM)</DisplayName> <AssemblyName>ImportDataFormatterTabAutoBOM.dll</AssemblyName> <ClassName>HP.HPTRIM.DataPort.Framework.DataFormatters.ImportDataFormatterTabAutoBOM</ClassName> </DataFormatterDefinition> </ArrayOfDataFormatterDefinition>
Launch DataPort and use the new formatter: