2012-10-29 5 views
3

제가 해결하려고하는 문제는 명령 줄 "program input_file output_file"이있는 일부 타사 코드의 입력을 최적화하는 것입니다. 제 3 자 코드는 표준 fopen, fseek, fread 등으로 input_file을 처리합니다. 여러 입력 파일을 사용할 수 있기를 원합니다. 공급되는 순서대로 연결된 것처럼 단일 파일로 처리합니다. 제 3 자 코드가 있지만 가능한 한 수정하지 않으려합니다. 현재 파일을 연결 한 다음 연결된 파일로 프로그램을 호출하여 파일이 커질 수 있으므로 시간을 들이기 때문에 연결을 제거하려고합니다. stdin을 읽는 것은 내가 원하는 것을하지 않는다. 왜냐하면 프로그램이 seek를 허용하기 위해 파일에 stdin을 쓰고 있기 때문이다.투명하게 여러 스트림을 하나의 것으로 취급합니다 (알려진 스트림 크기)

해결책은 input_file 명령 줄 인수를 여러 파일을 연결 (? 구분)하고, concat_stream.h를 프로그램 소스의 시작 부분 (stdio 포함 후)에 추가하는 것입니다. concat_stream.h는 표준 호출을 인터셉트하고 스트림 및 연결된 데이터의 일부 전역 배열로 연결된 스트림을 구현하여 여러 스트림을 하나의 스트림으로 투명하게 처리합니다. 내가 곧 정상 궤도에 오전

FILE * fopen_concat_streams (char * filename, char * mode) 
    { 
     if(strchr(filename, '?')!=NULL)/*do we want a concat_stream?*/ 
     return concat_streams_init(filename, mode);/*setup concat_stream, return first stream as id*/ 
     else 
     return fopen(filename, mode);/*standard library implementation*/ 
    } 

    long int ftell_concat_streams(FILE * stream) 
    { 
     unsigned int index=is_stream_concat(stream);/*work out if stream refers to a concat_stream or regular stream*/ 
     if(index!=CONCAT_STREAMS_MAX)/*is stream a concat_stream?*/ 
     { 
     ... 
     return answer;/*work out and return location in concat_stream*/ 
     } 
     else 
     return ftell(stream);/*standard library implementation*/ 
    } 

    #define fopen(x, y) fopen_concat_streams(x, y) 
    #define ftell(x) ftell_concat_streams(x) 

내 질문은, 그것을 할 수있는 쉬운 방법이있다 예를 들면 다음과 같습니다로 concat_stream.h의 작은 부분이다? 나에게 이것을 분류 할 라이브러리가 있다면 대신 그 라이브러리를 사용할 것이므로 인기있는 일이 될 것 같지만 지금까지는 찾지 못했습니다. 초기 문제를 해결하는 완전히 다른 방법이 또한 받아 들여질 것입니다. 다중 스트림은 가장 쉬운 솔루션에서의 최선의 추측 일뿐입니다.

답변

2

모든 파일의 경로와 크기를 알고있는 경우이 방법이 유용 할 수 있습니다. 당신이 달성하려고 노력하는 것은 모든 개별 부품으로 구성된 가상 파일을 만드는 것입니다.

각 파일의 파일 핸들과 오프셋 (가상 파일에서)을 포함하는 데이터 구조를 만들어야합니다. 그런 다음이 구조에서 실제 파일 핸들을 검색하고 올바른 오프셋을 계산할 수 있습니다. 당신이 '돈 경우

  • : 단일 fread() 호출

다른 옵션을 파일의 끝을 읽어 경우

  • :

    문제는 알고 있어야합니다 fseek()이 필요하면 stdin의 별칭으로 -을 이해하고 01을 사용하는 코드를 가르쳐 볼 수 있습니다.을 사용하여 파일을 연결하십시오. cat file1 file2 file3 | program - output

  • FUSE API을 사용하여 파일 시스템을 작성하십시오. 그것은 당신의 경우에 들리는만큼 무서운 것이 아닙니다. 그러면 원본 코드를 변경하지 않고 유지할 수 있습니다. 대신 FUSE를 사용하여 파일을 거대한 파일처럼 보이게 만들 수 있습니다. 당신이 bash 4 무엇을 달성하고자하는 같은

  • FUSE Python Tutorial
  • FUSE - Filesystem in Userspace part 1 (part 2)
+0

