如何在不使用文件的情况下实现 Unix Tail 操作。在红宝石中

发布于 2024-11-09 15:25:54 字数 1835 浏览 0 评论 0原文

我使用 Ruby 读取图像文件并将其保存到字符串中。

partial_image100 = File.read("image.tga")
partial_image99 = File.read("image.tga")
partial_image98 = File.read("image.tga")
...

我在分布式系统的一端读取这些图像。在另一个系统中我想做一个尾部操作。系统仅接收图像。

我有大约 100 张部分图像。我想做一个 Tail 操作,如下所示:

tail -c +19 image100 >> image99
tail -c +19 image99 >> image98
tail -c +19 image97 >> image96
...

基本上它只是删除部分图像的前 18 个字节并将剩下的内容附加到下一个图像。

问题是这很慢。从 Ruby 调用 100 个 unix 命令很慢。我想重构它,以便这发生在 Ruby 世界中。就在记忆里。没有文件。

我怎样才能在 Ruby 中做到这一点?

谢谢

编辑:

图像存储在这样的哈希中:

{"27"=>"\u0000\u0000\u0002\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u000E\u0001\xD0\a\xD0\a\u0018 \xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF...

编辑:

您在这里拥有所有相关代码:https:// gist.github.com/989563

有两个文件。文件中以 json 形式编码的代码和哈希对象。运行代码时,将在 /tmp 处创建两个图像文件

  • /tmp/image-tail-merger.tga – 尾部合并算法的输出
  • /tmp/image-/time/.tga – in 的输出-memory-tail算法

目前内存算法失败,因为生成的图像是毕加索的。

如果您设法使内存算法生成与尾部合并算法相同的图像,那么您就成功了。

编辑:

我终于做对了!

这是代码 https://gist.github.com/989563

I used Ruby to read an image file and save that into a string.

partial_image100 = File.read("image.tga")
partial_image99 = File.read("image.tga")
partial_image98 = File.read("image.tga")
...

I read those images at one end of a distributed system. In another system I want to do a Tail operation. The system receives just the images.

I have around a 100 partial images. I want to do a Tail operation, like this:

tail -c +19 image100 >> image99
tail -c +19 image99 >> image98
tail -c +19 image97 >> image96
...

Basically it just removes the first 18 bytes of the partial image and append what is left to the next image.

The problem is that this is slow. Calling 100 unix commands from Ruby is slow. I want to refactor this so that this happen in Ruby world. Just in memory. No files.

How can I do this in Ruby?

Thanks

edit:

The images are stored in a hash like this:

{"27"=>"\u0000\u0000\u0002\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u000E\u0001\xD0\a\xD0\a\u0018 \xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF\u0000\xFF\xFF...

EDIT:

You have all the relevant code here: https://gist.github.com/989563

There are two files. The code and a hash object encoded in json in a file. When you run the code there will be two image files created at /tmp

  • /tmp/image-tail-merger.tga – The output from the tail-merge algorithm
  • /tmp/image-/time/.tga – the output from the in-memory-tail algorithm

Currently the in-memory algorithm fails because the generated image is a Picasso.

If you manage to make the in-memory-algorithm generate the same image that the tail-merge algorithm do then you have succeeded.

EDIT:

I got it right finally!!!

Here is the code
https://gist.github.com/989563

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

水染的天色ゝ 2024-11-16 15:25:54

我可能会查看 File::Tail,类似于 Perl 模块。

File.open(filename) do |log|
 log.extend(File::Tail)
 log.interval = 10
 log.backward(10)
 log.tail { |line| puts line }
end

您还可以对自己的 File 进行猴子修补以使用 File::Tail 以及更简洁的使用方式。

I might look at File::Tail, similar to the Perl module.

File.open(filename) do |log|
 log.extend(File::Tail)
 log.interval = 10
 log.backward(10)
 log.tail { |line| puts line }
end

You can also monkey-patch your own File to use File::Tail as well for cleaner usage.

恬淡成诗 2024-11-16 15:25:54

您可能想看看 String#unpack (及其逆Array#pack)。

在你的情况下,类似的东西应该做你想做的事:

trunked = image.unpack('@19c*').pack('c*')

You may want to take a look at String#unpack (and its inverse Array#pack).

In your case some like that should do what you want:

trunked = image.unpack('@19c*').pack('c*')
-柠檬树下少年和吉他 2024-11-16 15:25:54

您可以尝试类似这样的

image100 = "some image string"
image99 = "some other image string"

image99 += image100.slice(0,19)

编辑:在您的具体示例中,您可以执行此操作来迭代整个图像

(image_hash.size..1).each do i
  # Here we use slice to select everything *except* the first 19 bytes
  # Note: To select just the first 19 bytes we could do slice(0,19)
  #       To select just the last 19 bytes we could do slice(-19,19)

  # We then append this result to the next image down the line
  image_hash[i-1] += image_hash[i].slice(19,image_hash[i].size-19)
end

如果您想永久删除“尾部”位,您可以使用 slice! 进行内联替换。

也许更干净一点:

# Strip the headers
image_hash.each { |k,v| v.slice!(0,19) }

# Append them together
(image_hash.keys.sort).collect{ |i| image_hash[i] }.join

编辑:工作代码示例 https://gist.github.com/989563

You might try something like this

image100 = "some image string"
image99 = "some other image string"

image99 += image100.slice(0,19)

EDIT: In your specific example you could do this to iterate through the entire image

(image_hash.size..1).each do i
  # Here we use slice to select everything *except* the first 19 bytes
  # Note: To select just the first 19 bytes we could do slice(0,19)
  #       To select just the last 19 bytes we could do slice(-19,19)

  # We then append this result to the next image down the line
  image_hash[i-1] += image_hash[i].slice(19,image_hash[i].size-19)
end

If you want to remove the "tailed" bits permanently you can use slice! to do an inline replace.

Maybe a bit cleaner:

# Strip the headers
image_hash.each { |k,v| v.slice!(0,19) }

# Append them together
(image_hash.keys.sort).collect{ |i| image_hash[i] }.join

EDIT: Working code example https://gist.github.com/989563

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文