1

I'm trying to write to a file and want to use Write System Call to make it faster. Basically I have a QVector and I want to store the results in a file. Originally I was just iterating through the array but it's too slow. So I did some research and found something called Write System Call, but I can't figure out how to set up the code.

This is what I have tried so far:

/*Header File*/

QVector<unsigned short> rawData;

/*Implementation File*/

int fd = open("output.txt", O_WRONLY)L
write(fd, &rawData, rawData.size());
close(fd);

While the above code does not crash on me it doesn't actually write anything to the output file. Any ideas what I'm doing wrong?

EDIT:

Using fwrite I am able to write to the file but the data in the file is some strange Unicode. Basically it's not number which is what I'm trying to get. Here is what I'm doing:

FILE * pFile;

pfile = fopen("pixelValues.txt", "wb");

fwrite(&rawData, sizeof(unsigned short), sizeof(rawData), pFile);

fclose(pFile);
demonplus
  • 5,613
  • 12
  • 49
  • 68
Angel Lockhart
  • 157
  • 1
  • 2
  • 11
  • What's the declaration of `rawData`? – Barmar Dec 24 '16 at 22:02
  • If it's a `std::vector`, you need to use `&rawData[0]`. See http://stackoverflow.com/questions/6485496/how-to-get-stdvector-pointer-to-the-raw-data – Barmar Dec 24 '16 at 22:03
  • There's no reason you should need to use non-portable calls like write() to "make things faster" - you could use the portable fwrite() function. Also, you need to check that the file did actually open. –  Dec 24 '16 at 22:04
  • @Barmar Sorry, forgot to add that. It's there now. – Angel Lockhart Dec 24 '16 at 22:04
  • `QVector` is not a standard C++ class. – Barmar Dec 24 '16 at 22:05
  • @latedeveloper Since I'm a C++ noob can you expand on what yo mean by portable and non-portable? – Angel Lockhart Dec 24 '16 at 22:06
  • @AngelLockhart `write()` is a POSIX system call, not part of the C++ language. Don't worry about it, all modern OSes are POSIX-compliant and provide `write()`.[ – Barmar Dec 24 '16 at 22:07
  • @Angel write() is a feature of POSIX systems and is not part of Standard C++. It's therefore non-portable, as far as C++ implementations are concerned. –  Dec 24 '16 at 22:07
  • Oh so you're saying that I just flat out can't use the write command. Will `fwrite()` still give me a better runtime than just going through the `QVector` element by element and writing it to a file? Cause the reason I was even following this path was because I thought `write()` doesn't need to iterate. – Angel Lockhart Dec 24 '16 at 22:10
  • @Angel No, we are not saying that. And fwrite() and write() both take a pointer to the thing you want to write and the number of bytes to write as parameters, so they are basically interchangeable. –  Dec 24 '16 at 22:13
  • @latedeveloper So if it `write()` is an okay thing to use then why would I chose `fwrite()` over it? Sorry if I'm being stupid, I'm not used to working with this kind of low level stuff. – Angel Lockhart Dec 24 '16 at 22:17
  • @Angel It's good practice to use the highest-level, least platform-specific function that does the job well enough. This makes your code easier to move between different platforms, and the higher-level functions are often easier to use. –  Dec 24 '16 at 22:21
  • @latedeveloper I tried using `fwrite()` but the files doesn't contain numbers but some strange Unicode. Did I do it correctly? I've updated the code in my original post. – Angel Lockhart Dec 24 '16 at 22:41
  • @Angel write/fwrite both write out binary data, not human readable character strings. –  Dec 24 '16 at 22:58
  • @Angel Open the file up in a hex editor. Convert hex to decimal. It should match your numbers then. – Matthew Beck Dec 24 '16 at 23:00
  • @MatthewHooker Dose the hex editor convert the values for me? Can you recommend one that I can use to open the file and check its content? I just want to make sure that I am in fact writing to the file the correct values. – Angel Lockhart Dec 24 '16 at 23:19
  • @Angel Yes it does. http://jujusoft.com/jujuedit/ will work for you. Just note that it's an advanced notepad also. Open the file up and select BIN but hit the down arrow. Then select decimal. – Matthew Beck Dec 24 '16 at 23:29

2 Answers2

3

There is a difference between QVector the object and the elements inside it. You probably want to write the QVector elements, so in order to do that you need something like this:

template<typename T>
int writeVector(const QVector<T>& vec, int fd)
{
    // note: the size argument to write() is about the number of bytes
    // which is: (size of each element) * (number of elements to write) 
    return write(fd, vec.constData(), (sizeof(T)) * vec.size());
}

For a better solution, consider using a QDataStream instead:

template<typename T>
void writeVectorBetter(QDataStream& stream, const QVector<T>& vec)
{
    stream << vec;
}

This will also ensure you can read the information back from the file in a consistent manner.

user268396
  • 11,576
  • 2
  • 31
  • 26
1

You're assuming that you need to write your data directly using system calls. Without seeing your code I'd argue that it probably is not the case. Most likely you were doing something very obnoxiously inefficient.

You can do better: In Qt, the simplest way would be to leverage QDataStream. It will do everything necessary to give you the same vector back when you read the data later. It perfoms quite adequately:

bool write(const QString &filename, const QVector<uint16_t> &data)
{
   QSaveFile f(filename);
   if (!f.open(QIODevice::WriteOnly))
      return false;
   QDataStream s(&f);
   s.setVersion(QDataStream::Qt_5_6);
   s << data;
   return f.commit();
}

QVector<uint16_t> read(const QString &filename)
{
   QVector<uint16_t> data;
   QFile f(filename);
   if (!f.open(QIODevice::ReadOnly))
      return data;
   QDataStream s(&f);
   s.setVersion(QDataStream::Qt_5_6);
   s >> data;
   if (s.status() != QDataStream::Ok)
      data.clear();
   return data;
}

Other issues:

  1. The file is not a text file, so don't give it a .txt extension.

  2. Use types with explicit sizes, such as uint16_t or quint16 instead of unsigned short.

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313