【问题标题】:How to convert a std::istream to std::wistream如何将 std::istream 转换为 std::wistream
【发布时间】:2011-10-01 22:35:37
【问题描述】:

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

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

【问题讨论】:

    标签: c++ unicode stream ascii


    【解决方案1】:

    您可以编写一个读取缓冲区以使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 接口的最低限度。如果需要,您可以添加缓冲区管理代码以提高性能。

    【讨论】:

      【解决方案2】:

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

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

      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 有合理的知识。我承认我对流不满意。

      【讨论】:

      • 我从来没有说过这是不可能的,但我讨厌挖掘 std::streambuf 的深层细节......(为了清楚起见,我编辑了我的帖子)
      • 我认为你们两个是正确的,这似乎是可能的,但深入研究 STL 流类的内部本身就是一场噩梦。最后,我更改了代码以使用带有仿函数的 boost 函数来进行所需的转换。
      猜你喜欢
      • 2019-02-28
      • 2021-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-31
      • 1970-01-01
      • 2017-07-02
      • 2016-12-06
      相关资源
      最近更新 更多