std :: ofstream自动在\ n之后添加回车符(CR; \ r) [英] std::ofstream is adding carriage return (CR; \r) after \n automatically

查看:409
本文介绍了std :: ofstream自动在\ n之后添加回车符(CR; \ r)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在磁盘上写入PPM文件. PPM是一种简单的图像格式,由ASCII图像标头和像素字节数组组成:

I am trying to write PPM file on disk. PPM is a simple image format that consists of ASCII image header and byte array of pixels:

P6\n
width height\n
255\n
[width*height*3 bytes total]

这是我的PPM课程(简体):

This is my PPM class (simplified):

class PPMImage
{
protected:
    friend std::istream& operator >>(std::istream &inputStream, PPMImage &other);
    friend std::ostream& operator <<(std::ostream&, const PPMImage&);
    size_t width;
    size_t height;
    // eg. "P6"
    std::string magicNumber;
    // Normally 255
    uint16_t maxBrightness;
    std::vector<std::vector<ImagePixel>> pixels;
};

这就是我将图像写入std::ofstream的方式:

This is how I write the image to std::ofstream:

std::ostream& operator <<(std::ostream &output, const PPMImage &other) {
    // Writing header - THIS IS WHERE THE PROBLEM IS!
    output<<"P6\n"<<other.width<<'\n'<<other.height<<'\n'<<other.maxBrightness<<'\n';
    // The rest is pretty much irrelevant
    size_t position = output.tellp();
    output.seekp(position+other.width*other.height*3);
    // Force the stream to be specific size
    const char zero = 200;
    output.write(&zero, 1);
    // Write the image
    output.seekp(position);
    for(size_t y=0, yl=other.height; y<yl; ++y) {
        for(size_t x=0, xl=other.width; x<xl; ++x) {
            output.write((char*)&(other.pixels[y][x].r), 1);
            output.write((char*)&(other.pixels[y][x].g), 1);
            output.write((char*)&(other.pixels[y][x].b), 1);
        }
    }
    return output;
}

这是我使用此API的方式:

This is how I use this API:

std::ofstream out;
out.open("copy.ppm");
if(!out.is_open()) {
    // error and exit here
}
out<<image;
out.close();

图像看起来还可以,除了ofstream在标头中的每个\n之前添加\r的事实:

The image seems ok, except for the fact that ofstream adds \r before every \n in the header:

P6\r\n
width height\r\n
255\r\n
[width*height*3 bytes total]

这是不可接受的.我试图像这样更改初始化代码:

This is unacceptable. I tried to change the initialization code like this:

std::ofstream out("copy.ppm", std::ios::binary);
// I wonder why I have to mention "copy.ppm" twice...
out.open("copy.ppm");

但这只会创建一个空文件.有人可以解释如何正确写出不带回车的PPM wile吗?

But that just creates empty file. Can someone explain how to correctly write PPM wile without carriage returns?

换句话说:如何正确地 初始化ofstream,使其在没有\r的情况下写入?

In other words: How to correctly initialize the ofstream so that it writes without \r?

推荐答案

通过第二次错误地打开文件,将流置于失败状态.只需调用clear()即可使其正常工作,但这并不理想.

By incorrectly opening the file a second time, you place the stream in a fail state. Just calling clear() makes it work, but this is not ideal.

#include <fstream>
#include <iostream>

class CustomObject{
public:
    std::string message;
    explicit CustomObject(const std::string &text) : message(text) {}
    friend std::ostream& operator <<(std::ostream&, const CustomObject&);
};

std::ostream& operator <<(std::ostream &output, const CustomObject &other) {
    if (output.fail()){
        std::cout << "the stream is in a fail state due to the bad open" << std::endl;
        output.clear();
    }

    output << "P6\n" << other.message.c_str() << '\n';
    return output;
}

int main()
{
    std::string filename("something.ppm");
    std::ofstream out(filename, std::ios::binary);
    out.open(filename);
    out << CustomObject("Hello");
}

打开文件的正确方法是将所有参数(文件名和模式)一起传递,无论您选择将其放在何处.要么在构造函数中,要么与open一起使用,但不能同时使用两者.因此,只需使用原始代码以及适用于Windows的正确模式即可.

The correct way to open your file is to pass all the arguments together, filename and mode, wherever you chose to put it. Either in the constructor, or with open, but not both. So just use your original code plus the correct mode for Windows.

std::ofstream out;
out.open("copy.ppm", std::ios::binary);
if(!out.is_open()) {
    // error and exit here
}
out<<image;
out.close();

这篇关于std :: ofstream自动在\ n之后添加回车符(CR; \ r)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