예, '가상 파일'을 설명하는 좋은 방법입니다. 나는 구현의 중간에 있지만 상당히 오래갑니다. 나는 중요한 기능을 위해 많은 맞춤 코드를 작성하는데 조심 스럽다. 특히 가로 채기로 투명하다. 전용 라이브러리가 더 강력 할 것입니다. 불행하게도 고양이와 배관 할 수는 없지만 질문에서 설명했지만 분명하지 않을 수 있습니다. 답장을 보내 주셔서 감사 드리며 퓨즈 API를 제안 해 주시면 다음 내용을 읽으 실 수 있습니다 :) –

+0

FUSE를 사용하여 구현하십시오. Python으로 간단한 파일 시스템을 작성할 수 있습니다. 그런 식으로 새로운 (위대한) 프로그래밍 언어를 배우고, 파일 시스템에 대해 배우고, 노력을 덜하면서 문제를 해결할 수 있습니다. 두 개의 자습서에 대한 링크를 추가했습니다. –

1

소리가 난다.당신이 cat 하나 개라는 이름의 스트림으로 입력 파일을 보내입니다

the_program <(cat file1 file2 file3) output 

프로그램을 열고에서 읽을 수있는 (아마, 이름과 같은 /dev/fd/64 수 있습니다) : X '는 프로세스 대체'을 통해 달성 . 이렇게하면 프로그램을 수정하지 않아도됩니다.

이것은 효과를 얻기 위해 C 코드가 필요한 것 이외의 요구 사항을 충족합니까? 프로그램에 탐색 가능한 파일이 필요한 경우 가능한 한 가지 문제점이 있습니다. 열리는 파일 스트림을 탐색 할 수 있는지 여부는 확실하지 않습니다.

+0

탐색이 필요합니다. 두려운 것이지만, +1은 프로세스 교체를 내 관심으로 가져옵니다. :) –

0

다음은 기본을 구현하는 컷 다운 차단 솔루션입니다. 제한된 테스트, 제한된 오류 확인, 페더만큼 강력합니다. 모든 기능이 완벽하지는 않으며 많은 기능이 빠져 있습니다 (코드에서 fseeki64를 사용하고 여기에서 구현하는 경우). 그것은 내가 제안한 것처럼 퓨즈를 시도 할 것입니다. 그러나 다른 누군가가이 방법으로 이것을 원한다면 이것은 출발점 일 수 있습니다.

주요

#include <stdio> 
#include "concat_streams.h" 
int main(int argc, char*argv[]) 
{ 
    char buf[16]; 
    concat_streams_global_init('?'); 
    FILE* file = fopen("file1?file2?file3?file4", "rb"); 
    ... 
    fseek(file, 12, SEEK_SET); 
    ... 
    fread(buf, 1, 16, file); 
    ... 
    fclose(file); 
} 

concat_streams.h

#define CONCAT_STREAMS_MAX 10 /*max number of concat streams*/ 
FILE*** concat_streams=NULL; 
size_t** concat_streams_boundaries=NULL; 
size_t* concat_streams_count=NULL; 
size_t* concat_streams_selector=NULL; 
size_t* concat_streams_tot_size=NULL; 
char concat_streams_delim='?'; 

/*return index of stream if it is concat, CONCAT_STREAMS_MAX otherwise*/ 
int is_stream_concat(FILE* stream) 
{ 
    unsigned int index=0; 
    while(index<CONCAT_STREAMS_MAX) 
    { 
    if(concat_streams[index]!=NULL) 
    { 
     if(concat_streams[index][0]==stream) 
     break; 
    } 
    ++index; 
    } 
    return index; 
} 

/*Initialise concat_stream store*/ 
void concat_streams_global_init(char delim_use) 
{ 
    concat_streams_delim=delim_use; 

    concat_streams=(FILE***) malloc(sizeof(FILE**)*CONCAT_STREAMS_MAX); 
    concat_streams_boundaries=(size_t**) malloc(sizeof(size_t*)*CONCAT_STREAMS_MAX); 
    concat_streams_count=(size_t*) malloc(sizeof(size_t)*CONCAT_STREAMS_MAX); 
    concat_streams_selector=(size_t*) malloc(sizeof(size_t)*CONCAT_STREAMS_MAX); 
    concat_streams_tot_size=(size_t*) malloc(sizeof(size_t)*CONCAT_STREAMS_MAX); 

    memset(concat_streams, 0, sizeof(FILE**)*CONCAT_STREAMS_MAX); 
    memset(concat_streams_boundaries, 0, sizeof(size_t*)*CONCAT_STREAMS_MAX); 
    memset(concat_streams_count, 0, sizeof(size_t)*CONCAT_STREAMS_MAX); 
    memset(concat_streams_selector, 0, sizeof(size_t)*CONCAT_STREAMS_MAX); 
    memset(concat_streams_tot_size, 0, sizeof(size_t)*CONCAT_STREAMS_MAX); 
} 

