I'm trying to download a file in Qt5, but the file must not be located on the HDD after download.
To clarify> My app will use a downloaded file to update some firmware, and I don't want the downloaded update to remain on the user's hard drive because it could get stolen.
So, I'm trying to make a QFile from QNetworkReply* but without saving it to some path on a hard drive.
I'm downloading a file using QNetworkAccessManager and storing the data into QNetworkReply. I always used to make a QFile with QNetworkReply*, but now I can't do that.
I have found the QTemporaryFile class where a file gets removed right after using it, but that still leaves user with some options of finding the file later.
I tried typecasting that QNetworkReply* as a QFile, but didn't manage to get that to work, seems like QFile can't be without a path on HDD.
Does anyone have any ideas how to do this, and how?
Thanks everyone.
Again not sure your intended end use case but since your data is small enough to hold in memory you can use a QByteArray or QBuffer and write into it from your QNetworkReply. QBuffer provides a QIODevice interface for the QByteArray so it may be a bit easier for you to work with.
Make sure to open the QBuffer for read/write. See the simple example below from the Qt documentation, http://doc.qt.io/qt-5/qbuffer.html#details, below:
QBuffer buffer;
char ch;
buffer.open(QBuffer::ReadWrite);
buffer.write("Qt rocks!");
buffer.seek(0);
buffer.getChar(&ch); // ch == 'Q'
buffer.getChar(&ch); // ch == 't'
buffer.getChar(&ch); // ch == ' '
buffer.getChar(&ch); // ch == 'r'
That should allow you to read back the data and use as required without creating a file on the system.
Related
In my program it is possible to select a sound for an action. the sound is changeable, which means the .wav file gets replaced by another file.
This may cause the problem. When i replace the file and set the source of the QSoundEffect the sound does not change.
At the moment i am having a source like this:
//variable in .h
QUrl sound = "file:///"+soundDirectory+"sound.wav";
QUrl newSound = "file:///"+soundDirectory+"newSound.wav"; ;
QSoundEffect soundeffect;
//called in setSound() in .cpp
soundEffect.setSource(sound);
the sound loads without problem and i can play that sound.
i can change that sound with this code
// changing the sound in changeSound()
soundEffect.setSource(newSound);
this also works fine. the new sound is loaded and i can play it.
But it is also possible to change the sound files in the directory:
//changeSoundFile()
QFile::remove(sound.toLocalFile());
QFile::copy(anyPossibleSound.toLocalFile(), sound.toLocalFile());
This also works and replaces the sound file in its directory with another.
If I call setSound() after changing the file. It seems like the file does not get reload. and the sound is not changed. This is also the problem if changed the sound in between (call setSound on startup, then changeSound, then changeSoundFile and the setSound again)
Am I overlooking something?
It's not mentioned in the official docs, but you can find the implementation on GitHub:
void QSoundEffect::setSource(const QUrl &url) {
if (d->source() == url)
return;
d->setSource(url);
emit sourceChanged();
}
The file does not get reloaded because the URL is the same. The implementation holds an internal cache with the data that has been loaded before, so when you play the file, nothing change.
The API does not provide a way of forcing the reset of the data source. You have two alternatives:
Re-creating the QSoundEffect instance each time you modify the file.
Changing the file name:
// Create a temporal file
const auto uuid = QUuid::createUuid();
const auto new_filename = uuid.toString() + ".wav";
// Copy the file
QFile::remove(sound.toLocalFile());
QFile::copy(anyPossibleSound.toLocalFile(), new_filename);
sound = QUrl(new_filename);
// Use it
soundEffect.setSource(sound);
I'm making an application part of which is reading from an XML which stores some preferences. However, whenever I build the project, all the sources get copied but the preferences file does not! I have added the following to the .pro file -
RESOURCES += rsc.qrc
And my rsc.qrc contains
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>data/preferences.xml</file>
<file>data/gamedata.xml</file>
</qresource>
</RCC>
Now whenever I try to open preferences.xml
QFile preferences(":/data/preferences.xml");
if(!preferences.exists()){
preferences.open(QFile::WriteOnly);
preferences.write("abc");
qDebug() << "Written";
}
else {
qDebug() << "File exists";
}
Absolutely nothing gets printed and even the rest of the application stops working.
You don't use the resource part correctly in your example.
It will most likely not work because you try to write to a resource that is embedded into your executable after you have build your application. Reading is fine, but writing can't work by definition.
If you want a editable setting files, you have to distribute them along with your executable, or use a different method for reading/writing your settings like QSettings.
However using QSettings also means, that you will need to configure all your default settings in your loading function in case the values do not exist if you use the default configuration. Meaning you use registry on windows.
You have the option to force the use of a INI file format in the constructor of QSettings, this can make sense if you want to provide a default settings INI file instead of your xml files.
In case you want to store more complex data a xml file might be needed anyway, so if you want to stick with that you will need a way to copy your setting files to your build path. This can be done within your pro file with QMAKE_POST_LINK.
Example:
COPY_CMD = "$$PWD\\data\\preferences.xml $$OUT_PWD\\release\\data\\preferences.xml"
COPY_CMD = $${QMAKE_COPY} $$replace( COPY_CMD, "/", "\\" ) $$escape_expand( \\n\\t )
QMAKE_POST_LINK += $$COPY_CMD
I can make a file and make my Qt project read and write to it .
But How can I make it create it's own text file for the first time then it writes and reads from and to it later for example i want it to write and read to and from this directory C:\Users\Administrator\Documents .
I will answer supposing that you are asking (don't know if I understood well, since your question is hardly understandable) how to create a file one time, then later, write and read from this file already created.
First, you have to give your file a name.
QString fileName = "C:\Users\Administrator\Documents\file.txt";
QFile file(fileName);
If your file is not already created : calling the function QFile::open(OpenMode mode) will create this file :
bool openOk = file.open(QIODevice::ReadWrite);
if (openOk)
{
// process
}
You can now write and read from your file.
Later, if you want to use your file again, just call this function again : if the file is already created, then you can read/write in this file.
I am working on a special application in Qt that stores its .mp3 audio files in a QSQLITE database as BLOB data.
With the following code I create a QByteArray:
QByteArray array = query->value(0).toByteArray();
Then I try to play the sound with a QMediaPlayer:
mediaPlayer.setMedia( QMediaContent( QUrl::fromEncoded(array) ) );
mediaPlayer.play();
But I unfortunately get this error:
DirectShowPlayerService::doSetUrlSource: Unresolved error code 800c000d
The main thing that I would like to achieve is to be able to play these .mp3 files that are stored in the QByteArray.
Note: Storing the pathway only in the database is not possible in that special circumstance.
I would really-very appreciate your help.
Thank you very much!
You need to provide the QByteArray as a QIODevice to the stream parameter of QMediaPlayer::setMedia(const QMediaContent & media, QIODevice * stream = 0).
Try the following:
QBuffer mediaStream(&array);
mediaPlayer.setMedia(QMediaContent(), &buffer);
mediaPlayer.play();
I have the following issue: I create a QFileSystemWatcher and it runs and works nicely on Linux, but no way on Windows 7. Can you spot anything in the code that might make it not to work?
Thx.
Here is the code to initialize it:
mConfigChangeWatcher = new QFileSystemWatcher();
mConfigChangeWatcher->addPath(config_file_name);
QObject::connect(mConfigChangeWatcher,
SIGNAL(fileChanged(QString)),
this,
SLOT(configFileChanged(QString)));
and this is supposed to be the slot getting the work done:
void MyClass::configFileChanged(const QString &file)
{
qDebug() << "Changed: " << file ;
}
When you check if the file is added to the watcher using QFileSystemWatcher::files() method after the first modification in the file do you get the correct list?
I was with the issue that some applications, when modifing a file, delete the old file from the system and write it again.
Note that QFileSystemWatcher stops monitoring files once they have been renamed or removed from disk, and directories once they have been removed from disk.
I was using QFileSystemWatcher to watch an image file edited by Photoshop. Somehow the file gets removed from the list of files being watched.
I had the same problem and solved it very fast.
Within the slot that manages the fileChanged signal I noted the path disappears from files(). I simply make a check and re-add it if necessary
if (! watcher_.files().contains(path))
{
watcher_.addPath(path);
}
I hope this helps
Fabio