2009-11-16 6 views
5

FILE *을 어떤 함수에 전달하여 함수가 fprintf으로 쓸 수있는 방법을 찾고 있습니다. 출력이 디스크의 실제 파일에 나타나기를 원한다면 이렇게하는 것이 쉽습니다. 하지만 대신에 모든 출력을 문자열 (char *)으로 가져 오는 것이 좋습니다. 내가 좋아하는 것 API의 종류는 다음과 같습니다문자열을 생성하는 FILE * 스트림 만들기

/** Create a FILE object that will direct writes into an in-memory buffer. */ 
FILE *open_string_buffer(void); 

/** Get the combined string contents of a FILE created with open_string_buffer 
    (result will be allocated using malloc). */ 
char *get_string_buffer(FILE *buf); 

/* Sample usage. */ 
FILE *buf; 
buf = open_string_buffer(); 
do_some_stuff(buf); /* do_some_stuff will use fprintf to write to buf */ 
char *str = get_string_buffer(buf); 
fclose(buf); 
free(str); 

의 glibc 헤더 파일이 실제 읽기와 쓰기를 수행하기 위해 후크 기능을 설정할 수 있음을 시사한다. 필자는 필자가 쓰기 훅을 사용하여 문자열의 복사본을 링크 된 목록에 추가하고 목록의 전체 길이를 계산하는 get_string_buffer 함수를 사용하여 메모리를 할당 한 다음 각 항목을 복사합니다. 정확한 위치에 넣으십시오.

do_some_stuff과 같은 함수에 전달할 수있는 것을 목표로하고 있습니다.이 함수는 쓸 수있는 것 이외의 다른 것을 알 필요가 없습니다. FILE *.

이와 같은 기존 구현이 있습니까? 유용하고 C 친화적 인 것 같습니다. FILE 확장성에 대한 가정이라고 가정합니다.

답변

5

을 만들지 않습니다. 그것들은 GNU 확장이며 따라서 glibc 시스템에서만 사용 가능합니다. POSIX.1-2008 (fmemopenopen_memstream)의 일부인 것처럼 보입니다.

+0

open_memstream에 대한 필요성은 내가 원하는 것입니다. 연결된 목록 방식을 사용하고 있는지 확실하지 않지만 큰 금액을 쓰지 않아도 상관 없습니다. – Edmund

2

나는 비 이식 FILE 객체를 확장하는 것이 가능하다면 모르겠지만, 당신이 조금 더 POSIX 친화적 인 뭔가를 찾고 있다면, 당신은 pipefdopen를 사용할 수 있습니다.

버퍼에서 바이트를 반환하는 것은 정확히 FILE*과 같지 않지만 프로그래밍 방식으로 결정된 내용이있는 FILE*입니다.

int fd[2]; 
FILE *in_pipe; 

if (pipe(fd)) 
{ 
    /* TODO: handle error */ 
} 

in_pipe = fdopen(fd[0], "r"); 
if (!in_pipe) 
{ 
    /* TODO: handle error */ 
} 

거기에서 write()를 사용 fd[1]로 버퍼를 기록 할 것입니다. 하지만이 단계를 신중하게 사용하면 파이프의 버퍼가 가득 차면 (즉 누군가 다른 쪽을 읽어야 할 필요가있는 경우) write()이 차단 될 수 있고 쓰기 작업 중에 신호가 수신되는 경우 EINTR이 표시 될 수 있습니다. 다른 쪽 끝이 파이프를 닫을 때 발생하는 SIGPIPE에주의하십시오. 어쩌면 블로킹을 피하기 위해 버퍼의 write을 별도의 스레드에서 수행하고 SIGPIPE을 처리해야 할 수도 있습니다.

휴대가 당신을 위해, 당신은 fmemopenopen_memstream에 좀 걸릴 수 있습니다 중요하지 않은 경우 물론, 이것은 시크 FILE* ...

+0

한 좋은 설명에 대해 원하는 별도의 스레드 – Andomar

0

필자가 왜 FILE *로 엉망이되는지 이해가 잘 모르겠습니다. 단순히 파일에 쓰고 문자열로로드 할 수 없습니까? 당신은 단지 문자열로 형식의 텍스트를 "쓰기"하려면

char *get_file_in_buf(char *filename) { 
    char *buffer; 
    ... get file size with fseek or fstat ... 
    ... allocate buffer ... 
    ... read buffer from file ... 
    return buffer; 
} 

, 다른 옵션이 처리하는 방법에 대한 제안이 SO 질문에 대한 답변을 참조 (snprintf()를 사용하여 확장 가능한 버퍼를 처리 할 수 ​​: Resuming [vf]?nprintf after reaching the limit).

경우, 대신에, 당신은 ... 그것은 훨씬 더 복잡한 문제이다, 그 문자열 버퍼에 역할을 확인하기 위해 FILE *을 복용하는 함수에 투명하게 전달 될 수있는 유형을 만들

+0

'FILE *'을 원한다면 좋은 이유가있다 :'FILE * '기반 I/O만을 제공하는 라이브러리가 많이 있으며, 이미 메모리에서 데이터를 이용할 수있을 때 파일을 읽어야한다고 주장한다. 따라서 이러한 라이브러리 용 파일에 쓰지 않고 메모리 버퍼를 전달할 수있는 것이 바람직합니다. 불행하게도,이 라이브러리들은 거의 존재하지 않는다면'FILE * '의존적 인 API의 대안을 제공하는 경우는 거의 없다. – greyfade

관련 문제