std::fstream에서 FILE* 가져오기
C++ std::fstream에서 C FILE* 핸들을 취득하는 (크로스 플랫폼) 방법이 있습니까?
C++ 라이브러리가 fstream을 받아들이기 때문에 FILE*을 받아들이는 C 라이브러리를 사용하고 싶습니다.
간단한 대답은 '아니오'입니다.
그 는...std::fstream
.FILE*
파일 를 에서 .std::fstream
오브젝트 및 수동으로 FILE 오브젝트를 빌드하면 버퍼링된 오브젝트 2개가 같은 파일 기술자에 기록되기 때문에 다른 문제가 발생합니다.
왜 ''을 하는 입니다.std::fstream
를 제기하다FILE*
않지만,.funopen()
.
아쉽게도 이것은 POSIX API(BSD 확장)가 아니기 때문에 휴대성에 문제가 있습니다.그래서 아마 내가 다른 사람을 찾을 수 없는 이유일 거야std::stream
런런물물물물물물
FILE *funopen(
const void *cookie,
int (*readfn )(void *, char *, int),
int (*writefn)(void *, const char *, int),
fpos_t (*seekfn) (void *, fpos_t, int),
int (*closefn)(void *)
);
를 통해 " " " 를 할 수 .FILE
오브젝트를 지정하고 실제 작업에 사용할 기능을 지정합니다. 할 수요.std::fstream
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
업데이트: @Jettatura를 참조하십시오.최적의 답변은 https://stackoverflow.com/a/33612982/225186(Linux만?)입니다.
오리지널:
(아마 크로스 플랫폼이 아닌 심플)
http://www.ginac.de/ ~kreckel/fileno/ (dvorak answer)에서 해킹을 단순화하고 이 gcc 확장자 http://gcc.gnu.org/onlinedocs/gcc-4.6.2/libstdc++/api/a00069.html#a59f78806603c619eafcd4537c920f859,을 보면 다음과 같은 솔루션이 있습니다.GCC
및 (4.8 이상) »clang
3 3.3 이상)
#include<fstream>
#include<ext/stdio_filebuf.h>
typedef std::basic_ofstream<char>::__filebuf_type buffer_t;
typedef __gnu_cxx::stdio_filebuf<char> io_buffer_t;
FILE* cfile_impl(buffer_t* const fb){
return (static_cast<io_buffer_t* const>(fb))->file(); //type std::__c_file
}
FILE* cfile(std::ofstream const& ofs){return cfile_impl(ofs.rdbuf());}
FILE* cfile(std::ifstream const& ifs){return cfile_impl(ifs.rdbuf());}
이것을 사용할 수 있습니다.
int main(){
std::ofstream ofs("file.txt");
fprintf(cfile(ofs), "sample1");
fflush(cfile(ofs)); // ofs << std::flush; doesn't help
ofs << "sample2\n";
}
제한사항: (댓글을 환영합니다)
는 하다는 것을 .
fflush
후에fprintf
★★★★★★★★★★★★★★★★에의 인쇄std::ofstream
sample1은 sample2는 sample2는 sample2는 sample1은 sample2는 sample2는 sample1은 sample2는 sample2는 sample1은 sample1은 sample1 좋은 잘 .fflush
★★★ofs << flush
도움이 안 돼요*에서 파일을(를) 추출할 수 .
std::stringstream
만약이 가능한지도 몰라요그게 가능한지조차 모르겠어요.(아래 업데이트를 보).(업데이트는 아래 참조).나는 아직도 어떻게 C의 아직 C를 추출하는방법을 모르겠어요를 추출할 지 모르겠어요.
stderr
부터에서std::cerr
그랬던 거지, 예를 들어 예를 들어,에 사용하는 경우에 사용할.fprintf(stderr, "sample")
, 이 다음과와 같은 가상적인 코드에서가상 코드로 같은.fprintf(cfile(std::cerr), "sample")
..
마지막 제한에 대해 찾은 유일한 회피책은 다음과 같은 과부하를 추가하는 것입니다.
FILE* cfile(std::ostream const& os){
if(std::ofstream const* ofsP = dynamic_cast<std::ofstream const*>(&os)) return cfile(*ofsP);
if(&os == &std::cerr) return stderr;
if(&os == &std::cout) return stdout;
if(&os == &std::clog) return stderr;
if(dynamic_cast<std::ostringstream const*>(&os) != 0){
throw std::runtime_error("don't know cannot extract FILE pointer from std::ostringstream");
}
return 0; // stream not recognized
}
FILE* cfile(std::istream const& is){
if(std::ifstream const* ifsP = dynamic_cast<std::ifstream const*>(&is)) return cfile(*ifsP);
if(&is == &std::cin) return stdin;
if(dynamic_cast<std::ostringstream const*>(&is) != 0){
throw std::runtime_error("don't know how to extract FILE pointer from std::istringstream");
}
return 0; // stream not recognized
}
처리를 처리하기 위해 시도하다 시도iostringstream
그것은을 사용하여와 읽을수 있습니다를 읽는 것이 가능하다.fscanf
부터에서istream
사용을 사용하여.fmemopen
만약 한 C-reads과 C++-reads.단을 결합하기 위해서 C-reads와 C++-reads를양의 부킹이 필요합니다 많은 조합하려면을 원하지만, 그, 책들과 읽기 후에 스트림의 입력 위치를 업데이트하지 않도록 하는 많이 필요하다.나는이거 못 바꿔서에 이 변환할 수 없었다.cfile
위 같은 역할.위와 같이 기능합니다.(아마도 1(아마도...cfile
각 읽기 후에 계속 갱신되는 클래스가 좋습니다).
// hack to access the protected member of istreambuf that know the current position
char* access_gptr(std::basic_streambuf<char, std::char_traits<char>>& bs){
struct access_class : std::basic_streambuf<char, std::char_traits<char>>{
char* access_gptr() const{return this->gptr();}
};
return ((access_class*)(&bs))->access_gptr();
}
int main(){
std::istringstream iss("11 22 33");
// read the C++ way
int j1; iss >> j1;
std::cout << j1 << std::endl;
// read the C way
float j2;
char* buf = access_gptr(*iss.rdbuf()); // get current position
size_t buf_size = iss.rdbuf()->in_avail(); // get remaining characters
FILE* file = fmemopen(buf, buf_size, "r"); // open buffer memory as FILE*
fscanf(file, "%f", &j2); // finally!
iss.rdbuf()->pubseekoff(ftell(file), iss.cur, iss.in); // update input stream position from current FILE position.
std::cout << "j2 = " << j2 << std::endl;
// read again the C++ way
int j3; iss >> j3;
std::cout << "j3 = " << j3 << std::endl;
}
표준화된 방법은 없습니다.이것은 C++ 표준화 그룹이 파일 핸들을 fd로 나타낼 수 있다고 상정하고 싶지 않았기 때문이라고 생각합니다.
대부분의 플랫폼에서는 이를 위한 비표준적인 방법이 제공되고 있는 것 같습니다.
http://www.ginac.de/~kreckel/fileno/는 상황을 적절하게 기술하고 적어도 GCC의 경우 플랫폼 고유의 전체성을 숨기는 코드를 제공합니다.이게 GCC에 대한 징그러운 점으로 미뤄볼 때, 가능하면 이 모든 것을 함께 하는 것은 피하고 싶습니다.
Linux에서 이를 실현하는 또 다른 방법:
#include <stdio.h>
#include <cassert>
template<class STREAM>
struct STDIOAdapter
{
static FILE* yield(STREAM* stream)
{
assert(stream != NULL);
static cookie_io_functions_t Cookies =
{
.read = NULL,
.write = cookieWrite,
.seek = NULL,
.close = cookieClose
};
return fopencookie(stream, "w", Cookies);
}
ssize_t static cookieWrite(void* cookie,
const char* buf,
size_t size)
{
if(cookie == NULL)
return -1;
STREAM* writer = static_cast <STREAM*>(cookie);
writer->write(buf, size);
return size;
}
int static cookieClose(void* cookie)
{
return EOF;
}
}; // STDIOAdapter
사용 예:
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/bzip2.hpp>
#include <boost/iostreams/device/file.hpp>
using namespace boost::iostreams;
int main()
{
filtering_ostream out;
out.push(boost::iostreams::bzip2_compressor());
out.push(file_sink("my_file.txt"));
FILE* fp = STDIOAdapter<filtering_ostream>::yield(&out);
assert(fp > 0);
fputs("Was up, Man", fp);
fflush (fp);
fclose(fp);
return 1;
}
싱글 스레드 POSIX 애플리케이션에서는, 휴대 가능한 방법으로 fd 번호를 간단하게 취득할 수 있습니다.
int fd = dup(0);
close(fd);
// POSIX requires the next opened file descriptor to be fd.
std::fstream file(...);
// now fd has been opened again and is owned by file
이 메서드는 이 코드가 파일 기술자를 여는 다른 스레드와 경합할 경우 멀티 스레드 응용 프로그램에서 중단됩니다.
파일 기술자를 가져오는 방법이 있습니다.fstream
다음으로 변환합니다.FILE*
)fdopen
FILE*
하면 리다이렉트, 리다이렉트) 등 가지 로운 작업을 할 수 dup2
를 참조해 주세요.
솔루션:
#define private public
#define protected public
#include <fstream>
#undef private
#undef protected
std::ifstream file("some file");
auto fno = file._M_filebuf._M_file.fd();
마지막 문자열은 libstdc++로 동작합니다.다른 라이브러리를 사용하고 있는 경우는, 리버스 엔지니어링을 실시할 필요가 있습니다.
이 속임수는 더럽고 fstream의 모든 개인 및 공공 구성원을 노출시킬 것입니다.는, 별도로 「동작」, 「동작」을 합니다..cpp
★★★★★★★★★★★★★★★★★」.h
'''로int getFdFromFstream(std::basic_ios<char>& fstr);
포함할 수 . 에프스트림
파일 기술자를 얻을 수 있습니다.메서드가 fd()인지 getfd()인지 잊어버렸습니다.지금까지 사용한 실장에서는 이러한 방법이 제공되고 있습니다만, 언어 표준에서는 필수가 아니라고 생각합니다.플랫폼이 파일에 fd를 사용하는지는 상관없습니다.
여기서 fdopen(fd, 모드)을 사용하여 FILE*을 얻을 수 있습니다.
단, STDIN/cin, STDOUT/cout, STDERR/cerr의 동기화에 필요한 메커니즘은 보이지 않아도 된다고 생각합니다.따라서 fstream과 FILE*을 모두 사용하는 경우 버퍼링으로 인해 문제가 발생할 수 있습니다.
또한 fstream OR 또는 the FILE이 닫히면 기본 fd가 닫히기 때문에 둘 다 플러시하고 나서 둘 중 하나를 닫아야 합니다.
언급URL : https://stackoverflow.com/questions/109449/getting-a-file-from-a-stdfstream
'source' 카테고리의 다른 글
vue 구성 요소에서 소품을 업데이트하는 방법 (0) | 2022.07.28 |
---|---|
Vue.js만을 사용하여 배경색 스타일을 변경하는 방법 (0) | 2022.07.28 |
마운트된 함수에 정의되지 않은 VueJS 데이터 속성이 반환됨 (0) | 2022.07.28 |
VueJs의 로컬 스토리지에서 새로 생성된 행을 '관찰'하는 방법은 무엇입니까? (0) | 2022.07.28 |
v-for가 개체의 속성과 함께 사용되는 경우 확인란과 함께 v-model 사용 (0) | 2022.07.27 |