首页 > 解决方案 > 如何以良好的性能将字符串数组写入/读取到 .bin

问题描述

将字符串数组写入 .bin 格式如下所示

out =  open("string_array.bin","w")
a = ["first string","second string","third string"]
write(out,a)
close(out)

但是在读取数组 a 时,事情开始变得棘手。

out =  open("string_array.bin","r")
a = read(out)
close(out)
typeof(a) # returns Array{UInt8,1}

如何将 Array{UInt8,1} 转换回原来的 Array{String,1} 类型的数组?

当字符串数组有 300+ 百万个元素时,它也需要工作,即解决方案必须表现良好。

标签: juliabinaryfiles

解决方案


所以 Bogumil 是对的,它有点 hacky,但是如果你热衷于写入和读取二进制文件,那么这里是一个读取和写入的实现,Vector{String}它通过将每个转换StringVector{UInt8},然后将每个写入Vector{UInt8}文件,使用初始Int64for每个Vector{UInt8}存储它的长度。该文件还以Int64存储Vector{String}. 然后读取例程使用此信息将其全部拉回并将其转换回Vector{String}

my_write(fid1::IOStream, x::Vector{UInt8}) = begin ; write(fid1, Int64(length(x))) ; write(fid1, x) ; end
my_write(fid1::IOStream, x::Vector{Vector{UInt8}}) = begin ; write(fid1, Int64(length(x))) ; [ my_write(fid1, y) for y in x ] ; end
my_read(fid1::IOStream, ::Type{Vector{UInt8}})::Vector{UInt8} = begin i = read(fid1, Int64) ; [ read(fid1, UInt8) for a = 1:i ] ; end
my_read(fid1::IOStream, ::Type{Vector{Vector{UInt8}}})::Vector{Vector{UInt8}} = begin i = read(fid1, Int64) ; [ my_read(fid1, Vector{UInt8}) for a = 1:i ] ; end
my_write(myfilepath::String, x::Vector{String}) = open(fid1 -> my_write(fid1, [ Vector{UInt8}(codeunits(y)) for y in x ]), myfilepath, "w")
function my_read(myfilepath::String, ::Type{Vector{String}})::Vector{String}
    x = open(fid1 -> my_read(fid1, Vector{Vector{UInt8}}), myfilepath, "r")
    return [ String(y) for y in x ]
end

我可能已经包含了比必要更多的类型信息,但它可能会让你更清楚一些。另外,对不起,我有一个用单线做这种事情的坏习惯,但如果需要,你可以很容易地打开它。这是一些测试代码(只需调整文件路径):

myfilepath = "/home/colin/Temp/test_file.bin"
x = ["abc", "de", "f", "", "ghij"]
my_write(myfilepath, x)
my_read(myfilepath, Vector{String})

请注意,只要稍加努力,这段代码就可以变得更通用,这样Vector{Vector{T}}只要T是可写的,它几乎可以在任何情况下工作。事实上,如果你真的很聪明,它应该可以推广到 any Vector{Vector{Vector{...{T}}}},只要你能得到正确的递归。


推荐阅读