【问题标题】:UTF-8 is not working for converting byte[] to stringUTF-8 不适用于将 byte[] 转换为字符串
【发布时间】:2018-07-12 23:53:45
【问题描述】:

我在 H-Base 表的行中有一个限定符(长值类型)。

我想获取两个长数字之间的 H-Base 行。为此,我使用以下过滤器。

我的过滤器是这样的:

long startEpochInDay = 384;

long endEpochInDays = 396;

string startDayFilter = "SingleColumnValueFilter('" + cf + "','" + qualifier + "', >= ,'binary:" + Encoding.UTF8.GetString(HBaseGenericHelper.GetBigEndianByteArray(startEpochInDays)) + "',true,true)";

string endDayFilter = "SingleColumnValueFilter('" + cf + "','" + qualifier + "', < ,'binary:" + Encoding.UTF8.GetString(HBaseGenericHelper.GetBigEndianByteArray(endEpochInDays)) + "',true,true)";

string finalFilter = startDayFilter + " AND " + endDayFilter

这些过滤器在数字小于 383 时工作正常,但如果数字大于此数字则失败。

我在调试时发现,将长数转换为字节数组时,它返回的字节数组类似于 \0\0\0\0\0\0\1\128

当字节数组中的最后一个数字为 127 或更少时,UTF-8 工作正常,但随着该数字变为 128 或更大,UTF-8 开始返回 "?" 最后一位。

如果我使用以下方法将字节数组编码为字符串

Encoding encoding = new UTF8Encoding(true,true);
string number = encoding.GetString(HBaseGenericHelper.GetBigEndianByteArray(startEpochInDays));

UTF-8 在将字节数组(如果字节数组中的最后一位数字是 128 或更多)转换为过滤器中的字符串时抛出异常。

异常 - 无法将索引 6 处的字节 [8B] 从指定代码页转换为 Unicode。

内部异常 -

at System.Text.DecoderExceptionFallbackBuffer.Throw(Byte[] bytesUnknown, Int32 index)
at System.Text.DecoderExceptionFallbackBuffer.Fallback(Byte[] bytesUnknown, Int32 index)
at System.Text.DecoderFallbackBuffer.InternalFallback(Byte[] bytes, Byte* pBytes)
at System.Text.UTF8Encoding.GetCharCount(Byte* bytes, Int32 count, DecoderNLS baseDecoder)
at System.String.CreateStringFromEncoding(Byte* bytes, Int32 byteLength, Encoding encoding)
at System.Text.UTF8Encoding.GetString(Byte[] bytes, Int32 index, Int32 count)
at System.Text.Encoding.GetString(Byte[] bytes)

提前致谢。

【问题讨论】:

  • ....您正在将 int 转换为字节表示,然后以某种方式期望这些字节形成有效的 UTF-8 字符?嗯?将 int 转换为字符串的逻辑方法要多得多……例如,.ToString()

标签: c# utf-8 hbase


【解决方案1】:

UTF8 不适合将任意字节编码为字符串。相反:它将任意字符串编码为字节(反之亦然,只要字节格式正确)。没有理由认为HBaseGenericHelper.GetBigEndianByteArray(startEpochInDays) 返回UTF-8 数据,所以encoding.GetString 是完全不合适的,实际上是在使用Encodingbackwards。这是first topic I discussed here - 所以不要惊慌:你的陪伴很好 - 人们总是犯这个错误。

您应该使用的是 base-16(十六进制)或 base-64。

获取十六进制:BitConverter.ToString(byte[])。获取 base-64:Convert.ToBase64String(byte[])

如果您需要数据采用非 base-64 或 base-16 的特定格式,那么您必须具体说明所需的格式。但是:它不是“UTF-8 向后使用”。

【讨论】:

  • 只是一个问题:1)如果它们是任意字节 - 你会如何计算并得出结论它们是任意的? 2)如果它们是任意的,那么您将如何理解它?我的意思是它没有映射——我错过了什么吗?
  • @CodingYoshi 1:a)因为它不起作用,因此这个问题,b)来自名称HBaseGenericHelper.GetBigEndianByteArray(startEpochInDays) - 真的听起来不像正在返回 UTF-8 - 听起来它正在返回 64 位数字的 8 字节大端表示(部分使用问题中的示例文本来推断 64 位); 2)我需要知道 expected 格式是什么;我对 H-Base 不是特别熟悉,但我非常了解二进制和 UTF-8。
  • 嗨,马克,感谢您的宝贵解释。我按照你的建议尝试了两种方法。但没有运气。我将该值保存为以下命令 - BitConverter.GetBytes(HBaseGenericHelper.SwapEndianness(epochInDays))
  • @amit_chauhan 最终,您将不得不了解 H-Base 在这里的期望。有一些文件吗?你甚至需要在这里使用二进制数据吗?它不适用于格式化为常规整数的startEpochInDays 连接吗?
  • @MarcGravell 值存储在 hbase 中,如 \x00\x00\x00\x00\x00\x00\x01~。我没有找到任何具体的文档。我猜H-Base如何比较一个整数值,因为它以二进制格式比较?我正在 H-Base 中节省价值,例如 -- BitConverter.GetBytes(HBaseGenericHelper.SwapEndianness(epochInDays))
猜你喜欢
  • 1970-01-01
  • 2013-03-02
  • 1970-01-01
  • 2012-12-05
  • 2012-02-20
  • 2015-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多