Trying to read a binary data file in the assets directory of android app:
void loadFile(InputStream filein){
log(filein.available()); // returns 11310099
int a = filein.read(); // returns -1 (i.e. EOF)
}
// Function was called using:
loadFile(context.getAssets().open("filename.dat"));
So if available() correctly returns that there is 11MB of data available in the filehandle, how can read() immediately return -1 as soon as I try to read the first byte?
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
Recently started exploring nanopb - apology if my questions sound sily. I faced some issues while assigning and retrieval of strings and integers when I modified simple example of nanopb. Let me give my steps before my questions -
I defined simple.proto file
message Device{
optional string devid =1;
optional string mac = 2;
optional string cpu=3 [default = "x86"] ;
optional bool isSecured=4;
optional int32 uptime = 5 [default = 1234];
}
Also defined simple.option
Device.devid max_size:64
Device.cpu max_size:64
Then I compiled as usual : protoc -osimple.pb simple.proto
Here is my code :
3a) Using same string encode decode utility function as in How to encode a string when it is a pb_callback_t type
//string encode decode to pb
bool encode_string(pb_ostream_t* stream, const pb_field_t* field, void* const* arg)
{
const char* str = (const char*)(*arg);
if (!pb_encode_tag_for_field(stream, field))
return false;
return pb_encode_string(stream, (uint8_t*)str, strlen(str));
}
bool print_string(pb_istream_t *stream, const pb_field_t *field, void **arg)
{
uint8_t buffer[1024] = {0};
/* We could read block-by-block to avoid the large buffer... */
if (stream->bytes_left > sizeof(buffer) - 1)
return false;
if (!pb_read(stream, buffer, stream->bytes_left))
return false;
/* Print the string, in format comparable with protoc --decode.
* Format comes from the arg defined in main(). */
printf((char*)*arg, buffer);
return true;
}
3b) here is my main code snippet based on simple.c of example -
/* This is the buffer where we will store our message. */
uint8_t buffer[128];
size_t message_length;
bool status;
/* Encode our message */
{
/* Allocate space on the stack to store the message data, check out the contents of simple.pb.h
* good to always initialize your structures so that no garbage data from RAM in there. */
//Device message = Device_init_zero; //init zero for empty
Device message = Device_init_default; //init default for default
/* Create a stream that will write to our buffer. */
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
/* Fill in the data */
message.devid.arg = "device1";
message.devid.funcs.encode = &encode_string;
//strcpy(message.devid,"device1"); // no easier way like this ?
message.isSecured = true; // should be 1 if printed with %d
message.uptime=9876; // should change, why it is not working ?
/* Now we are ready to encode the message! */
// encode stream to buffer , also get the buffer length
status = pb_encode(&stream, Device_fields, &message);
message_length = stream.bytes_written;
/* Then just check for any errors.. */
if (!status)
{
printf("Encoding failed: %s\n", PB_GET_ERROR(&stream));
return 1;
}
}
/* Now we could transmit the message over network, store it in a file etc. */
/* just decode it immediately. */
{
/* Allocate space for the decoded message. */
Device message = Device_init_zero;
/* Create a stream that reads from the buffer. */
pb_istream_t stream = pb_istream_from_buffer(buffer, message_length);
message.devid.funcs.decode = &print_string;
message.devid.arg = "before decode Device - devid: %s \n"; //works here
message.cpu.funcs.decode = &print_string;
message.cpu.arg = "before decode Device -cpu: %s \n"; //where in op?
printf("before decode isSecured %d\n",message.isSecured); // doesn't work
printf("before decode uptime %d\n",message.uptime); //doesn't work
/* Now ready to decode the message. */
// decode stream buffer into message
status = pb_decode(&stream, Device_fields, &message);
/* Check for errors... */
if (!status)
{
printf("Decoding failed: %s\n", PB_GET_ERROR(&stream));
return 1;
}
/* Print the data contained in the message. */
message.devid.funcs.decode = &print_string;
message.devid.arg = "after decode Devic - devid: %s \n"; // doesn't work here
printf(" after decode isSecured %d\n",message.isSecured); // prints default 0
printf(" after decode uptime %d\n",(int)message.uptime); //prints default assigned in proto
}
The output after build and run :
$ ./simple
before decode isSecured 0
before decode uptime 0
before decode Device - devid: device1
after decode isSecured 0
after decode uptime 1234
My queries ( also added my inline comments in code) :
In original simple.c message.lucky_number=13 assignment works but here message.uptime assignment is not working , it is taking default value. Similarly assigning boolean value to message.isSecured is not working. Please tell where is my fault.
I used Device_init_default before pb_encode as some have default values and Device_init_zero before pb_decode call as it will populate after decode. Is my approach correct ?
Is there any simpler way to assign string value using strcpy and printing it in C way by printf("%s",strvar) apart from the encode_string and decode_string util ?
The string is printed only before pb_decode call but uptime default value is printed after pb_decode call. Also boolean value assignment is not working. Why ? What is my mistake ?
I saw encode string and int functions in https://github.com/nanopb/nanopb/blob/master/tests/callbacks/encode_callbacks.c
How to encode and decode float and boolean ?
Thanks in anticipation
In original simple.c message.lucky_number=13 assignment works but here message.uptime assignment is not working , it is taking default value. Similarly assigning boolean value to message.isSecured is not working. Please tell where is my fault.
If you look into the generated .pb.h file, you'll find that every optional field has a boolean has_field. You'll have to set that to true also, to signify that the field is present.
I used Device_init_default before pb_encode as some have default values and Device_init_zero before pb_decode call as it will populate after decode. Is my approach correct ?
That's fine.
Is there any simpler way to assign string value using strcpy and printing it in C way by printf("%s",strvar) apart from the encode_string and decode_string util ?
Because you have already set a max_size for your string fields, they should be generated as a char array instead of callbacks. You can try passing -v switch like: ../generator/nanopb_generator.py -v simple.pb to see more verbose messages that can point out why the option is not applying. Perhaps the file name is incorrect or the message name is incorrect.
The string is printed only before pb_decode call but uptime default value is printed after pb_decode call. Also boolean value assignment is not working. Why ? What is my mistake ?
I saw encode string and int functions in https://github.com/nanopb/nanopb/blob/master/tests/callbacks/encode_callbacks.c How to encode and decode float and boolean ?
Well, usually you wouldn't have to resort to callbacks. But if you decide you need them, you can encode booleans with pb_encode_varint() and floats with pb_encode_fixed32(). For studying callbacks, the protobuf encoding documentation and this test case can be helpful.
You may find the network_server example useful to study.
Also, the Stack Overflow format works best when you have only a single question per post. That way the questions and answers remain focused and easy to follow.
I'm writing an Windows phone application with C++/CX. The function tries to copy input array to output array asynchronously:
IAsyncAction CopyAsync(const Platform::Array<byte, 1>^ input, Platform::WriteOnlyArray<byte, 1>^ output)
{
byte *inputData = input->Data;
byte *outputData = output->Data;
int byteCount = input->Length;
// if I put it here, there is no error
//memcpy_s(outputData, byteCount, inputData, byteCount);
return concurrency::create_async([&]() -> void {
memcpy_s(outputData, byteCount, inputData, byteCount); // access violation exception
return;
});
}
This function compiles but cannot run correctly and produces an "Access violation exception". How can I modify values in the output array?
This is Undefined Behaviour: by the time you use your 3 captured (by reference) variables inputData/outputData/byteCount in the lambda, you already returned from CopyAsync and the stack has been trashed.
It's really the same issue as if you returned a reference to a local variable from a function (which we know is evil), except that here the references are hidden inside the lambda so it's a bit harder to see at first glance.
If you are sure that input and output won't change and will still be reachable between the moment you call CopyAsync and the moment you run the asynchronous action, you can capture your variables by value instead of by reference:
return concurrency::create_async([=]() -> void {
// ^ here
memcpy_s(outputData, byteCount, inputData, byteCount);
return;
});
Since they're only pointers (and an int), you won't be copying the pointed-to data, only the pointers themselves.
Or you could just capture input and output by value: since they're garbage-collected pointers this will at least make sure the objects are still reachable by the time you run the lambda:
return concurrency::create_async([=]() -> void {
memcpy_s(output->Data, input->Length, input->Data, input->Length);
return;
});
I for one prefer this second solution, it provides more guarantees (namely, object reachability) than the first one.
I am using json-c library to send json-object to client.And I notice there is no native function to release the memory which json_object_to_json_string allocate.Does the library release it automaticlly? OR I have to "free(str)" to avoid memory leak?
I tried to read its source code but it makes me unconscious...So anybody know this?
It seems that you don't need to free it manually.
I see that this buffer comes from within the json_object (see the last line of this function):
const char* json_object_to_json_string_ext(struct json_object *jso, int flags)
{
if (!jso)
return "null";
if ((!jso->_pb) && !(jso->_pb = printbuf_new()))
return NULL;
printbuf_reset(jso->_pb);
if(jso->_to_json_string(jso, jso->_pb, 0, flags) < 0)
return NULL;
return jso->_pb->buf;
}
The delete function frees this buffer:
static void json_object_generic_delete(struct json_object* jso)
{
#ifdef REFCOUNT_DEBUG
MC_DEBUG("json_object_delete_%s: %p\n",
json_type_to_name(jso->o_type), jso);
lh_table_delete(json_object_table, jso);
#endif /* REFCOUNT_DEBUG */
printbuf_free(jso->_pb);
free(jso);
}
It is important to understand that this buffer is only valid while the object is valid. If the object reaches 0 reference count, the string is also freed and if you are using it after it is freed the results are unpredictable.
I am trying to delete all the temporary files created by my application during uninstall. I use the following code:
bool DeleteFileNow( QString filenameStr )
{
wchar_t* filename;
filenameStr.toWCharArray(filename);
QFileInfo info(filenameStr);
// don't do anything if the file doesn't exist!
if (!info.exists())
return false;
// determine the path in which to store the temp filename
wchar_t* path;
info.absolutePath().toWCharArray(path);
TRACE( "Generating temporary name" );
// generate a guaranteed to be unique temporary filename to house the pending delete
wchar_t tempname[MAX_PATH];
if (!GetTempFileNameW(path, L".xX", 0, tempname))
return false;
TRACE( "Moving real file name to dummy" );
// move the real file to the dummy filename
if (!MoveFileExW(filename, tempname, MOVEFILE_REPLACE_EXISTING))
{
// clean up the temp file
DeleteFileW(tempname);
return false;
}
TRACE( "Queueing the OS" );
// queue the deletion (the OS will delete it when all handles (ours or other processes) close)
return DeleteFileW(tempname) != FALSE;
}
My application is crashing. I think its due to some missing windows dll for the operations performed. Is there any other way to perform the same operation using Qt alone?
Roku have already told your problem in manipulating with QString and wchar_t*.
See the documentation: QString Class Reference, method toWCharArray:
int QString::toWCharArray ( wchar_t * array ) const
Fills the array with the data contained in this QString object. The array is encoded in utf16 on platforms where wchar_t is 2 bytes wide (e.g. windows) and in ucs4 on platforms where wchar_t is 4 bytes wide (most Unix systems).
array has to be allocated by the caller and contain enough space to hold the complete string (allocating the array with the same length as the string is always sufficient).
returns the actual length of the string in array.
If you are simply looking for a way to remove a file using Qt, use QFile::remove:
QFile file(fileNameStr);
file.remove(); // Returns a bool; true if successful
If you want Qt to manage the entire life cycle of a temporary file for you, take a look at QTemporaryFile:
QTemporaryFile tempFile(fileName);
if (tempFile.open())
{
// Do stuff with file here
}
// When tempFile falls out of scope, it is automatically deleted.
i'm trying to read a CAF-file on OSX, using AudioToolbox's Extended Audio File API.
opening the file works fine, however, i need to access the UUID chunk, and i cannot find any reference on how to do that (or how to access any header-chunk of the file)
surely there must be a way to do this without parsing the file on my own.
PS: i can already do this with libsndfile, but i want to find a way to do this with only components that come with OSX.
i already tried calling ExtAudioFileGetProperty() with the ExtAudioFilePropertyID set to 'uuid' but this doesn't seem to work.
it turned out that the trick is not to use the ExtAudio API for accessing low-level functionality like the UUID chunk. (if you need to access the file via ExtAudio API, it's possible to create an ExtAudioHandle from an AudioFileID.)
in the end i used something like this:
AudioFileID fileID;
ExtAudioFileRef extFile;
OSStatus err = AudioFileOpenURL((CFURLRef)inURL, kAudioFileReadPermission, 0, &fileID);
if(noErr!=err)return;
err = ExtAudioFileWrapAudioFileID (fileID, false, &extFile); // in case we *also* want to access the file via ExtAudio
if(noErr!=err)return;
for(index=0; ; index++) {
UInt32 size=0;
char*data=NULL;
OSStatus err = AudioFileGetUserDataSize (fileID,'uuid',index,&size);
if(noErr!=err)break; // check whether we were able to read the chunksize
if(0==size)continue; // check whether there is some payload in the uuid chunk
data=calloc(size, 1);
if(!data)continue;
err = AudioFileGetUserData (fileID, 'uuid', index, &size, data);
if(noErr!=err){free(data); break;} // check whether we were able to read the chunksize
/* ... */
free(data);
}
ExtAudioFileDispose(extFile);
AudioFileClose(fileID);