質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

2303閲覧

C++でファイルを保存せずに閉じる

jnst

総合スコア38

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2017/02/28 12:56

編集2017/02/28 13:00

###実現したいこと
あるオブジェクトを読み込んで内容をJSONファイルに出力する処理を書いています。
ある条件になったときはファイルに保存せずに終了したいのですがどのようなやり方があるでしょうか。

###該当のソースコード

c++

1FILE* fp; 2char buf[512]; 3 4fp = fopen(path.c_str(), "wb"); 5FileWriteStream ws(fp, buf, sizeof(buf)); 6PrettyWriter<FileWriteStream> writer(ws); 7 8for (Object o : objects) 9{ 10 // 書き込む処理 11} 12 13fclose(fp);

###試したこと
現状は fopen する前にあらかじめ for 文で objects をすべて走査し、該当する条件になったときは return してしまうコードにしています。
このやり方だと objects を2回走査しなければならないためスマートではありません。
他には該当する条件になったときはファイルを保存した後に削除してしまうという方法もあると思いますが、これも余計なことをしていますよね。
そもそもファイルを保存したくないのです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

こんにちは。

std::stringstreamへ出力しておいて、必要な時にファイルへ書き出すのではどうでしょう?

投稿2017/02/28 13:01

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jnst

2017/03/01 04:45

FileWriteStreamを最初から使うのではなく、std::stringstream で一度扱い、最後に必要だったら FileWriterStream に変換してファイル保存を行う、というアプローチが本来やりたかったことのように思います。 ストリーム処理は経験が少なく調べても使えそうなのが見つからないため、サンプルコードを示していただけないでしょうか?
Chironian

2017/03/01 05:06

FileWriteStreamを使ったことがないので分からないです。 C++対応のライブラリなら、std::ostreamへの出力をサポートしていることが一般的と思うのですが。 もし、お使いのライブラリがRapidJSONでしたら、std::ostreamをサポートしてなさそうですね。 http://qiita.com/k2ymg/items/eef3b15eaa27a89353ab を見ると、メモリへの出力としてStringBufferStreamをサポートしていると言うことですので、そこへ出力後、その内容を文字列として取り出してファイルへ書き込めば良いと思います。
guest

0

ベストアンサー

現状の作りで正しいと思います。
取りうる選択肢は以下の2つだけです。
・現状の形を維持する
・正常なデータのみが書き込み処理に到達するようにする

1回チェックしてから書き込むので普通ですから、物凄くピーキーな処理以外ではあまり気にしない方が良いと思います。物理的に書き込む時間とインメモリをチェックする時間には大きな開きがありますから。

fopenとか生書きで直後にobjectを走査するコードがあるとしたら、走査回数を気にするよりよほど問題だと思います。

質問の要件で、僕の場合のC++における理想のコードは以下のような形です。
(以下Embarcadero社製のC++Builderを使っているコードなので違和感があるかもしれませんが)

void WriteObjectsToJson(String path, const std::vector<Object> &objects) { auto result = Validator::Validate(objects); if (!result.Success) return; std::unique_ptr<Stream> stream(new TFileStream(path, fsCreate)); JsonSerializer::Serialize(objects, stream); }

この際のValidationするクラスや、シリアライズするクラスは適当です。
クラスじゃなくてメソッドでもいい。ただこういう呼び出しの組み合わせで機能を実現する、ということです。

ここで説明したいのは、この時、「2回全体の走査が行われる」とかを一切気にしないということです。
されるのが当たり前だと考えているのもあるし、移譲された処理の先で何が起きているか考えること自体が少し違うかなと考えているからです。
それに上記の処理には再利用性があります。
例えば、TCP:IP通信でJson返したいんだよね、とか、WebのレスポンスにJson入れたいんだよね、という時には、ファイルストリームではなく、そちらも大体Stream関連のクラスが用意されているもので、わずかな手間で結果の出力先を変えることができます。
Validation関連の処理は書き込み前にも使えますが、フロントエンドでUI上で簡易なエラー検査処理を行う際にも使えます。(サービスとクライアントが分かれている場合、検査が2回行われるのはありえる。)

fopenの前にやってるobjectsの走査処理と、書き込み操作処理を合わせるというのは、この完全に分割できる二つの処理を、なんとか混ぜあわせて、処理回数を削ろうとしているのに等しいです。
ストリームに一旦書き込めば1個のループに書き込みつつ、ファイルに書き込まないということはできます。しかし、それはつまり書き込む前に一旦メモリに全部書き出すということで今以上にリソースの観点からすればスマートではないやり方になると思います。ストリームがファイルストリームなら結局ファイルができてしまいますし。
ストリームにする最大の利点は、どのストリームに書き込むかを選択できることですからね。

現在言えることは、検査と書き込みを合体することはオススメできません。

いやいや、ものすごくピーキーなんだよ!データ数も物凄い量なんだよ!この処理は!
という時は、異常なデータが作られるのはどこなのか、どこでその間違いを防げるのか、そういうところを探し、そこで検査を行って、書き込み処理に来るデータを正常なものだけになるようにしましょう。

投稿2017/03/01 02:25

編集2017/03/01 02:31
haru666

総合スコア1591

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jnst

2017/03/01 04:43

良いプロダクトコードにするためのアプローチとして回答内容は100%同意します。 ですが、知りたかったことはまさに本当に物凄い量のデータ量だった場合でも効率良く書ける方法はないか、というところでした。 現実問題として必要はないのですけどね。
haru666

2017/03/01 04:56

・文字列ストリーム(≒メモリストリーム)に一旦書くとメモリの使用量が書き込む分必要になること ・C++で普通にオブジェクトの配列を操作するんだったら、走査そのものが書き込む処理やシリアライズよりずっと早いこと から、改善する方向を現情報から示すのは難しいです。 一括取得するとあまりにもオブジェクトが巨大である場合やメモリの圧迫が許されない場合には、オブジェクトを少しずつ受け取り、少しずつ処理して、一時ファイルに書き込み、最後にリネームします。エラーがある場合は削除します。
haru666

2017/03/01 04:57

結局ディスクスペースとメモリスペースとCPUのコスト比なので。その際、オブジェクトの走査にかかるCPUコストはあんまり考えなくていいのではないか、そこがボトルネックってことはないんじゃないか、と思います。
jnst

2017/03/01 05:50

仰る通りですね。効率的な、という観点だと一番最初にご教示いただいた内容が解になりそうです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問