Pregunta

He estado revisando la descripción del formato y el código fuente para el formato de archivo 7z, pero todavía tengo problemas para escribir un contenedor válido. Supongo que puedo crear un contenedor vacío ... de todos modos, aquí está mi inicio:

std::ofstream ofs(archivename.c_str(), std::ios::binary|std::ios::trunc);

Byte signature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
Byte major = 0;
Byte minor = 3;

ofs.write((const char*)signature, 6);
ofs.write((const char*)major, 1);
ofs.write((const char*)minor, 1);

UInt64 offset = 0;
UInt64 size = 0;
UInt32 crc = 0;

ofs.write((const char*)offset, 4);
ofs.write((const char*)size, 8);
ofs.write((const char*)crc, 8);
ofs.write((const char*)CrcCalc(0, 0), 8);

ofs.close();

Creo que mi principal problema es la falta de comprensión de std :: ofstream :: write (). Byte es un "carácter sin signo", UInt64 & Amp; UInt32 son 'largos sin signo'.

UPDATE0 : Como todos señalan, sería un problema si ejecutara esto en una máquina big-endian. Ese no es el caso aquí. Según Fredrik Janssen, debería emitir la dirección de los no arrays. También debo mencionar que CrcCalc () es una función en el SDK de LZMA. Agregando & Amp; ayuda un poco, es ese primer personaje sin firmar [6] el que tiene algunos problemas.

ACTUALIZACIÓN1 : Código de trabajo para obtener un archivo de almacenamiento vacío a continuación.

static void SetUInt32(Byte *p, UInt32 d)
{
  for (int i = 0; i < 4; i++, d >>= 8)
    p[i] = (Byte)d;
}

static void SetUInt64(Byte *p, UInt64 d)
{
  for (int i = 0; i < 8; i++, d >>= 8)
    p[i] = (Byte)d;
}

void make_7z_archive()
{
  CrcGenerateTable();

  std::ofstream ofs(archivename.c_str(), std::ios::binary|std::ios::trunc);

  Byte signature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
  Byte major = 0;
  Byte minor = 3;

  ofs.write((const char*)signature, 6);
  ofs.write((const char*)&major, 1);
  ofs.write((const char*)&minor, 1);

  UInt64 offset = 0;
  UInt64 size = 0;
  UInt32 crc = 0;

  Byte buf[24];
  SetUInt64(buf + 4, offset);
  SetUInt64(buf + 12, size);
  SetUInt32(buf + 20, crc);
  SetUInt32(buf, CrcCalc(buf + 4, 20));

  ofs.write((const char*)buf, 24);

  ofs.close();
}

NOTA: CrcGenerateTable () y CrcCalc () son del SDK de LZMA.

¿Fue útil?

Solución

no conozco el formato de 7z, pero cuando escribo offset, size y crc noto que estos se escribirán en el archivo en formato little-endian (supongo que tiene una CPU little-endian).

Editar: Probablemente peor, te falta el amplificador &; antes de mayor, menor, desplazamiento, tamaño y crc, es decir, está convirtiendo los valores reales en un puntero.

Otros consejos

Uh ... estoy confundido. Tiene un SDK ... que mencionas en tu publicación ... también el Las fuentes 7-zip están en línea . vea también p7zip en SourceForge. Acabo de mirar las fuentes para p7zip y hay un montón de archivos que comienzan con & "; 7z &"; parece que harían el truco.

No he usado el formato 7z programáticamente (solo a través de la línea de comandos util / GUI), pero ¿por qué necesitaría manejar esas cosas de bajo nivel usted mismo en lugar de hacerlo a través del SDK? (que no sea por la licencia LGPL)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top