2008-12-21 62 views
5

我有字节数组作为输入。我想将该数组转换为包含数组值的十六进制表示的字符串。这是F#代码:f#字节[] - >十六进制 - >字符串转换

let ByteToHex bytes = 
    bytes 
    |> Array.map (fun (x : byte) -> String.Format("{0:X2}", x)) 

let ConcatArray stringArray = String.Join(null, (ByteToHex stringArray)) 

这产生了我需要的结果,但我想使它更紧凑,因此我只有一个函数。 我无法找到连接ByteToHex的末尾 上每个字节的字符串表示形式的函数。
我试过Array.concat,concat_map,我试过列表,但是我能得到的最好的数组或字符串列表。

问题:

  1. 什么是最简单,最优雅的方式来做到这一点?
  2. 在F#中有字符串格式化结构,以便我可以从系统程序集中替换String.Format?

输入示例:[| 0x24uy; 0xA1uy; 0x00uy; 0x1Cuy |]应该会产生字符串“24A1001C”

回答

5

没有什么内在的错误你的榜样。如果你想把它归结为一个表达式,然后使用String.contcat方法。

let ByteToHex bytes = 
    bytes 
    |> Array.map (fun (x : byte) -> System.String.Format("{0:X2}", x)) 
    |> String.concat System.String.Empty 

在引擎盖下,String.concat只会调用String.Join。您的代码可能不得不轻微更改,因为根据您导入系统的样本。这可能会在F#String和System.String之间创建名称解析冲突。

+0

完美。我尝试过使用String.Concat,但我没有添加“System.String.Empty”参数。 – zendar 2008-12-21 15:02:40

-1

说实话,这看起来并不可怕(虽然我也有非常小F#的经验)。 F#提供了一种简单的迭代方法(foreach)吗?如果这是C#,我可能会使用类似(其中rawbyte[]参数):

 StringBuilder sb = new StringBuilder(); 
     foreach (byte b in raw) { 
      sb.Append(b.ToString("x2")); 
     } 
     return sb.ToString() 

我不知道怎么说转化为F#...

+0

呵呵,我可以WITE它在F#这种方式,但检查该演示卢卡·波隆尼http://channel9.msdn.com/pdc2008/TL11/ 在最初几分钟内有大约势在必行之间差异的解释声明式编程和示例是关于迭代器的。 – zendar 2008-12-21 13:18:54

+0

够公平的。那么,我会观察更好的答案。我可以学习一些F#; - p – 2008-12-21 13:28:32

0

看起来很好。在我看来,只要指出另一个,在Printf模块中非常有用的功能,请看ksprintf。它将格式化字符串的结果传递给您所选择的函数(在这种情况下为身份函数)。

val ksprintf : (string -> 'd) -> StringFormat<'a,'d> -> 'a 
    sprintf, but call the given 'final' function to generate the result. 
1

下面是另一个答案:

let hashFormat (h : byte[]) = 
    let sb = StringBuilder(h.Length * 2) 
    let rec hashFormat' = function 
    | _ as currIndex when currIndex = h.Length -> sb.ToString() 
    | _ as currIndex -> 
     sb.AppendFormat("{0:X2}", h.[currIndex]) |> ignore 
     hashFormat' (currIndex + 1) 
    hashFormat' 0 

这一个好处是,它的尾递归,它的预分配,这将需要转换的字符串生成器空间的确切数额字节数组转换为十六进制字符串。

为背景,我有这个模块中:

module EncodingUtils 

open System 
open System.Text 
open System.Security.Cryptography 
open Newtonsoft.Json 

let private hmacmd5 = new HMACMD5() 
let private encoding = System.Text.Encoding.UTF8 
let private enc (str : string) = encoding.GetBytes str 
let private json o = JsonConvert.SerializeObject o 
let md5 a = a |> (json >> enc >> hmacmd5.ComputeHash >> hashFormat) 

含义我可以通过MD5任何物体,并取回它的JSON哈希值。

2

如果你想变换和积累在一个步骤,fold是你的答案。 sprintf是F#字符串格式函数。

let ByteToHex = Array.fold (fun state x-> state + sprintf "%02X" x) "" 
相关问题