
お世話になります。
ブラウザ画面からファイルをアップロードし、そのバイナリデータを返すメソッドを作成したのですが、約50MB以上のファイルを使用するとOutOfMemoryエラーとなりJava heap spaceが足りないといわれてしまいます。ヒープサイズをあげればエラーはしなくなるとはおもいますが、根本的な解決にはならないと思います。
public byte[] upload(FormFile ff) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = ff.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
byte[] byteData;
try {
int data = 0;
byte[] buffer = new byte[1024];
while ((data = bis.read(buffer) != -1) {
baos.write(buffer, 0, data);
}
byteData = baos.toByteArray();
} catch (IOException e) {
throw e;
} finally {
if (null != bis) {
bis.close();
}
}
return byteData;
}
以上のようなメソッドなのですが、おかしい点はありますでしょうか。
指摘していただけると助かります。
よろしくお願いいたします。
No.2ベストアンサー
- 回答日時:
iBatisは、BLOBに対してデフォルトではbyte配列で対応するので、
ちょっと大きいデータを扱うと、この問題が発生するんですよね。
BLOBとStreamをマッピングする、カスタムTypeHandlerを作成して対応します。
iBatis側で用意されていないのは、DBによってBLOBの扱いが違うから。
No.1
- 回答日時:
50MBのファイルなら50MB全部を読み出してからbaos.toByteArray()を実行していますよね。
どうしてもファイル全体を読み込み終えてからでないと処理できないような内容ならば、ファイル全体を保持してもOutOfMemoryにならないだけの大きさのヒープを確保するしかありません。upload()がreturnした配列はその後どのように使われるのですか? ファイルを最後まで読み出してから一気に処理するのではなく、少しずつ読み出しては処理する(処理し終えた部分はメモリ上から消す)のを繰り返すという形には変更できませんか? そのように書き換えられる種類の処理であればそれが根本的な解決策です。
そういう書き換えができない場合に少しでも限界を遠ざけるにはどうしたらいいか、ですが、ファイルの長さは読み出し前には分からないでしょうか? ByteArrayOutputStreamに一度溜め込んでからtoByteArray()で変換するのはメモリの無駄です。ByteArrayOutputStreamを使うのをやめて、ファイルの長さ分のbyte配列をnewで初めから確保し、bis.read()でそのbyte配列に直接読み込むようにすれば大幅な節約になるはずです。それでも、ファイル全体をメモリ上に読み込もうとする限り200MBのファイルを扱おうとしたらOutOfMemoryになるかもしれません。
回答ありがとうございます。
取得したbyte配列はエンティティに格納してDBに格納しようとしています。
バイナリデータをDBに格納するのが必要なためByteArrayOutputStreamを使っていました。
InputStreamをそのまま格納できれば一番早いのかと思ったのですがiBatisでそれができるのかわからなかったからです。
>ByteArrayOutputStreamを使うのをやめて、ファイルの長さ分のbyte配列をnewで初めから確保し、bis.read()でそのbyte配列に直接読み込むようにすれば大幅な節約になるはずです。
これをちょっと試してみようと思います。
ありがとうございます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C#テキストボックスの文字を配列にいれてその後表示する 4 2022/07/17 04:47
- C言語・C++・C# TCP/IP通信時のサーバーからの受信 2 2022/11/23 09:11
- その他(プログラミング・Web制作) pythonのこのエラーがわかりません 3 2022/11/16 14:54
- CGI htmlからパラメータで、cgiに渡したい。 1 2023/02/06 16:15
- C言語・C++・C# c言語の問題です 2 2023/07/21 10:51
- C言語・C++・C# C# で、あるフォルダー内にあるすべてのテキストファイルを別のフォルダーにコピーする。 4 2022/11/21 13:23
- Java javaでのプログラム(配列)について質問です. 2 2022/10/14 22:27
- その他(プログラミング・Web制作) Python - Excel で Webからデータを連続取得したいのですが エラーが出ます 1 2023/07/06 20:08
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- Excel(エクセル) Excelにて、フォルダ内のTextファイルをマクロで統合すると文字化けしてしまう時の解消コード 4 2023/01/01 07:32
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
DXFファイルをVBで取り込み、図...
-
ファイルからビット単位での読...
-
ファイルをメモリに出力する方法
-
ファイル入力のデータを構造体...
-
SDKにて。
-
日本語を配列に収め、そして表...
-
Unicodeのファイル読み込みがう...
-
VBAでテキストファイルを複数開...
-
エクセルのプロパティーでセキ...
-
PDFファイルについて
-
エクセルで複数のコメントのサ...
-
カンマ区切りのCSVファイルから...
-
ExcelブックをGoogleスプレッド...
-
C++でのフォルダ削除ができま...
-
同じファイル名 上書きしないフ...
-
エクセルvbaでdocuworksprinter...
-
【マクロ】フォルダにファイル...
-
実行ファイルのパスを取得したい
-
タイムスタンプの更新の方法2
-
バッチファイルを作りたい。
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
バイト型のデータを16進表記で...
-
バイナリファイルの一部分をカ...
-
バイナリファイルでOutOfMemory...
-
DXFファイルをVBで取り込み、図...
-
Cで2次元配列にCSVファイルを...
-
配列操作について
-
日本語を配列に収め、そして表...
-
VBScriptの配列は、要素数を指...
-
テキストファイルを後ろから読...
-
CSVファイルによる検索の高速化
-
グレースケール画像の画素値を得る
-
ファイルをメモリに出力する方法
-
RGBのバイナリデータをCImageに...
-
C++による ファイルの読み込み
-
日本語混じりのファイルをラン...
-
VBAでテキストファイルの改行を...
-
VBでバイナリファイルのコピー...
-
[VBS] 16進数でバイナリファイ...
-
C言語でのファイル読み込み
-
Unicodeのファイル読み込みがう...
おすすめ情報