azure-data-lake - 在 USQL 中编写自定义提取器以跳过有编码问题的行

标签 azure-data-lake u-sql

我有大量数据,涵盖数百个文件。显然,它存在一些编码问题(主要是 UTF-8,但显然有些字符无效)。根据https://msdn.microsoft.com/en-us/library/azure/mt764098.aspx如果存在编码错误,无论将静默标志设置为 true(目的只是跳过错误行),都会发生运行时错误。

因此,我需要编写一个自定义提取器。我写了一个主要是 https://blogs.msdn.microsoft.com/data_otaku/2016/10/27/a-fixed-width-extractor-for-azure-data-lake-analytics/ 中示例的简化版本。因为它只需要一行,用分隔符将其分割,然后返回 try block 中的值。如果有任何异常,我只是处理它们并继续。

不幸的是,我在 USQL 脚本本身中实际引用此提取器时遇到了问题。当我按照上述链接上的指导进行操作时,它建议在另一个程序集中编写逻辑,构建它,将其注册在 ADLS 数据库/程序集中,然后通过 REFERENCE ASSEMBLY MyExtractors; 包含它在脚本的顶部(因为这是使用的 namespace )。在下面的Using语句中,我用USING new SimpleExtractor();来调用它。如果这样做,在针对 type or namespace cannot be found 的 ADLS 服务运行脚本时会出现错误。 。此外,如果我尝试更精确并使用 USING new MyExtractors.SimpleExtractor();在 using 语句中,它会产生相同的错误,引用上面的 USING 语句。

然后我在较旧的来源中找到了其他文档 https://azure.microsoft.com/en-us/documentation/articles/data-lake-analytics-u-sql-develop-user-defined-operators/它描述了在代码隐藏文件中执行相同的操作。我删除了单独的程序集并将逻辑复制到该文件中的类中。步骤 #6 中的示例未显示任何 REFERENCE ASSEMBLY语句,但是当我运行它时,我收到一个错误,即 type or namespace name cannot be found

查看最新的发行说明,希望这里的某些内容已经过时,我唯一看到的是,如果我使用 USING声明,在实际使用自定义代码的程序集之前,我需要引用它(如第一次尝试),我就是这样。

任何人都可以提供一些关于如何在 USQL 中正确引用 UDO 的指导,或者以其他方式指示如何让运行时静默处理编码异常(并跳过它们)?

这是我的提取器本身的逻辑:

using System.Collections.Generic;
using System.IO;
using System.Text;
using Microsoft.Analytics.Interfaces;

namespace Utilities
{
    [SqlUserDefinedExtractor(AtomicFileProcessing = true)]
    public class ModifiedTextExtractor : IExtractor
    {
        //Contains the row
        private readonly Encoding _encoding;
        private readonly byte[] _row_delim;
        private readonly char _col_delim;

        public ModifiedTextExtractor()
        {
            _encoding = Encoding.UTF8;
            _row_delim = _encoding.GetBytes("\r\n");
            _col_delim = '\t';
        }

        public override IEnumerable<IRow> Extract(IUnstructuredReader input, IUpdatableRow output)
        {
            //Read the input line by line
            foreach (var current in input.Split(_row_delim))
            {
                using (var reader = new StreamReader(current, this._encoding))
                {
                    var line = reader.ReadToEnd().Trim();

                    //If there are any single or double quotes in the line, escape them
                    line = line.Replace(@"""", @"\""");

                    var count = 0;

                    //Split the input by the column delimiter
                    var parts = line.Split(_col_delim);

                    foreach (var part in parts)
                    {
                        output.Set<string>(count, part);
                        count += 1;
                    }
                }
                yield return output.AsReadOnly();
            }
        }
    }
}

以及我如何尝试在 USQL 语句中使用它的片段(将其注册为程序集之后):

REFERENCE ASSEMBLY [Utilities];

CREATE VIEW MyView AS ...
USING new Utilities.ModifiedTextExtractor();

谢谢!

最佳答案

您遇到了 View 无法引用自定义代码的问题。在 U-SQL 中,所有对象都需要包含其上下文规范(例如其主体中引用的程序集)(这使得对象更加独立,并避免在对象用户不知情的情况下拉出潜在的长依赖关系的问题)。

您需要做的是将 VIEW 转换为表值函数:

CREATE FUNCTION MyFunct(/* optional parameters */) RETURNS @res AS
BEGIN
  REFERENCE ASSEMBLY [Utilities];
  @res = EXTRACT ... USING new Utilities.ModifiedTextExtractor();
END;

然后按如下方式调用该函数(请注意,您需要在 SELECT 语句中提供行集别名):

@data = SELECT ... FROM MyFunct() AS f WHERE ...;

或者如果您不想应用投影或滤镜:

@data = MyFunct();

与 View 一样,表值函数将被内联。

关于azure-data-lake - 在 USQL 中编写自定义提取器以跳过有编码问题的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40389614/

相关文章:

azure - 从 Azure Data Lake Gen 2 删除未刷新的文件

azure - 从 DBFS 安装到 Azure Data Lake 创建新表

u-sql - U-SQL 是否支持根据 ADLS 中的创建日期提取文件

c# - SQL - 如何在 SQL 中选择两个字符串行之间的所有行

readLines 与同时使用 Azure Data Lakes 和 R Server 时等效

azure - 将 U-SQL 表的计数读取为标量值?

Azure powershell 更改为检查 Azure Data Lake Storage Gen 1 中的文件并触发 BAT 脚本

xpath - 我无法使用 Xpath 提取节点文本

python - U-SQL + Python 返回列数未知的数据帧

azure - 从 Azure Blob 存储中的 DLL 创建 USQL 程序集