我的问题很简单,但我很难在网上找到有关此问题的任何信息。
是否可以使用 ifstream 从使用 Android NDK 的 Assets 和/或资源中打开文件?
例如,将 test.txt 文件放在/assets 中并尝试以下操作不起作用:
char pLine[256];
std::ifstream fin("/assets/test.txt");
if(!fin.fail())
{
LOGD( "test.txt opened" );
while( !fin.eof() )
{
fin.getline( pLine, 256 );
LOGD(pLine);
}
}
else
{
LOGD( "test.txt FAILED TO OPEN!" );
}
fin.close();
也没有任何变量:
std::ifstream fin("assets/test.txt");
std::ifstream fin("test.txt");
等等...,也不是将其放在/res 中。
那么,是否可以使用普通的 ifstream 运算符来访问 Assets 和/或资源文件?
最佳答案
不能使用 std::ifstream 是正确的,但可以创建一个可以以类似方式使用的 Assets 流。例如:
class asset_streambuf: public std::streambuf
{
public:
asset_streambuf(AAssetManager* manager, const std::string& filename)
: manager(manager)
{
asset = AAssetManager_open(manager, filename.c_str(), AASSET_MODE_STREAMING);
buffer.resize(1024);
setg(0, 0, 0);
setp(&buffer.front(), &buffer.front() + buffer.size());
}
virtual ~asset_streambuf()
{
sync();
AAsset_close(asset);
}
std::streambuf::int_type underflow() override
{
auto bufferPtr = &buffer.front();
auto counter = AAsset_read(asset, bufferPtr, buffer.size());
if(counter == 0)
return traits_type::eof();
if(counter < 0) //error, what to do now?
return traits_type::eof();
setg(bufferPtr, bufferPtr, bufferPtr + counter);
return traits_type::to_int_type(*gptr());
}
std::streambuf::int_type overflow(std::streambuf::int_type value) override
{
return traits_type::eof();
};
int sync() override
{
std::streambuf::int_type result = overflow(traits_type::eof());
return traits_type::eq_int_type(result, traits_type::eof()) ? -1 : 0;
}
private:
AAssetManager* manager;
AAsset* asset;
std::vector<char> buffer;
};
class assetistream: public std::istream
{
public:
assetistream(AAssetManager* manager, const std::string& file)
: std::istream(new asset_streambuf(manager, file))
{
}
assetistream(const std::string& file)
: std::istream(new asset_streambuf(manager, file))
{
}
virtual ~assetistream()
{
delete rdbuf();
}
static void setAssetManager(AAssetManager* m)
{
manager = m;
}
private:
static AAssetManager* manager;
};
void foo(AAssetManager* manager)
{
assetistream::setAssetManager(manager);
assetistream as("text/tmp.txt");
std::string s;
std::getline(as, s);
}
非常欢迎改进。
关于android - 我可以在 Android NDK 中使用 ifstream 来访问资源吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11063786/