基本的なアイデアを提供するはずの(テストされていない)コードスニペットを投稿します。
/**
* Implementors of this interface should only convert current row to byte array and return it.
*
* @author yura
*/
public interface RowToByteArrayConverter {
byte[] rowToByteArray(ResultSet resultSet);
}
public class ResultSetAsInputStream extends InputStream {
private final RowToByteArrayConverter converter;
private final PreparedStatement statement;
private final ResultSet resultSet;
private byte[] buffer;
private int position;
public ResultSetAsInputStream(final RowToByteArrayConverter converter, final Connection connection, final String sql, final Object... parameters) throws SQLException {
this.converter = converter;
statement = createStatement(connection, sql, parameters);
resultSet = statement.executeQuery();
}
private static PreparedStatement createStatement(final Connection connection, final String sql, final Object[] parameters) {
// PreparedStatement should be created here from passed connection, sql and parameters
return null;
}
@Override
public int read() throws IOException {
try {
if(buffer == null) {
// first call of read method
if(!resultSet.next()) {
return -1; // no rows - empty input stream
} else {
buffer = converter.rowToByteArray(resultSet);
position = 0;
return buffer[position++] & (0xff);
}
} else {
// not first call of read method
if(position < buffer.length) {
// buffer already has some data in, which hasn't been read yet - returning it
return buffer[position++] & (0xff);
} else {
// all data from buffer was read - checking whether there is next row and re-filling buffer
if(!resultSet.next()) {
return -1; // the buffer was read to the end and there is no rows - end of input stream
} else {
// there is next row - converting it to byte array and re-filling buffer
buffer = converter.rowToByteArray(resultSet);
position = 0;
return buffer[position++] & (0xff);
}
}
}
} catch(final SQLException ex) {
throw new IOException(ex);
}
}
@Override
public void close() throws IOException {
try {
statement.close();
} catch(final SQLException ex) {
throw new IOException(ex);
}
}
}
これは非常に単純な実装であり、次の方法で改善できます。
- 読み取りメソッドの if と else の間のコードの重複を削除できます - 明確化のために投稿されました
- 行ごとにバイト配列バッファーを再作成する (
new byte[]
コストのかかる操作です) 代わりに、一度だけ初期化されてから再入力されるバイト配列バッファーを使用する、より洗練されたロジックを実装できます。次に、埋められたバイト数を返し、渡されたバイト配列を満たすRowToByteArrayConverter.rowToByteArray
メソッドのシグネチャを変更する必要があります。int fillByteArrayFromRow(ResultSet rs, byte[] array)
バイト配列には符号付きバイト-1
(実際に255
は符号なしバイト) が含まれているため、ストリームの末尾が正しくないことを示しているため、& (0xff)
符号付きバイトを符号なしバイトに整数値として変換するために使用されます。詳細については、Java が int をバイトに変換する方法を参照してください。.
また、ネットワーク転送速度が遅い場合、結果セットが長時間開かれたままになり、データベースに問題が生じる可能性があることにも注意してください。
お役に立てれば ...