2011-06-21 45 views
11

Estoy tratando de abrir un archivo binario para escribir sin borrar el contenido. Pero no quiero escribir para eof. Quiero escribir en una posición específica en el archivo.Escribir en el medio de un archivo binario existente C++

Aquí está un ejemplo litte:

ofstream out("test.txt", ios::binary | ios::app); 
for(int i = 0; i < 100; i++) 
    out.put('_'); 
out.write("Hallo", 5); 
out.close(); 

ofstream out2("test.txt", ios::binary | ios::app); 
out2.seekp(10); 
out2.write("Welt", 4); 
out2.close(); 

Si se utiliza la aplicación, busque no funciona. Si no se utiliza el archivo de apertura de la aplicación, se borran los datos. ¿Alguien sabe una respuesta?

Respuesta

10

aplicar el segundo sobrecarga de seekp, lo que le permite proporcionar un desplazamiento y una dirección , esto podría ser inicio de archivo en su caso (es decir ios_base::beg). Por supuesto, esto supone que sabes lo que estás haciendo y lo único que quieres hacer es sobrescribir una cantidad existente de caracteres.

EDIT: aquí está funcionando plenamente ejemplo:

#include <iostream> 
#include <fstream> 

using namespace std; 
int main() 
{ 
    { 
    ofstream out("test.txt", ios::binary); 
    for(int i = 0; i < 100; i++) 
     out.put('_'); 
    out.write("Hallo", 5); 
    } 

    { 
    fstream out2("test.txt", ios::binary | ios::out | ios::in); 
    out2.seekp(10, ios::beg); 
    out2.write("Welt", 4); 
    } 
} 
+0

Acabo de probar out2.seekp (10, ios_base :: beg) ;. Eso no cambia nada. –

+0

No debe borrar el archivo a menos que especifique ios :: trunc – crashmstr

+0

@crashmstr, tiene usted razón. Estoy borrando mi comentario. –

5

No se puede extender mágicamente el archivo desde el centro. Tal vez sea más fácil escribir en un nuevo archivo: primero copie el segmento inicial, luego escriba sus datos nuevos y luego copie el segmento restante. Cuando todo está hecho, puede sobrescribir el archivo original.

+0

No quiero extender el archivo en el medio. ¡Quiero sobrescribir los valores iniciales! –

+0

@Jonny: Eso no es lo que dijiste en tu pregunta. Usted dijo "sin borrar el contenido". De lo contrario, es trivial, solo abre para escribir (sin "agregar"), busca al principio y escribe. –

+0

No quiero escribir desde el principio. Quiero escribir en algún lugar del archivo. El problema es abrir nuevamente el archivo borrará el contenido. Por ejemplo: Archivo al principio: ______________________ Archivo después de la manipulación: ______Bla_______ –

5

Al abrir con ios :: aplicación, es como si se abre un nuevo archivo que acaba de pasar a ser unido a un archivo existente: se no puede acceder al archivo existente. No estoy seguro, porque haría lo mismo que en la respuesta de Kerrek, pero si realmente quieres probar, probablemente tengas que abrir con "ios :: in | ios :: out", similar a fopen ("test. txt "," rw ").

O como crashmstr señala: ios :: out podría ser suficiente.

+4

necesita '' ios :: out' y 'ios :: in', de lo contrario, simplemente sobrescribe methinks .. – Nim

+0

Sí porque' ios :: out' solo da como resultado una llamada abierta del siguiente tipo en Linux : O_WRONLY | O_CREAT | O_TRUNC, mientras combina 'ios :: out | ios :: in' da como resultado una llamada O_RDWR, sin el O_TRUNC. – daminetreg

2

De acuerdo con la especificación de fstream aquí

fstream::open

la aplicación ios :: "conjuntos de indicadores de la posición de la corriente hasta el final de la corriente antes de cada operación de salida." Entonces ios :: aplicación no funciona para reemplazar, busca de cualquier tipo falla, al menos para mí.

El solo uso de ios :: out borra el contenido del archivo conservando solo el tamaño, básicamente convirtiendo el archivo en basura.

ios :: in | ios :: out resultó ser lo único que funcionaba para mí.

0

Código de trabajo: Este código busca una cadena (OLD-STRING) en cout.exe y reemplaza con una nueva cadena (NEW-STRING).

`#include "stdafx.h" 
#include <iostream> 
#include <fstream> 
#include <string> 

using namespace std; 

int main(int argc, char *argv[]) 
{ 
    fstream ifs; 
    ifs.open ("C:\\Users\\user\\Desktop\\cout.exe", fstream::binary | fstream::in | fstream::out); 

    std::string str((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>()); 

    size_t pos = str.find("OLD-STRING"); 

    if (pos != string::npos) 
    { 
    cout << "string found at position: " << int(pos) << endl; 

    ifs.seekp(pos); 

    ifs.write("NEW-STRING", 10); 

    } 
    else 
    { 
    cout << "could not find string" << endl; 
    } 

    if (ifs.is_open()) 
    ifs.close(); 

    return 0; 
}` 
Cuestiones relacionadas