C# 在底层数据不是UTF-16时有效地实现DbDataReader.GetChars()
我需要为ADO.NET提供程序实现DbDataReader.GetChars(),但需要注意的是,单元格中的数据可能不是UTF-16,实际上可能是多种不同编码中的任意一种 该实现专门针对“长数据”,源数据位于服务器上。我与服务器的接口(实际上无法更改)是请求单元格的字节范围。服务器不会以任何方式解释这些字节,它只是二进制数据 我可以在特殊情况下使用明显的实现UTF-16LE和UTF-16BE,但对于其他编码,没有直接的方法将请求“get me UTF-16 codeunits X to X+Y”转换为请求“get me bytes X'to X'+Y'in encoding Z” 消除明显实施的一些“要求”:C# 在底层数据不是UTF-16时有效地实现DbDataReader.GetChars(),c#,character-encoding,ado.net,streaming,C#,Character Encoding,Ado.net,Streaming,我需要为ADO.NET提供程序实现DbDataReader.GetChars(),但需要注意的是,单元格中的数据可能不是UTF-16,实际上可能是多种不同编码中的任意一种 该实现专门针对“长数据”,源数据位于服务器上。我与服务器的接口(实际上无法更改)是请求单元格的字节范围。服务器不会以任何方式解释这些字节,它只是二进制数据 我可以在特殊情况下使用明显的实现UTF-16LE和UTF-16BE,但对于其他编码,没有直接的方法将请求“get me UTF-16 codeunits X to X+Y”
- 我不希望在任何时候向客户端检索给定单元格的所有数据,除非有必要。单元可能非常大,一个请求几千字节的应用程序不需要处理数百兆的内存才能满足请求
- 我希望相对有效地支持GetChars()公开的随机访问。在第一次请求代码单元10亿到10亿+10的情况下,我看不到任何方法可以避免在请求的代码点之前从服务器检索单元格中的所有数据,但随后请求代码单元10亿+10到10亿+20,甚至9.99亿、99.9万到10亿的代码点也不应该意味着重新检索所有这些数据
所以,我的问题是,有没有什么“窍门”可以用来实现这一点(计算出字节到代码单元的精确映射,而不用像在循环中转换、逐字节减小源字节的大小之类的方法)?你知道你的服务器可能提供哪些编码吗?我这样问是因为有些编码是“有状态的”,这意味着给定字节的含义可能取决于其前面的字节序列。例如(),在编码标准ISO 2022-JP中,0x24 0x2c的两个字节可能表示日语平假名字符或两个ASCII字符“$”和“,”“移位状态”-前面控制序列的存在。在几个unicode之前的日文编码中,这些移位状态可以出现在字符串中的任何位置,直到遇到新的移位控制序列为止。在最坏的情况下,根据,“通常,只有从一开始就线性读取非Unicode文本,才能可靠地检测字符边界”
即使是c#使用的UTF-16编码(在概念上是无状态的),由于和的存在,也比通常实现的复杂。代理项对是一对
char
,它们共同指定了一个给定的字符,例如,我发现了如何处理可能丢失的转换状态:我保留了一个解码器aro的副本und在从相关偏移量重新启动时使用的映射中。这样,我不会丢失它在其内部缓冲区中保留的任何部分代码点。这还可以避免添加编码特定的代码,并处理编码的潜在问题,例如dbc带来的Shift JIS
解码器是不可克隆的,所以我使用序列化+反序列化来制作副本。结果发现UTF-32解码器中似乎存在一个bug:序列化它并反序列化它似乎可以清除其内部状态(与文档所述相反)。叹气。。。