SSIS - 平面文件总是ANSI从不UTF-8编码

Nei*_*eil 17 ssis flat-file utf-8

有一个非常直接的SSIS包:

  • OLE DB Source通过视图获取数据(db表nvarchar或nchar中的所有字符串列).
  • 派生列以格式化现有日期并将其添加到数据集(数据类型DT_WSTR).
  • 用于在以下各项之间拆分数据集的多播任务:
    • OLE DB命令将行更新为"已处理".
    • 平面文件目标 - 其连接管理器设置为代码页面65001 UTF-8和Unicode未选中.所有字符串列都映射到DT_WSTR.

每次我运行这个包时,在Notepad ++中打开它的ANSI平面文件,而不是UTF-8.如果我检查Unicode选项,则该文件是UCS-2 Little Endian.

我做错了什么 - 如何让平面文件成为UTF-8编码?

谢谢

小智 25

在源 - >高级编辑 - >组件属性 - >设置默认代码页65001 AlwaysUseDefaultCodePage为True

然后Source-> Advance Editor - > Input和OutPut Properties检查外部列和OutPut列中的每一列,并尽可能将CodePage设置为65001.

而已.

顺便说一句,Excel无法将文件中的数据定义为UTF - 8. Excel只是一个文件处理程序.您也可以使用记事本创建csv文件.只要你用UTF-8填写csv文件就可以了.

  • 在源 - >高级编辑器 - >组件属性 - >将默认代码页设置为65001 AlwaysUseDefaultCodePage为True,这一步帮助我节省了数小时寻找双重代码页参考错误 (2认同)

小智 5

为答案添加解释......

将CodePage设置为65001(但不检查文件源上的Unicode复选框),应生成UTF-8文件.(是的,内部的数据类型也应该是nvarchar等).

但是从SSIS生成的文件没有BOM头(字节顺序标记),因此某些程序会认为它仍然是ASCII,而不是UTF-8.我已经看到MS MS员工在MSDN上证实了这一点,并通过测试证实了这一点.

文件附加解决方案是一种解决方法 - 通过使用适当的BOM创建空白文件,然后从SSIS附加数据,BOM标头仍然存在.如果您告诉SSIS覆盖该文件,它也会丢失BOM.

感谢这里的提示,它帮助我弄清楚了上面的细节.


小智 5

我最近处理了一个问题,我们遇到了如下情况:

您正在使用 SQL Server 集成服务 (Visual Studio 2005) 开发解决方案。您正在从数据库中提取数据并尝试将结果放入 UTF-8 格式的平面文件 (.CSV) 中。该解决方案完美导出数据并将特殊字符保留在文件中,因为您使用了 65001 作为代码页。

但是,当您打开文本文件或尝试将其加载到另一个进程时,它表示该文件是 ANSI 而不是 UTF-8。如果您在记事本中打开文件并执行另存为并将编码更改为 UTF-8,那么您的外部过程就可以工作了,但这是一项繁琐的手动工作。

我发现当您指定平面文件连接管理器的代码页属性时,它会生成一个 UTF-8 文件。但是,它会生成一个 UTF-8 文件版本,该版本遗漏了我们称为字节顺序标记的内容。

因此,如果您有一个包含字符 AA 的 CSV 文件,则 UTF8 的 BOM 将为 0xef、0xbb 和 0xbf。即使文件没有 BOM,它仍然是 UTF8。

不幸的是,在一些旧的遗留系统中,应用程序搜索 BOM 以确定文件的类型。看来你的过程也在做同样的事情。

要解决此问题,您可以在脚本任务中使用以下代码段,该代码段可以在导出过程之后运行。

using System.IO;

using System.Text;

using System.Threading;

using System.Globalization;

enter code here

static void Main(string[] args)
       {
           string pattern = "*.csv";
           string[] files = Directory.GetFiles(@".\", pattern, SearchOption.AllDirectories);
           FileCodePageConverter converter = new FileCodePageConverter();
           converter.SetCulture("en-US");
           foreach (string file in files)
           {
               converter.Convert(file, file, "Windows-1252"); // Convert from code page Windows-1250 to UTF-8  
           }  
       }

class FileCodePageConverter 
  { 
      public void Convert(string path, string path2, string codepage) 
      { 
          byte[] buffer = File.ReadAllBytes(path); 
          if (buffer[0] != 0xef && buffer[0] != 0xbb) 
          { 
              byte[] buffer2 = Encoding.Convert(Encoding.GetEncoding(codepage), Encoding.UTF8, buffer); 
              byte[] utf8 = new byte[] { 0xef, 0xbb, 0xbf }; 
              FileStream fs = File.Create(path2); 
              fs.Write(utf8, 0, utf8.Length); 
              fs.Write(buffer2, 0, buffer2.Length); 
              fs.Close(); 
          } 
      } 

      public void SetCulture(string name) 
      { 
          Thread.CurrentThread.CurrentCulture = new CultureInfo(name); 
          Thread.CurrentThread.CurrentUICulture = new CultureInfo(name); 
      } 
  }
Run Code Online (Sandbox Code Playgroud)

当您运行该包时,您会发现指定文件夹中的所有 CSV 文件都将转换为包含字节顺序标记的 UTF8 格式。

这样,您的外部流程将能够使用导出的 CSV 文件。

如果您只查找特定文件夹...将该变量发送到脚本任务并使用下面的一个...

      string sPath;

      sPath=Dts.Variables["User::v_ExtractPath"].Value.ToString();

      string pattern = "*.txt";

      string[] files = Directory.GetFiles(sPath);
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助!!


Nei*_*eil 0

好的 - 似乎在SQL Server 论坛上找到了可接受的解决方法。本质上,我必须创建两个 UTF-8 模板文件,使用文件任务将它们复制到我的目的地,然后确保我是附加数据而不是覆盖。