/*The meat of fopen*/ 
FILE* concat_streams_init(char* files_question_delim, char * mode) 
{ 
    unsigned int concat_streams_next_set=0; 
    while(concat_streams_next_set<CONCAT_STREAMS_MAX) 
    { 
    if(concat_streams[concat_streams_next_set]==NULL) 
     break; 
    ++concat_streams_next_set; 
    } 
    if(concat_streams_next_set==CONCAT_STREAMS_MAX) 
    return NULL; 
    char*files_question_delim_cpy=NULL; 
    unsigned int i=0; 
    while(files_question_delim[i]!=0) 
    { 
    if(files_question_delim[i]=='?') 
     ++concat_streams_count[concat_streams_next_set]; 
    ++i; 
    } 
    ++concat_streams_count[concat_streams_next_set]; 

    files_question_delim_cpy=(char*)malloc(i); 
    memcpy(files_question_delim_cpy, files_question_delim, i); 

    concat_streams[concat_streams_next_set]=(FILE**)malloc(sizeof(FILE*)*concat_streams_count[concat_streams_next_set]); 
    concat_streams_boundaries[concat_streams_next_set]=(size_t*)malloc(sizeof(size_t)*(concat_streams_count[concat_streams_next_set]+1)); 
    concat_streams_boundaries[concat_streams_next_set][0]=0; 


    char* next_file; 
    next_file=strtok(files_question_delim_cpy, "?"); 
    while(next_file!=NULL) 
    { 
    concat_streams[concat_streams_next_set][concat_streams_selector[concat_streams_next_set]]=fopen(next_file, "rb"); 
    if(concat_streams[concat_streams_next_set][concat_streams_selector[concat_streams_next_set]]==NULL) 
    { 
     fclose_concat_streams(concat_streams[concat_streams_next_set][0]); 
     return NULL;/*fopen failed*/ 
    } 
    fseek(concat_streams[concat_streams_next_set][concat_streams_selector[concat_streams_next_set]], 0, SEEK_END); 
    concat_streams_boundaries[concat_streams_next_set][1+concat_streams_selector[concat_streams_next_set]] = concat_streams_boundaries[concat_streams_next_set][concat_streams_selector[concat_streams_next_set]] + ftell(concat_streams[concat_streams_next_set][concat_streams_selector[concat_streams_next_set]]); 
    concat_streams_tot_size[concat_streams_next_set]+=ftell(concat_streams[concat_streams_next_set][concat_streams_selector[concat_streams_next_set]]); 
    rewind(concat_streams[concat_streams_next_set][concat_streams_selector[concat_streams_next_set]]); 
    ++concat_streams_selector[concat_streams_next_set]; 
    next_file=strtok(NULL, "?"); 
    } 
    concat_streams_selector[concat_streams_next_set]=0; 

    free(files_question_delim_cpy); 
    return concat_streams[concat_streams_next_set][0]; 
} 

FILE * fopen_concat_streams (char * filename, char * mode) 
{ 
    if(strchr(filename, '?')!=NULL) 
    return concat_streams_init(filename, mode); 
    else 
    return fopen(filename, mode); 
} 

/*only implemented origin==SEEK_SET*/ 
int fseek_concat_streams(FILE * stream, long int offset, int origin) 
{ 
    unsigned int i=0; 
    unsigned int index=is_stream_concat(stream); 
    if(index!=CONCAT_STREAMS_MAX) 
    { 
    switch(origin) 
    { 
     case SEEK_SET: 
     while(i<concat_streams_count[index]) 
     { 
      if(offset>=concat_streams_boundaries[index][i] && offset<concat_streams_boundaries[index][i+1]) 
      break; 
      ++i; 
     } 
     if(i==concat_streams_count[index]) 
      return 1;/*out of range*/ 
     concat_streams_selector[index]=i; 
     return fseek(concat_streams[index][concat_streams_selector[index]], offset-concat_streams_boundaries[index][concat_streams_selector[index]], SEEK_SET); 
     default: 
      puts("error, Only SEEK_SET supported when using cat streams"); 
     return 1;/*not implemented*/ 
    } 
    } 
    else 
    return fseek(stream, offset, origin);/*just a normal file*/ 
} 

