最近我遇到了一个问题,具体情况如下:
您正在使用SQL Server Integration Services(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");
}
}
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);
}
}
当您运行该程序包时,您会发现指定文件夹中的所有CSV文件都将被转换为UTF8格式,其中包含字节顺序标记。
这样,您的外部进程就能够使用导出的CSV文件了。
如果您只想要特定的文件夹...将该变量发送到脚本任务并使用下面的命令。
string sPath;
sPath=Dts.Variables["User::v_ExtractPath"].Value.ToString();
string pattern = "*.txt";
string[] files = Directory.GetFiles(sPath);
我希望您能够受益!