2011-06-21 69 views
11

Tôi đang cố mở tệp nhị phân để ghi mà không xóa nội dung. Nhưng tôi không muốn viết thư cho eof. Tôi muốn ghi vào một vị trí cụ thể trong hồ sơ.Ghi vào giữa tệp nhị phân hiện có C++

Dưới đây là một ví dụ 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(); 

Nếu sử dụng ứng dụng, tìm kiếm không hoạt động. Nếu không sử dụng tệp mở ứng dụng sẽ xóa dữ liệu. Có ai biết câu trả lời không?

Trả lời

10

thử quá tải thứ hai của seekp, cho phép bạn để cung cấp một bù đắp và một hướng, điều này có thể được khởi điểm của tập tin trong trường hợp của bạn (ví dụ: ios_base::beg). Điều này tất nhiên giả định bạn biết những gì bạn đang làm và tất cả những gì bạn muốn làm là ghi đè lên một số ký tự hiện có.

EDIT: đây là hoàn toàn ví dụ làm việc:

#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

Tôi vừa thử out2.seekp (10, ios_base :: beg) ;. Điều đó không thay đổi bất cứ điều gì. –

+0

Không nên xóa tệp trừ khi bạn chỉ định ios :: trunc – crashmstr

+0

@crashmstr, bạn nói đúng. Tôi đang xóa nhận xét của mình. –

5

Bạn không thể mở rộng tệp một cách kỳ diệu từ giữa. Có lẽ dễ nhất để ghi vào một tệp mới: Trước tiên hãy sao chép phân đoạn ban đầu, sau đó ghi dữ liệu mới của bạn, sau đó sao chép phân đoạn còn lại. Khi tất cả được thực hiện, bạn có thể ghi đè lên tập tin gốc.

+0

Tôi không muốn mở rộng tệp ở giữa. Tôi muốn ghi đè lên các giá trị sinh dục! –

+0

@Jonny: Đó không phải là những gì bạn đã nói trong câu hỏi của bạn. Bạn đã nói "mà không xóa nội dung". Nếu không nó là tầm thường, chỉ cần mở để viết (mà không cần "nối thêm"), tìm cách bắt đầu và viết. –

+0

Tôi không muốn ghi vào đầu. Tôi muốn viết một nơi nào đó trong tập tin. Sự cố đang mở lại tệp sẽ xóa nội dung. Ví dụ: Tệp ở đầu: ______________________ Tệp sau khi thao tác: ______Bla_______ –

5

Khi mở với ios :: app, đó là, nếu bạn mở một tập tin mới mà chỉ tình cờ được gắn vào một tập tin hiện có: bạn không thể truy cập tệp hiện có. Tôi không chắc chắn, bởi vì tôi sẽ làm như trong câu trả lời của Kerrek, nhưng nếu bạn thực sự muốn thử, bạn có thể phải mở với "ios :: in | ios :: out", tương tự như fopen ("kiểm tra. txt "," rw ").

Hoặc như điểm cố định: ios :: out có thể là đủ.

+4

bạn cần cả 'ios :: out' và' ios :: in', nếu không, nó chỉ ghi đè lên liên kết. – Nim

+0

Có vì 'ios :: out' đơn độc dẫn đến cuộc gọi mở của loại sau trên linux : O_WRONLY | O_CREAT | O_TRUNC, trong khi kết hợp 'ios :: out | ios :: in' kết quả trong một cuộc gọi O_RDWR, không có O_TRUNC. – daminetreg

2

Theo đặc điểm kỹ thuật của fstream đây

fstream::open

ios :: app "Thiết lập chỉ báo vị trí của dòng đến cuối dòng trước MỖI hoạt động ngõ ra." Vì vậy, ứng dụng ios :: không hoạt động để thay thế, tìm kiếm bất kỳ loại lỗi nào, ít nhất là đối với tôi.

Chỉ cần sử dụng ios :: out sẽ xóa nội dung tệp chỉ giữ nguyên kích thước, về cơ bản chuyển tệp vào thùng rác.

ios :: in | ios :: hóa ra là điều duy nhất làm việc cho tôi.

0

Mã hoạt động: Mã này tìm kiếm một chuỗi (OLD-STRING) trong cout.exe và thay thế bằng một chuỗi mới (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; 
}` 
Các vấn đề liên quan