Discussion:
[soci-users] Problem to store binary data into blob
Ulrich Heinicke
2013-03-14 09:19:36 UTC
Permalink
Hi,

i try to store a pdf-files into the blob, read it from the table and store it on the file system. After that I compare the source pdf-file with the reading file and find differences.

My code is:

backend_factory const &backEnd = *soci::factory_oracle();

bool read(const std::string inputfilename)
{
std::cout << "Read: " << inputfilename << "\n";
try
{
session sql(backEnd, connectString);

sql << "select max(id) from soci_blob", into(idx);

idx++;

std::ifstream is(inputfilename.c_str(), std::ifstream::binary);
if (is)
{
// get length of file:
is.seekg (0, is.end);
int length = is.tellg();
is.seekg (0, is.beg);

char * buffer = new char [length];

std::cout << "Reading " << length << " characters... ";
// read data as a block:
is.read (buffer,length);

if (is)
std::cout << "all characters read successfully.\n";
else
std::cout << "error: only " << is.gcount() << " could be read\n";
is.close();

std::ofstream os("test.xx", std::ofstream::binary);
os.write (buffer,length);
os.close();

sql << "insert into soci_blob (id, img) values (:id, empty_blob())", use(idx);

sql.commit();

transaction tr(sql);

blob b(sql);

oracle_session_backend *sessionBackEnd = static_cast<oracle_session_backend *>(sql.get_backend());

oracle_blob_backend *blobBackEnd = static_cast<oracle_blob_backend *>(b.get_backend());

OCILobDisableBuffering(sessionBackEnd->svchp_, sessionBackEnd->errhp_, blobBackEnd->lobp_);

sql << "select img from soci_blob where id = :id for update", use(idx), into(b);
assert(b.get_len() == 0);

// note: blob offsets start from 1
b.write(1, buffer, sizeof(buffer));

sql << "update soci_blob set length = :length where id = :id", use(length), use(idx);

tr.commit();

std::cout << "all characters saved successfully.\n";

delete[] buffer;
}
}
catch (oracle_soci_error const & e)
{
std::cerr << "Oracle error: " << e.err_num_ << " " << e.what() << std::endl;

return false;
}
return true;
}

bool write(const std::string outputfilename)
{
std::cout << "Write: " << outputfilename << "\n";

try
{
session sql(backEnd, connectString);
std::ofstream outfile(outputfilename.c_str(), std::ofstream::binary);
if(outfile)
{
// get size of file
long size;

sql << "select length from soci_blob where id = :id", use(idx), into(size);

std::cout << "Writing " << size << " characters... ";

// allocate memory for file content
char* buffer = new char[size];

blob b(sql);
sql << "select img from soci_blob where id = :id", use(idx), into(b);
b.read(1, buffer, size);

// write to outfile
outfile.write (buffer,size);

// release dynamically-allocated memory
delete[] buffer;

outfile.close();
}
}
catch (oracle_soci_error const & e)
{
std::cerr << "Oracle error: " << e.err_num_ << " " << e.what() << std::endl;

return false;
}
return true;
}

int main(int argc, char** argv)
{
if(argc < 3)
{
std::cout << "usage: " << argv[0]
<< " inputfilename outputfilename\n"
<< "example: " << argv[0]
<< " Test.pdf read.pdf\n";
std::exit(1);
}
else
{
connectString = "service=" + servicename + " user=" + username + " password=" + password;
std::cout << connectString << "\n";

if(read(argv[1]))
{
write(argv[2]);
}
}
return 0;
}

When I use text files I get no compare errors.


Mit freundlichem Gruß
Ulrich Heinicke
--
______________________________________________

DAVID Software GmbH - Wendenring 1 - 38114 Braunschweig

Tel.: +49 531 24379-73
Fax.: +49 531 24379-79

E-Mail: mailto:***@david-software.de
WWW: http://www.david-software.de

Eintragung: Amtsgericht Braunschweig, HRB 3167
Geschäftsführer: Frank Ptok
______________________________________________
Mateusz Loskot
2013-03-17 14:01:46 UTC
Permalink
On 14 March 2013 09:19, Ulrich Heinicke
Post by Ulrich Heinicke
i try to store a pdf-files into the blob, read it from the table and store
it on the file system. After that I compare the source pdf-file with the
reading file and find differences.
There may be numerous factors affecting the binary data written
and read, how you perform the actual comparison, etc.
As I mentioned, I'm not experienced with Oracle BLOBs myself,
so nothing particular comes to mind.

Perhaps, you could your comparison test with Python's cx_Oracle.
That could be helpful to confirm if SOCI Oracle behaviour diverges.
I actually was curious and tried to do it myself,
but I've got stuck during installation
https://sourceforge.net/mailarchive/message.php?msg_id=30603651

Best regards,
--
Mateusz Loskot, http://mateusz.loskot.net

Loading...