I would like to build a string from a byte value.
I currently use:
str = " "
str[0] = byte
This seems to work fine but I find it ugly and not very scalable to strings longer than 1 character.
Any idea?
There is a much simpler approach than any of the above: Array#pack:
>> [65,66,67,68,69].pack('c*')
=> "ABCDE"
I believe pack is implemented in c in matz ruby, so it also will be considerably faster with very large arrays.
Also, pack can correctly handle UTF-8 using the 'U*' template.
c*. You really want C*. See: ruby-doc.org/core-1.9.3/Array.html c is for "8-bit signed (signed char)", C is for "8-bit unsigned (unsigned char)"for 1.9 you need:
[195,164].pack('c*').force_encoding('UTF-8')
C* because you want unsigned integers. c* is for signed integers. Note that: "ä".unpack('c*') == [-61, -92]. What you want is: "ä".unpack('C*') == [195, 164]can't remember if there is a single function that does that:
>> a = [65,66,67]
=> [65, 66, 67]
>> a.map {|x| x.chr}.join
=> "ABC"
[195,164].pack('c*').force_encoding('UTF-8')[195,164].map { |x| x.chr }.join.force_encoding('UTF-8')a.map(&:chr).joinThe accepted solution does not work well as of today (2024), it was probably fine in 2009. Nowadays UTF-8 is the de facto Internet encoding standard so we will encode bytes to it. What I found works is a combination of previous good suggestions, I resume the proposed solution in a new answer for ease of future readers reference. bye
# BAD, previously suggested, today bytes do not encode only ASCII
irb> "a α b β".bytes.pack("c*")
=> "a \xCE\xB1 b \xCE\xB2"
# BAD, previously suggested, pack("U*") works well only if
# the array of Int represent UTF-8 integers, larger than bytes.
# try "a α b β".unpack("U*").pack("U*").
irb> "a α b β".bytes.pack("U*")
=> "a α b β"
# OK, proposed solution in 2024
irb> "a α b β".bytes.pack("C*").force_encoding("UTF-8")
=> "a α b β"