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

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

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

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

3回答

2604閲覧

【アルゴリズム】ループで、余りのデータを1つ前のデータと合わせたい

Hoge2017

総合スコア11

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2017/10/23 06:21

編集2022/01/12 10:55

###前提・実現したいこと
現在、InputStreamでわたってくるデータを、一定サイズ毎(5MB)にバッファに格納しています。
その際、元のデータは必ずしも綺麗に5MBに分割できるわけではなく、当然余りのデータも発生します。
今回、ループの最後のデータが1MB以下になった場合は、1つ前のデータと併せてInputStreamに格納したいです。
つまり、データは必ず1MB以上にしたいのです。
しかし、その方法、書き方がわかりません、、、

ご教授頂けませんでしょうか?、、
よろしくお願い致します。

追記:パラメータとしてファイルサイズを渡すことができます。
Long fileSize(現状、使用していません。)

関連の質問
受け取ったInputStreamをReadメソッドで一定のバイト数毎に読み込みアップロードしたい

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

public static void uploadPer5MBytes(String containerName, String objectName, String PID, String nowStr, InputStream in, Long fileSize) throws IOException { int offset; int bytesRead; byte[] data = new byte[5242880];// 5Mのバッファ boolean next; int outerLoop = 0; int innerLoop = 0; String renban = ""; // ストリームが終わるまでデータを読み込む外側ループ処理 do { // 外側ループ毎の初期化処理 offset = 0; // offsetのリセット next = false; // 5MBのデータを読み込む内側ループ処理 while ((bytesRead = in.read(data, offset, data.length - offset)) != -1) { offset += bytesRead; innerLoop++; if (offset >= data.length) { next = true; break; } } // 読み込んだデータの送信 if (offset >= 1) { ByteArrayInputStream bais = new ByteArrayInputStream(data, 0, offset); // バッファに格納した分アップロード renban = String.format("%03d", outerLoop); } outerLoop++; System.out.println(outerLoop); } while(next); }

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

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

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

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

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

guest

回答3

0

6MB分バッファ用意して6MB分読み込み、
読み込めた場合は、5MB分だけ送信して1MBを次の処理に繰り越し
途中でファイルが終了した場合は、そのままバッファにたまっているのを送信

配列だけでこの処理書こうとすると面倒くさいので、
ByteBufferクラスを使うといいと思います。

----- 追記 -----
実際書いてみたら配列でも十分処理できますね。
ByteBufferクラスは習得が面倒くさいので、
ドキュメントとにらめっこして理解できるようになったら使ってみる程度で考えてください。

5MB分だけ送信して1MBを次の処理に繰り越し、ここが肝になる処理なのですが、
ByteBufferクラスなら、5MBの切り出しはgetメソッド、1MBの繰り越しはcompactメソッド。
配列なら、5MBの切り出し、1MBの繰り越し、両方ともSystem.arraycopyで出来ます。

ただし、配列の場合は次の読み込みを行う際、offsetを1MB分進めておかないと、
繰り越したデータを上書きすることになるので気を付けてください。

投稿2017/10/24 01:56

編集2017/10/24 02:21
abs123

総合スコア1280

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

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

Hoge2017

2017/10/25 05:19

ありがとうございます。 Bufferクラス、勉強します。 今回は別の方からご回答頂いた配列方式でやってみます。
guest

0

fileSizeの仕様がわからないので、使わずに行きます。
まず、5MB読み込んでもそのあとに1MB未満で終わる配列が来る可能性があるため、すぐにbaisにすることはできません。
0. 読み込んだbyte配列をいったん変数(仮にtemp)に置いておく
0. 続きを読み込む
0. 2で読み込んだのが1MB未満ならtempと連結する。
1MB以上ならtempをbaisに入れ、2をtempに置く。
0. nextがtrueなら2に戻るが、falseならtempもbaisにして送信(?)して終了

という流れになるのではないかと。

java

1 public static void uploadPer5MBytes(String containerName, String objectName, String PID, String nowStr, InputStream in, Long fileSize) throws IOException { 2 int offset; 3 int bytesRead; 4 byte[] data = new byte[(5 << 20)];// 5Mのバッファ 5 6 // 送信待機の配列(新たに追加) 7 byte[] temp = new byte[(5 << 20)]; 8 9 boolean next; 10 int outerLoop = 0; 11 int innerLoop = 0; 12 String renban = ""; 13 14 // ストリームが終わるまでデータを読み込む外側ループ処理 15 do { 16 // 外側ループ毎の初期化処理 17 offset = 0; // offsetのリセット 18 next = false; 19 20 // 5MBのデータを読み込む内側ループ処理 21 while ((bytesRead = in.read(data, offset, data.length - offset)) != -1) { 22 offset += bytesRead; 23 innerLoop++; 24 if (offset >= data.length) { 25 next = true; 26 break; 27 } 28 } 29 // 読み込みサイズが1MB未満で、1回目でないとき(1回目の場合はマージする対象がない) 30 if (offset < (1 << 20) && outerLoop > 0) { 31 byte[] merge = Arrays.copyOf(temp, temp.size + offset); 32 System.arraycopy(data, 0, merge, temp.size, offset); 33 data = merge; 34 offset += temp.size; 35 } 36 // 読み込んだデータの送信 37 if (offset > 0) { 38 ByteArrayInputStream bais = new ByteArrayInputStream(data, 0, offset); 39 // バッファに格納した分アップロード 40 renban = String.format("%03d", outerLoop); 41 42 } 43 outerLoop++; 44 System.out.println(outerLoop); 45 } while(next); 46 }

適当に変えたが足りていません。

投稿2017/10/23 16:42

swordone

総合スコア20649

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

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

Hoge2017

2017/10/25 05:18

コードの方、ありがとうございます。 想定どおりに分割されました。 ただ、連番の振られ方が 想定では000⇒001なのが000⇒002になってしまっており そこを調査しております。 いずれにせよ、ありがとうございました。
swordone

2017/10/25 06:43

実はこのコード未完成で、その旨書いていたはずなのですが、切れてしまっていました。
Hoge2017

2017/10/25 07:25

承知しました。 差し支えなければ、未完成部分というのは、どういった処理なのでしょうか、ざっくりとで構いませんので教えて頂けませんか、、
Hoge2017

2017/10/25 07:47

すみません。 連番がおかしいというのは、自分の勘違いでした!
guest

0

ファイルサイズが分かるなら5MBずつ読んでいって、
N回目に読み込むときに何バイトのデータが読み込める分かると思います。

であれば、今回が何回目の読み込みかを数えておいてその回数+1から
「次回に何バイトが読み込めるか」を求められるはずです。

それがわかれば、読み込みロジックを
「次回に読み込まれるバイト数」が1MB以下のデータが読まれる場合は、ファイルの最後までバッファに格納する。
そうではない場合は、5MBほどバッファに格納する。
……とすればいいんじゃないでしょうか。

投稿2017/10/23 09:09

ku__ra__ge

総合スコア4524

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

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

Hoge2017

2017/10/25 05:19

ありがとうございます。 ロジックへの理解を深めます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問