如何将 std::istream 转换为 std::wistream

发布于 2024-12-07 17:52:11 字数 112 浏览 0 评论 0原文

我有一个 istream,有些代码需要一个 wistream。

我确实希望源流的每个字符都从零扩展为 wchar_t。我不关心代码页,也不关心本地化,我只是想无缝地传输此输入,最快的方法是什么?

I have an istream and some code expects a wistream.

I literally want every char of a source stream zero extended to a wchar_t. I don't care about code pages, I don't care about localization, I simply want to seamlessly pipe this input, what's the fastest way to do it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

鲜肉鲜肉永远不皱 2024-12-14 17:52:11

您可以编写一个读取缓冲区,使 istream 中的底层流缓冲区适应您的 wistream

class adapting_wistreambuf : public wstreambuf {
  streambuf *parent;
public:
  adapting_istreambuf(streambuf *parent_) : parent(parent_) { }
  int_type underflow() {
    return (int_type)parent->snextc();
  }
};

稍后:

istream &somestream = ...;
adapting_wistreambuf sb(somestream.rdbuf());
wistream wistream(&sb);

// now work with wistream

这仅实现了 Streambuf 接口的最低限度。如果需要,您可以添加缓冲区管理代码来提高性能。

You can write a read buffer to adapt the underlying stream buffer in the istream to your wistream:

class adapting_wistreambuf : public wstreambuf {
  streambuf *parent;
public:
  adapting_istreambuf(streambuf *parent_) : parent(parent_) { }
  int_type underflow() {
    return (int_type)parent->snextc();
  }
};

Later:

istream &somestream = ...;
adapting_wistreambuf sb(somestream.rdbuf());
wistream wistream(&sb);

// now work with wistream

This implements only the bare minimum of streambuf's interface. You could add buffer management code to improve performance if you need to.

一抹微笑 2024-12-14 17:52:11

我认为如果不围绕 std::wistream 编写一个复杂的*包装器来提供 std::istream 接口是不可能的。两者之间的区别在于从模板实例化这些类时使用的 char 类型,从而使 std::istream (char_type = char) 和 std::wistream (char_type = wchar_t) 位于两个不同的类层次结构中。他们只共享 std::ios_base 作为公共基类,它不提供任何东西对您当前的问题有用。

因此,下面的代码将无法编译(它尝试将 s2 的内部 std::streambuf 替换为 s1 的内部 std::streambuf,从而使 s2 上的 I/O 操作对来自 s2 的数据执行file) :

std::wifstream     s1 ;
std::istringstream s2 ;

// assuming s1 and s2 are correctly initialized ...

s2.ios::rdbuf(s1.rdbuf()) ;  // will not compile, unfortunately, unless the char type
                             // is the same for the two streams :(

我不知道一个简单的解决方案,也许是 Boost IOStreams Filter 可以使用(我从未尝试过:()。

如果您不处理二进制数据,并且流长度不太大,请尝试将所有数据读取为字符串,然后转换(零扩展作为你说)到 std::wistringstream

* :复杂意味着您对 std::streams 有合理了解。对溪流不适应。

I think it is not possible without writing a complicated* wrapper around an std::wistream to provide an std::istream interface. The difference between the two is the char type used when instantiating these classes from templates, thus making std::istream (char_type = char) and std::wistream (char_type = wchar_t) in two different class hierarchies. They only share std::ios_base as a common base class, which does not provide something useful for your current problem.

Because of that, the following piece of code will not compile (it tries to replace the internal std::streambuf of s2 with s1's one, thus making I/O operations on s2 performing on the data from the file) :

std::wifstream     s1 ;
std::istringstream s2 ;

// assuming s1 and s2 are correctly initialized ...

s2.ios::rdbuf(s1.rdbuf()) ;  // will not compile, unfortunately, unless the char type
                             // is the same for the two streams :(

I'm not aware of a simple solution, perhaps a Boost IOStreams Filter can be used (I never tried :( ).

If you're not dealing with binary data, and your stream length isn't too big, try reading all the data to a string and then convert (zero extend as you say) into an std::wistringstream.

* : complicated means that you have reasonable knowledge about std::streams. I confess I'm not comfortable with streams.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文