【问题标题】:C++:How to reading a binary file in a thread and writing it in another thread?C++:如何在一个线程中读取二进制文件并在另一个线程中写入?
【发布时间】:2019-11-16 17:44:32
【问题描述】:

我想在一个线程中读取二进制文件并在另一个线程中写入它。它适用于小文件(如 txt 文件)但不适用于大文件(如 jpg 文件)。我尝试在向量中存储缓冲区,但它像队列一样工作。

#include <iostream>
#include <thread>
#include <queue>
#include <fstream>
#include <unistd.h>
#include <mutex>
#include <string>
using namespace std;

std::mutex mtx;

vector<char *> q;
const int MAX_QUEUE_LENGTH = 100;
int string_size(char * str)
{
    int Size = 0;
    while (str[Size] != '\0') Size++;
    return Size;
}

void readFile()
{
  ifstream file;
  file.open("in.jpg", ios::binary);
  file.seekg(0, ios::end);
  int length = file.tellg();
  cout << length;
  file.seekg(0, ios::beg);

  while (true) {
    mtx.lock();

    if (q.size() > MAX_QUEUE_LENGTH) {
      mtx.unlock();
      sleep(10);
      continue;

    }

    if (length - file.tellg() <= 1024) {
      int tmp = length - file.tellg();
      char *c = new char[tmp];
      file.read(c,tmp);
      q.push_back(c);
      mtx.unlock();
      break;
    } else {
      char *c = new char[1024];
      file.read(c,1024);
      q.push_back(c);
      mtx.unlock();
    } 

  }

  file.close();
}

void writeFile() {
  ofstream o;
  o.open("out.jpg", ios::binary);

  while (true) {
    mtx.lock();
    if(q.empty()) {
      mtx.unlock();
      sleep(5); 
      mtx.lock();
    }

    if(q.empty()) break;
    o.write(q.front(), string_size(q.front()));
    q.erase(q.begin());
    mtx.unlock();
  }

  o.close();
}
int main() {
  thread th_in(readFile);
  thread th_out(writeFile);
  th_in.join();
  th_out.join();
}

【问题讨论】:

  • 与其手动使用std::mutex::lock()std::mutex::unlock(),不如考虑使用std::lock_guard
  • 解释您的问题“它不起作用”。碰撞?输出错误?
  • 输出错误!!! out.jpg 应该是图片,但它是奇怪的符号字符串!

标签: c++ multithreading file binary


【解决方案1】:

主要问题是在writeFile 函数中调用了string_size。为什么您认为在 JPG 流内容中不能出现空字节?假设您读取第一个块 - 1024 字节,在第 10 个位置具有 0 值,该块排队到 q,然后在写入时调用 string_size 返回 10,并且该块的其余部分不写入文件 -并且永远不会被写入,因为 erase 被调用到 q

您可以将pair 存储为指向块数据及其长度的指针:

vector< std::pair< char *, int> > q;

然后在readFile:

if (length - file.tellg() <= 1024) {
  int tmp = length - file.tellg();
  char *c = new char[tmp];
  file.read(c,tmp);
  q.emplace_back(c,tmp); // <--- added
  mtx.unlock();
  break;
} else {
  char *c = new char[1024];
  file.read(c,1024);
  q.emplace_back(c,1024); // <--- added
  mtx.unlock();
}

writeFile:

if(q.empty()) { mtx.unlock(); break; } // in this place unlock should also be called
o.write(q.front().first, q.front().second); // <--added
q.erase(q.begin());

除了将原始指针存储在 q 之外,还可以考虑使用像 unique_ptr 这样的智能指针。

【讨论】:

  • 谢谢。但它不适用于我的 jpg 文件 :(。你知道错误在哪里吗?
【解决方案2】:

看看你的这段代码:

while (true) {
    mtx.lock();

    if (q.size() > MAX_QUEUE_LENGTH) {
      mtx.unlock();
      sleep(5);
      mtx.lock();
      continue;
    }
....
}

如果if 为真,则将互斥锁两次锁定在continue 之前,然后在while 块的开头。

mutex doc 说这是未定义的行为。

【讨论】:

  • 谢谢。我编辑了代码,但它仍然不起作用:(。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-01
  • 1970-01-01
  • 2015-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多