
質問を見ていただいて有難うございます。
長文になりますが、宜しくお願いいたします。
最終的な質問をまとめると、
『file descriptorをSTDOUTに切り替えるにはどうしたら良いですか?』
になるかと思いますが、目的から経緯についても以下に記します。
zipファイルを標準出力に書き出したいです。
プログラム上で作り出したzipファイル形式のデータを、
ディスクに書き出すのではなく、標準出力に書き出したいのです。
zipファイルをレスポンスするcgiを作りたいからです。
zipファイルを生成するライブラリは、探したところ
・rubyzip
・zipruby
というのがありました。
ziprubyには、Zip::Archive.open_bufferというメソッドがあったので、
これを利用して以下の様に書いてみました。(行頭スペースは全角です)
-------------------------------------------------------------
#!/usr/local/bin/ruby
require 'cgi'
require 'rubygems'
require 'zipruby'
body=''
Zip::Archive.open_buffer(body, Zip::CREATE) do |ar|
ar.add_buffer('first_entry.txt','Hello world!')
ar.add_dir('adir')
ar.add_buffer('adir/first_entry.txt','Hello again!')
end
CGI.new().out({
'status'=>'OK',
'type'=>'application/zip',
'Content-Disposition'=>'attachment; filename="hoge.zip"'
}){body}
-------------------------------------------------------------
とりあえずは、これで目的を達成できたのですが、
巨大なzipファイル生成すると、クライアント(ブラウザ)がタイムアウトしてしまいます。
そこで、CGI.new().outを使うのをやめて、STDOUTに直接、”ストリーム”に書き出そうと思います。(Chunkで)
rubyzipには、Zip::ZipOutputStream::open(ファイル名)というのがあります。
これをファイルではなく、STDOUTへ出力するように改造を試みました。
zip.rbというソースファイルを見ると、
@outputStream = File.new(fileName, "wb")
という部分があるので、この@outputStreamをSTDOUTに変えてしまえばよいと考え、
以下の様に描いてみました。
(標準出力に書き出す部分のみです。)
-------------------------------------------------------------
require 'zip/zip'
module ZipKai
include Zip
class ZipOutputStreamKai < ZipOutputStream
def initialize(fileName)
super(fileName)
@fileName = fileName
#@outputStream = File.new(fileName, "wb")
@outputStream = IO.new(1, "wb")
end
end
end
ZipKai::ZipOutputStreamKai::open("my.zip") { |io|
io.put_next_entry("first_entry.txt")
io.write "Hello world!"
io.put_next_entry("adir/first_entry.txt")
io.write "Hello again!"
}
-------------------------------------------------------------
実行してみると、以下エラーがでました。
C:/ruby/lib/ruby/gems/1.8/gems/rubyzip-0.9.1/lib/zip/zip.rb:1008:in `tell': Bad
file descriptor (Errno::EBADF)
ここで、質問です。
file descriptor(@outputStream)をSTDOUTに切り替えるにはどうしたら良いでしょうか?
※そもそも、他にもっと良い方法があるよといったご回答でもOKです。
ご指導のほど、宜しくお願いいたします。
A 回答 (2件)
- 最新から表示
- 回答順に表示
No.2
- 回答日時:
>出来たところから、チャンクでソケットに書きたいと思いました。
出来たところからと言っても、圧縮ファイルの先頭に「圧縮後の長さ」を書かないと行けないので、ファイル単位でしか「出来」ませんよ。
つまり、細かいファイルたくさんを集めて圧縮するなら、ファイル単位で出力することで改善されますが、大きなファイル1つなら改善不可能。
いずれにせよ、やるとなると、大幅書き直しになるかと。
notnotさん、ご回答有難うございます。
細かいファイルをたくさん集めての出力なので。。。
>いずれにせよ、やるとなると、大幅書き直しになるかと。
そのようですね。
アドバイス有難うございました。
No.1
- 回答日時:
エラーメッセージからすると、ライブラリが内部でtellメソッドを使っているようですが、tellは、現在のファイル位置がファイル先頭から何バイト目かを返すメソッドで、ディスク上のファイルには使えますが、STDOUTには使えません。
いずれにせよ、処理に時間がかかってタイムアウトしているなら、出力方法をどう変えても同じだと思いますけど。圧縮に時間がかかっているのでは?
圧縮率を低く(無圧縮とか)すれば時間が短縮できると思います。
notnotさん ご回答有難うございます。
>いずれにせよ、処理に時間がかかってタイムアウトしているなら
今の方法だと、リクエストをもらってからレスポンスを開始するまでの
時間(無通信の時間)が長いので、クライアントがタイムアウトするものと思いまして。。。
出来たところから、チャンクでソケットに書きたいと思いました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
(再質問)エクセルのマクロボ...
-
秀丸エディタで、同じ記号で囲...
-
CSSのhtmlへの紐付けについ...
-
Ruby 格納
-
Ruby newメソッド
-
1、Rstudioで回帰直線を求める...
-
a=2, b=1のとき”x=(a-b+3)%3”の...
-
Ruby require ライブラリー
-
ruby OpenURI::Meta
-
ruby while式
-
ruby loopメソッド 変数(再喝)
-
ruby 配列
-
ruby loopメソッド 変数
-
ruby クラス・オブジェクト・イ...
-
ルビー言語 ライブラリー 追記
-
ruby raise句
-
ruby begin句
-
ruby ensure句
-
ルビー言語 ライブラリー(再々...
-
ルビー言語 csvファイル 続き(...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C# ファイルを読み込みlistvie...
-
ファイルサイズ
-
fgetsの処理を詳しく説明してく...
-
サーバにアップしたファイルを...
-
【ruby】zipファイルデータをST...
-
バッチ処理 特定の文字以降を...
-
VBAでcsvファイルもシートもあ...
-
ダブルコーテーション付きでCSV...
-
【ExcelVBA】300万件越えCSVか...
-
Excelマクロ 空白セルを無視し...
-
Access VBA エラー2448について
-
VBA テキストボックスを選択状...
-
[コンパイルエラー 修飾子が不...
-
LibreOffice Calcのマクロで、...
-
ファイル名を変数で書きこむfwr...
-
シート内容の文字列を置換してV...
-
EXCEL→CSV保存時のダブルクォー...
-
バッチファイルでcsvファイルに...
-
パイソンでのファイルを見るには
-
Excel VBAでループ?続けて処理...
おすすめ情報