2009-02-12 16 views
31

Có cách nào để tạo bộ nhớ đệm dưới dạng FILE * hay không. Trong TiXml nó có thể in xml thành một FILE * nhưng tôi không thể làm cho nó in ra một bộ nhớ đệm.Làm cách nào để ghi vào bộ nhớ đệm bằng FILE *?

+1

Cũng xem [Sự khác nhau giữa fmemopen và open_memstream] (https: // stackoverflow .com/q/29849749/608639). – jww

Trả lời

2

Bạn có thể sử dụng phương pháp CStr của TiXMLPrinter mà tài liệu khẳng định:

Các TiXmlPrinter rất hữu ích khi bạn cần phải:

  1. Print để nhớ (đặc biệt là trong chế độ không STL)
  2. Định dạng điều khiển (kết thúc dòng, v.v.)
16

Tôi đoán câu trả lời đúng là bởi Kevin. Nhưng đây là một hack để làm điều đó với FILE *. Lưu ý rằng nếu kích thước bộ đệm (ở đây 100000) quá nhỏ thì bạn sẽ mất dữ liệu, vì nó được ghi ra khi bộ đệm bị xóa. Ngoài ra, nếu chương trình gọi fflush() bạn bị mất dữ liệu.

#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char **argv) 
{ 
    FILE *f = fopen("/dev/null", "w"); 
    int i; 
    int written = 0; 
    char *buf = malloc(100000); 
    setbuffer(f, buf, 100000); 
    for (i = 0; i < 1000; i++) 
    { 
     written += fprintf(f, "Number %d\n", i); 
    } 
    for (i = 0; i < written; i++) { 
     printf("%c", buf[i]); 
    } 
} 
+0

hack dễ dàng - bất kỳ ý tưởng nào nếu nó di động? –

+0

Nó chỉ hoạt động nếu có thể ngăn chặn stdio khỏi xả bộ đệm, và tôi đoán các chi tiết không được chuẩn hóa. –

+6

'setbuf()' và 'setvbuf()' (NOT 'setbuffer()') là ISO-C, vì vậy nó * nên * được di chuyển khi bạn sử dụng chúng. Nếu chế độ đệm được đệm đầy đủ, nó nên cố gắng lấp đầy bộ đệm hoàn toàn; trên cửa sổ, bạn phải sử dụng "NUL" thay vì "/ dev/null"; bạn cũng nên mở tệp ở chế độ nhị phân "wb" – Christoph

8

fmemopen có thể tạo TẬPTIN từ bộ đệm, bạn có cảm thấy điều đó không?

4

Tôi đã viết một ví dụ đơn giản làm thế nào tôi sẽ tạo ra một tập tin trong bộ nhớ:

#include <unistd.h> 
#include <stdio.h> 

int main(){ 
    int p[2]; pipe(p); FILE *f = fdopen(p[1], "w"); 

    if(!fork()){ 
    fprintf(f, "working"); 
    return 0; 
    } 

    fclose(f); close(p[1]); 
    char buff[100]; int len; 
    while((len=read(p[0], buff, 100))>0) 
    printf(" from child: '%*s'", len, buff); 
    puts(""); 
} 
54

Có một cách POSIX để sử dụng bộ nhớ như một mô tả FILE: fmemopen hoặc open_memstream, tùy thuộc vào ngữ nghĩa bạn muốn: Difference between fmemopen and open_memstream

+8

Không có fmemopen, cũng như open_memstream được định nghĩa trong bất kỳ tiêu chuẩn C/C++ nào! – MFH

+0

@MFH POSIX 200809 – tbert

+13

POSIX KHÔNG phải là tiêu chuẩn C/C++! Đó là một tiêu chuẩn phụ thuộc nhiều vào tiêu chuẩn C, nhưng dù sao chỉ hoạt động trên một tập con của các hệ điều hành được hỗ trợ bởi/phát triển trong C/C++! Chưa kể rằng POSIX xung đột với các khía cạnh nhất định của tiêu chuẩn C/C++ ... – MFH

0

C++ basic_streambuf thừa kế

Trong C++, bạn nên tránh FILE* nếu bạn có thể.

Chỉ sử dụng C++ stdlib, nó có thể để thực hiện một giao diện duy nhất mà minh bạch sử dụng tập tin hoặc bộ nhớ IO.

này sử dụng kỹ thuật đề cập tại địa chỉ: Setting the internal buffer used by a standard stream (pubsetbuf)

#include <cassert> 
#include <cstring> 
#include <fstream> 
#include <iostream> 
#include <ostream> 
#include <sstream> 

/* This can write either to files or memory. */ 
void write(std::ostream& os) { 
    os << "abc"; 
}  

template <typename char_type> 
struct ostreambuf : public std::basic_streambuf<char_type, std::char_traits<char_type> > { 
    ostreambuf(char_type* buffer, std::streamsize bufferLength) { 
     this->setp(buffer, buffer + bufferLength); 
    } 
}; 

int main() { 
    /* To memory, in our own externally supplied buffer. */ 
    { 
     char c[3]; 
     ostreambuf<char> buf(c, sizeof(c)); 
     std::ostream s(&buf); 
     write(s); 
     assert(memcmp(c, "abc", sizeof(c)) == 0); 
    } 

    /* To memory, but in a hidden buffer. */ 
    { 
     std::stringstream s; 
     write(s); 
     assert(s.str() == "abc"); 
    } 

    /* To file. */ 
    { 
     std::ofstream s("a.tmp"); 
     write(s); 
     s.close(); 
    } 

    /* I think this is implementation defined. 
    * pusetbuf calls basic_filebuf::setbuf(). */ 
    { 
     char c[3]; 
     std::ofstream s; 
     s.rdbuf()->pubsetbuf(c, sizeof c); 
     write(s); 
     s.close(); 
     //assert(memcmp(c, "abc", sizeof(c)) == 0); 
    } 
} 

Thật không may, nó dường như không thể trao đổi FILE*fstream: Getting a FILE* from a std::fstream

Các vấn đề liên quan