Archive for the ‘ruby’ Category

巨大なデータファイルの数行に一行がほしいということがあります。

たとえば、1分おきに記録されている元データがあるけど、実際には1時間に一回のデータが見られればいいという場合、60行につき1行のデータがとれれば事足りるという具合です。


result = ""

idx = 0
File.open('./src.csv', 'r') do |f|
    f.each_slice(10000) do |chunk|
        result += chunk[0].to_s
        puts idx	#check progress
        idx += 1
    end
end

File.open("./output.csv", 'w') do |f|
    f.puts result
end

肝は io.each_slice(n)メソッドを使うことです。

もともとのsrc.csvは1億2千万行を保持するファイルですが、each_slice(10000)を使うことによって、1万件のデータをひとかたまり(chunk)として取り出し、その1行目をresultに追記していくことで1万行につき一行を取り出すということをやっています。

この方法だと、メモリの使用量も全行を読み出すのに比べてずいぶん節約できているようでした。

スクリプトを回して10秒ちょっとくらいで無事、1万2千件のデータがoutput.csvに保存されました。

OSXでmozjpegを使おうと思ったら、mozjpegのコマンドcjpegが使えないというか、cjpegは私の環境では


/usr/local/bin/cjpeg

を指す事になっており、それに気づかず、自分のmozjpegはセルフビルドしてないからjpeg to jpegの圧縮に対応してないのだろうか、とか混乱しまくったので、誰か他にも同じような人が出て来る事の内容に書いておきます。

brew install mozjpeg

でmozjpegをインストール

私のmozjpegはversion3.2でした。

/usr/local/Cellar/mozjpeg/3.2/

以下にインストールされています。
よってこれをパスの通ったディレクトリにシンボリックリンクを作ってあげます。

ln -s /usr/local/Cellar/mozjpeg/3.2/bin/jpegtran /usr/local/bin/mozjpegtran
ln -s /usr/local/Cellar/mozjpeg/3.2/bin/cjpeg /usr/local/bin/mozcjpeg

これでmozjpegが使えるようになりました。

mozjpeg -optimize -quality 80 infile.jpg > outfile.jpg

とする事で動作します。

手元のjpegファイルではmozjpegを使う事によって80%のファイル容量削減に成功しました。画質はかなり高く、相当ズームしてみないと違いはわかりません。

かなり使えそうなので、ブログ用の写真画像を用意するスクリプトにmozjpegをかましてみました。今後は画像容量の削減にかなり役立ってくれそうです。

下のコードは、リサイズ圧縮したい画像のあるディレクトリで実行すると、長辺をsizeで指定したサイズに比率を維持したままリサイズし、それらをmozjpegを使って圧縮するrubyによるスクリプトです。

別途imagemagickをインストールしてお使いいただけます。

#!/usr/bin/ruby
size="1024"
quality="85"
resized_delete=false


#imagemagick resize
resize_cmd = "mkdir resized; find ./ -name '*jpg' -type f | xargs -I@ convert -resize "+size+"x"+size+" -verbose @ ./resized/@"
value = `#{resize_cmd}`

#mozjpeg compression
puts "***mozjpeg_compression***\n"

#処理に必要なファイル集めて保存場所の作成
p files=`find ./* -mindepth 1 -name "*jpg"`.chomp().split("\n")
comp_cmd="mkdir resize_and_compressed;"

#mozjpeg実行
files.map { |f| comp_cmd+="mozcjpeg -optimize -quality "+quality+" "+f+" > " +f.gsub('./resized/','./resize_and_compressed/') +";"}
value = `#{comp_cmd}`

#1024pxオリジナルの削除
if resized_delete == true then
  `#{"rm -rf ./resized"}`
end

上記スクリプトで1024pxにリサイズした画像の圧縮前と圧縮後のサンプルを置いておきます。

圧縮前(471kB)
圧縮前

圧縮後(quality85 111kB)
圧縮後