首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在cppwinrt中读取StorageFile中的字节数据?

如何在cppwinrt中读取StorageFile中的字节数据?
EN

Stack Overflow用户
提问于 2018-02-15 03:48:17
回答 2查看 1.4K关注 0票数 1

2012年,StackOverflow的一个答案(“如何在Windows Store应用中读取二进制文件”)提出了从Windows Store应用中的StorageFile读取字节数据的方法:

代码语言:javascript
复制
IBuffer buffer = await FileIO.ReadBufferAsync(theStorageFile);
byte[] bytes = buffer.ToArray();

这看起来很简单。当我在cppwinrt中工作时,我已经在生成StorageFiles向量的同一个IAsyncAction中将其翻译为以下代码。首先,我使用theFilesVector.GetAt( StorageFile )从VectorView获取索引;

//然后此行编译时不会出现错误:

代码语言:javascript
复制
IBuffer buffer = co_await FileIO::ReadBufferAsync(theStorageFile);

//但是我找不到一种方法来使buffer调用工作。

代码语言:javascript
复制
byte[] bytes = buffer.ToArray();

“byte[]”一开始不能工作,所以我把它改成了byte*,但是错误是“class‘winrt::Windows::Storage::Streams::IBuffer’没有成员‘ToArray’”

事实上,Intellisense没有列出IBuffer的这样的成员。然而,ReadBufferAsync的返回类型被指定为IBuffer。上面的示例代码看起来不能正常工作。

在FileIO的文档中,我发现建议使用DataReader来读取缓冲区,在cppwinrt中应该是这样的

代码语言:javascript
复制
DataReader dataReader = DataReader::FromBuffer(buffer);

这就编译了。然后,应该可以使用以下DataReader方法读取字节,幸运的是,该方法在UWP文档中以cppwinrt的形式提供:

代码语言:javascript
复制
void ReadBytes(Byte[] value) const;

但是,这不能编译,因为在cppwinrt中不能识别类型Byte。如果我创建一个字节数组:

代码语言:javascript
复制
byte* fileBytes = new byte(buffer.Length());

这是不被接受的。错误是

代码语言:javascript
复制
‘No suitable constructor exists to convert from “byte*” to “winrt::arrayView::<uint8_t>”’ 

uint8_t当然是一个字节,所以让我们试一试

代码语言:javascript
复制
uint8_t fileBytes = new uint8_t(buffer.Length());

这是错误的--显然我们真的需要创建一个winrt::array_view。然而,2015年红迪网上的一篇帖子说,array_view“死了”,我不确定如何宣布这一消息,或者它是否会有所帮助。回想起来,最初的从缓冲区读取字节的单行方法看起来非常漂亮。这是一篇很长的文章,但是有没有人能推荐当前最好的方法来简单地从cppwinrt中的StorageFile引用中读取原始字节?如果StorageFile上只有GetFileBytes()和GetFileBytesAsync()方法,那就太好了。

-更新:这是前进的一步。我发现Kenny Kerr去年发表了一篇评论,解释说array_view不应该直接声明,但可以使用std::vector或std::array来代替。这被接受为DataReader的ReadBytes方法的参数:

代码语言:javascript
复制
std::vector<unsigned char>fileBytes;
dataReader.ReadBytes(fileBytes);

现在唯一的问题是std::vector没有接收字节,即使被引用文件的大小在buffer.Length()中被正确返回为167,513字节。这似乎表明缓冲区很好,所以我不确定为什么应用于该缓冲区的ReadBytes方法不会产生任何数据。

更新#2: Kenny建议在向量中保留空间,这是我尝试过的方法,如下所示:

代码语言:javascript
复制
m_file_bytes.reserve(buffer.Length());

但这并没有起到什么作用。下面是使用DataReader的代码示例。

代码语言:javascript
复制
buffer = co_await FileIO::ReadBufferAsync(nextFile);
dataReader = DataReader::FromBuffer(buffer);
//The following line may be needed, but crashes
//co_await dataReader.LoadAsync(buffer.Length());
if (buffer.Length())
{
m_file_bytes.reserve(buffer.Length());
dataReader.ReadBytes(m_file_bytes);
}
The crash, btw, is 

throw hresult_error(result, hresult_error::from_abi);

那么,上面引用的2012年的原始解决方案在当今世界是不能工作的吗?但当然,一定有某种方法可以从文件中读取字节,所以我只是遗漏了一些对另一个人来说可能很明显的东西。

最后(我认为)更新:Kenny关于向量需要一个大小的建议一针见血。如果向量首先用m_file_bytes.assign(buffer.Length(),0)准备好,那么它就会被文件数据填充。现在我唯一担心的是,我并不真正理解IAsyncAction的工作方式,可能会遇到异步循环的问题,但我们将拭目以待。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-02-15 13:21:59

array_view弥补了Windows和C++数组类型之间的差距。在此示例中,ReadBytes方法要求调用方提供一些可将字节复制到其中的数组。array_view将一个指针转发给调用者的数组及其大小。在本例中,您传递的是一个空向量。尝试在调用ReadBytes之前调整向量的大小。

票数 3
EN

Stack Overflow用户

发布于 2021-04-15 19:17:51

当您知道预期的字节数(在本例中为2字节)时,这对我是有效的:

代码语言:javascript
复制
    std::vector<unsigned char>fileBytes;
    fileBytes.resize(2);        
    DataReader reader = DataReader::FromBuffer(buffer);
    reader.ReadBytes(fileBytes);
    cout<< fileBytes[0] << endl;
    cout<< fileBytes[1] << endl;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48795084

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档