# Why stringfy an array of UInt8s empties it?

**URL:** <https://discourse.julialang.org/t/why-stringfy-an-array-of-uint8s-empties-it/102389>\
**Category:** General Usage\
**Created:** [August 2, 2023, 10:15am UTC](https://discourse.julialang.org/t/why-stringfy-an-array-of-uint8s-empties-it/102389 "2023-08-02T10:15:12Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [August 2, 2023, 10:15am UTC](https://discourse.julialang.org/t/why-stringfy-an-array-of-uint8s-empties-it/102389/1 "2023-08-02T10:15:12Z")

</div>

Is this result documented?  
What is the reason why v is emptied?

```julia
julia> v=[0x41,0x42]
2-element Vector{UInt8}:
 0x41
 0x42

julia> String(v)
"AB"

julia> v
UInt8[]

```

PS  
Is there a more efficient and side-effect free way to transform an array of codeunits into string?

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [August 2, 2023, 10:36am UTC](https://discourse.julialang.org/t/why-stringfy-an-array-of-uint8s-empties-it/102389/2 "2023-08-02T10:36:14Z")

</div>

I found some of the answers

```julia
String(v::AbstractVector{UInt8})

  Create a new String object using the data buffer from byte vector v. If v is a Vector{UInt8} it will be truncated to zero        
  length and future modification of v cannot affect the contents of the resulting string. To avoid truncation of Vector{UInt8}     
  data, use String(copy(v)); for other AbstractVector types, String(v) already makes a copy.

  When possible, the memory of v will be used without copying when the String object is created. This is guaranteed to be the      
  case for byte vectors returned by take! on a writable IOBuffer and by calls to read(io, nb). This allows zero-copy conversion    
  of I/O data to strings. In other cases, Vector{UInt8} data may be copied, but v is truncated anyway to guarantee consistent      
  behavior.

```

perhaps a ‘!’ should be added

---

<div class="post-metadata">

**Author:** ![barucden](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barucden/32/26154_2.png) [@barucden](https://discourse.julialang.org/u/barucden)\
**Post date:** [August 2, 2023, 10:43am UTC](https://discourse.julialang.org/t/why-stringfy-an-array-of-uint8s-empties-it/102389/3 "2023-08-02T10:43:12Z")

</div>

There is an open issue for exactly this [String constructor truncates data. · Issue #32528 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/32528). You can read there about why it was made like this.

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [August 2, 2023, 11:08am UTC](https://discourse.julialang.org/t/why-stringfy-an-array-of-uint8s-empties-it/102389/4 "2023-08-02T11:08:37Z")

</div>

For me the problem arose in an attempt to write differently and compare the performance of the various proposed solutions to [this](https://discourse.julialang.org/t/multiway-string-substitution/102345/11) problem.  
It didn’t take me long to find where the problem was, but in much more complex code this “hidden” behavior can be much harder to spot.

```julia

function multisbs3(str,sstr, s)
    cstr,csstr,cs=codeunits.([str,sstr, s])
    lcstr,lcsstr,lcs = length.([cstr,csstr,cs])
    l=lcs-(lcstr-lcsstr)
    fp=findfirst(cstr, cs)
    tmp=Vector{UInt8}(undef,l)
    res=Vector{String}(undef,4)
    j=1
    while !isnothing(fp)
        fs,ls=first(fp),last(fp)
        copyto!(tmp,1, cs,1,fs-1)
        copyto!(tmp,fs,csstr)
        copyto!(tmp,ls,cs,ls+1,lcs-ls)
        res[j]=String(copy(tmp))
        j+=1
        fp=findnext(cstr, cs,first(fp)+1)
    end
    res
end

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [August 2, 2023, 11:47am UTC](https://discourse.julialang.org/t/why-stringfy-an-array-of-uint8s-empties-it/102389/5 "2023-08-02T11:47:55Z")

</div>

> [@rocco\_sprmnt21](#):
>
> Is there a more efficient and side-effect free way to transform an array of codeunits into string?

Yes, you can use [StringViews.jl](https://github.com/JuliaStrings/StringViews.jl).

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [August 2, 2023, 12:47pm UTC](https://discourse.julialang.org/t/why-stringfy-an-array-of-uint8s-empties-it/102389/6 "2023-08-02T12:47:26Z")

</div>

> [@stevengj](#):
>
> Yes, you can use [StringViews.jl](https://github.com/JuliaStrings/StringViews.jl).

```julia
using StrngViews
julia> function multisbsSV(str,sstr, s)
           cstr,csstr,cs=codeunits.([str,sstr, s])
           lcstr,lcsstr,lcs = length.([cstr,csstr,cs])
           l=lcs-(lcstr-lcsstr)
           fp=findfirst(cstr, cs)
           tmp=Vector{UInt8}(undef,l)
           res=Vector{StringView}(undef,lcs-lcsstr)
           j=1
           while !isnothing(fp)
               fs,ls=first(fp),last(fp)
               copyto!(tmp,1, cs,1,fs-1)
               copyto!(tmp,fs,csstr)
               copyto!(tmp,ls,cs,ls+1,lcs-ls)
               res[j]=StringView(tmp)
               j+=1
               fp=findnext(cstr, cs,first(fp)+1)
           end
           @view res[1:j-1]
       end
multisbs3 (generic function with 1 method)

julia> function multisbsSC(str,sstr, s)
           cstr,csstr,cs=codeunits.([str,sstr, s])
           lcstr,lcsstr,lcs = length.([cstr,csstr,cs])
           l=lcs-(lcstr-lcsstr)
           fp=findfirst(cstr, cs)
           tmp=Vector{UInt8}(undef,l)
           res=Vector{String}(undef,lcs-lcsstr)
           j=1
           while !isnothing(fp)
               fs,ls=first(fp),last(fp)
               copyto!(tmp,1, cs,1,fs-1)
               copyto!(tmp,fs,csstr)
               copyto!(tmp,ls,cs,ls+1,lcs-ls)
               res[j]=String(copy(tmp))
               j+=1
               fp=findnext(cstr, cs,first(fp)+1)
           end
           @view res[1:j-1]
       end
multisbs4 (generic function with 1 method)

julia> @btime multisbsSV("BB","A","BBBBBaBBCCDDDDDDDAA")
  497.423 ns (11 allocations: 672 bytes)
5-element view(::Vector{StringView}, 1:5) with eltype StringView:
 "BBBBBaACCDDDDDDDAA"
 "BBBBBaACCDDDDDDDAA"
 "BBBBBaACCDDDDDDDAA"
 "BBBBBaACCDDDDDDDAA"
 "BBBBBaACCDDDDDDDAA"

julia> @btime multisbsSC("BB","A","BBBBBaBBCCDDDDDDDAA")
  637.126 ns (16 allocations: 1.16 KiB)
5-element view(::Vector{String}, 1:5) with eltype String:
 "ABBBaBBCCDDDDDDDAA"
 "BABBaBBCCDDDDDDDAA"
 "BBABaBBCCDDDDDDDAA"
 "BBBAaBBCCDDDDDDDAA"
 "BBBBBaACCDDDDDDDAA"

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [August 2, 2023, 1:13pm UTC](https://discourse.julialang.org/t/why-stringfy-an-array-of-uint8s-empties-it/102389/7 "2023-08-02T13:13:16Z")

</div>

> [@rocco\_sprmnt21](#):
>
> `res=Vector{StringView}(undef,lcs-lcsstr)`

This is an [abstractly typed container](https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-abstract-container). You maybe want

```julia
res = StringView{Vector{UInt8}}(undef,lcs-lcsstr)

```

But I don’t think this does what you want:

> [@rocco\_sprmnt21](#):
>
> `res[j]=StringView(tmp)`

It uses the same (mutable) array `tmp` as the storage for every element `res[j]`, so the next `j` iteration overwrites the data for the previous `StringViews` in `res`.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [August 2, 2023, 1:15pm UTC](https://discourse.julialang.org/t/why-stringfy-an-array-of-uint8s-empties-it/102389/8 "2023-08-02T13:15:29Z")

</div>

> [@rocco\_sprmnt21](#):
>
> `str,csstr,cs=codeunits.([str,sstr, s])`

Note that this allocates an array just to assign it to 3 variables. If you want to use this style I would use a tuple, e.g.

```julia
str,csstr,cs=codeunits.((str,sstr, s))

```

which is allocation-free.

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [August 2, 2023, 1:40pm UTC](https://discourse.julialang.org/t/why-stringfy-an-array-of-uint8s-empties-it/102389/9 "2023-08-02T13:40:29Z")

</div>

I tried, but …

```julia
julia> res = StringView{Vector{UInt8}}(undef,lcs-lcsstr)
ERROR: MethodError: no method matching StringView{Vector{UInt8}}(::UndefInitializer, ::Int64)

```

> [@stevengj](#):
>
> But I don’t think this does what you want:

I need it as a temporary buffer to put the codeunits to be transformed into output strings.  
It gets completely overwritten every cycle, but that’s okay

I could avoid this by writing the variuos vector of UInt8 into a Vector and then doing String.(Vector(vector(UInt8))), but that seems less efficient

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [August 2, 2023, 11:47pm UTC](https://discourse.julialang.org/t/why-stringfy-an-array-of-uint8s-empties-it/102389/10 "2023-08-02T23:47:53Z")

</div>

> [@rocco\_sprmnt21](#):
>
> `res = StringView{Vector{UInt8}}(undef,lcs-lcsstr)`

Sorry, I meant:

```julia
res = Vector{StringView{Vector{UInt8}}}(undef,lcs-lcsstr)

```

> [@rocco\_sprmnt21](#):
>
> It gets completely overwritten every cycle, but that’s okay

It’s not okay because you’re not using it as a temporary buffer — you are also using it as the permanent storage for the strings in `res`. (I’m not sure you understand the “view” concept here?) That’s why all of the strings returned by `multisbsSV` in your example above were the same.

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [August 3, 2023, 10:57am UTC](https://discourse.julialang.org/t/why-stringfy-an-array-of-uint8s-empties-it/102389/11 "2023-08-03T10:57:22Z")

</div>

The alternative idea to String(copy()) was this. The fact that I was unable to define a vector of vectors of the type StringView made me create a hybrid that ran into a typical problem where the last used “view” overwrites all previous elements.

Similar problem to what I would have if I defined  
`res= fill(fill(0x00,18),19)`  
I use 18 and 19 because I get bored looking for suitable generic formulas 😀

```julia
using StringViews
function multisbsSV(str,sstr, s)
    cstr,csstr,cs=codeunits.((str,sstr, s))
    fp=findfirst(cstr, cs)
    #res = Vector{StringView{Vector{UInt8}}}(undef,lcs-lcsstr)
    res=[fill(0x00,18) for _ in 1:19]
    j=1
    while !isnothing(fp)
        fs,ls=first(fp),last(fp)
        copyto!(res[j],1, cs,1,fs-1)
        copyto!(res[j],fs,csstr)
        copyto!(res[j],ls,cs,ls+1,lcs-ls)
        j+=1
        fp=findnext(cstr, cs,first(fp)+1)
    end
   StringView.(res[1:j-1])
end

```

PS  
I tried to use this definition, but it gives me problems when I have to use res[j] inside copyto!().

`res = Vector{StringView{Vector{UInt8}}}(undef,lcs-lcsstr)`

```julia
julia> multisbsSV("BB","A","BBBBBaBBCCDDDDDDDAA")
ERROR: UndefRefError: access to undefined reference

```

In fact I have some doubts about the general validity of preallocating an array of arrays with undefined elements.