long int ftell_concat_streams(FILE * stream) 
{ 
    unsigned int index=is_stream_concat(stream); 
    if(index!=CONCAT_STREAMS_MAX) 
    { 
    /*Found*/ 
    return concat_streams_boundaries[index][concat_streams_selector[index]] + ftell(concat_streams[index][concat_streams_selector[index]]); 
    } 
    else 
    return ftell(stream); 
} 

int feof_concat_streams(FILE * stream) 
{ 
    unsigned int index=is_stream_concat(stream); 
    if(index!=CONCAT_STREAMS_MAX) 
    { 
    if(concat_streams_selector[index]==concat_streams_count[index]) 
     return 1;/*EOF*/ 
    else 
     return 0; 
    } 
    else 
    return feof(stream); 
} 

size_t fread_concat_streams (void * ptr, size_t size, size_t count, FILE * stream) 
{ 
    size_t mult=size*count; 
    size_t num_to_go=mult; 
    char* buffer=NULL; 
    unsigned int index=is_stream_concat(stream); 
    unsigned int num_read; 
    char* out_ptr=(char*)ptr; 

    if(index!=CONCAT_STREAMS_MAX) 
    { 
    if(concat_streams_selector[index]==concat_streams_count[index]) 
     return 0;/*at eof*/ 

    buffer=(char*)malloc(2048*4096); 
    while(num_to_go!=0) 
    { 
     num_read=fread(buffer, 1, num_to_go>=2048*4096?2048*4096:num_to_go, concat_streams[index][concat_streams_selector[index]]); 
     if(num_read != (num_to_go>=2048*4096?2048*4096:num_to_go)) 
     { 
     if(feof(concat_streams[index][concat_streams_selector[index]])==0) 
     { 
      puts("EOF not set, read error"); 
      memcpy(out_ptr, buffer, num_read); 
      out_ptr+=num_read; 
      num_to_go-=num_read; 
      free(buffer); 
      return mult-num_to_go; 
     } 
     else 
     { 
      rewind(concat_streams[index][concat_streams_selector[index]]); 
      ++concat_streams_selector[index]; 
      if(concat_streams_selector[index]==concat_streams_count[index]) 
      { 
      memcpy(out_ptr, buffer, num_read); 
      out_ptr+=num_read; 
      num_to_go-=num_read; 
      free(buffer); 
      return mult-num_to_go; 
      } 
      else 
      rewind(concat_streams[index][concat_streams_selector[index]]); 
     } 
     } 
     memcpy(out_ptr, buffer, num_read); 
     out_ptr+=num_read; 
     num_to_go-=num_read; 
    } 
    free(buffer); 
    return mult; 
    } 
    else 
    return fread(ptr, size, count, stream); 
} 

size_t fwrite_concat_streams (const void * ptr, size_t size, size_t count, FILE * stream) 
{ 
    unsigned int index=is_stream_concat(stream); 
    if(index!=CONCAT_STREAMS_MAX) 
    { 
    puts("error, writing to cat_streams not supported"); 
    return 0; 
    } 
    else 
    return fwrite(ptr, size, count, stream); 
} 

int fclose_concat_streams (FILE * stream) 
{ 
    unsigned int i=0; 
    unsigned int index=is_stream_concat(stream); 
    if(index!=CONCAT_STREAMS_MAX) 
    { 
    while(i<concat_streams_count[index]) 
    { 
     fclose(concat_streams[index][i]); 
     ++i; 
    } 
    free(concat_streams[index]); 
    concat_streams[index]=NULL; 
    free(concat_streams_boundaries[index]); 
    concat_streams_boundaries[index]=NULL; 
    concat_streams_count[index]=0; 
    concat_streams_selector[index]=0; 
    concat_streams_tot_size[index]=0; 
    } 
    else 
    return fclose(stream); 
} 

#define fseek(x, y, z) fseek_concat_streams(x, y, z) 
#define fread(w, x, y, z) fread_concat_streams(w, x, y, z) 
#define fwrite(w, x, y, z) fwrite_concat_streams(w, x, y, z) 
#define fopen(x, y) fopen_concat_streams(x, y) 
#define ftell(x) ftell_concat_streams(x) 
#define feof(x) feof_concat_streams(x) 
#define fclose(x) fclose_concat_streams(x)