Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ std::ofstream正确地查找文件并向其中添加元素_C++_Json_Windows_Fstream_Ofstream - Fatal编程技术网

C++ std::ofstream正确地查找文件并向其中添加元素

C++ std::ofstream正确地查找文件并向其中添加元素,c++,json,windows,fstream,ofstream,C++,Json,Windows,Fstream,Ofstream,我正在尝试将元素添加到[]之间的.json文件中 如何使用std::ofstream移动光标在[…]之间添加元素 我尝试过几种开放模式,但有一些奇怪的事情。首先,我提出了一个问题:由于覆盖问题,无法使用文件流进行读写 #include <iostream> #include <fstream> int main () { char errmsg[2048]; std::ofstream ostream;

我正在尝试将元素添加到
[]
之间的
.json
文件中

如何使用
std::ofstream
移动光标在
[…]
之间添加元素

我尝试过几种开放模式,但有一些奇怪的事情。首先,我提出了一个问题:由于覆盖问题,无法使用文件流进行读写

    #include <iostream>
    #include <fstream>

    int main ()
    {
        char errmsg[2048];
        std::ofstream ostream;
    
        ostream.exceptions(std::ios_base::badbit);

        try
        {
            ostream.open("LS22731.json", std::fstream::ate | std::fstream::in);
            strerror_s(errmsg, 2048, errno);
            std::cout << "Error (" << errno << "): " << errmsg << std::endl;
            if (ostream && ostream.is_open())
            {
                auto ppos = ostream.tellp();
                std::streampos sub = 1; // 
                std::cout << "Tellp: " << ppos << std::endl; // Always show zero but file has large data
                if (ppos > 1)
                    ostream.seekp(ppos - sub) << "aa";

                ppos = ostream.teelp();
                std::cout << "New tellp: " << ppos << std::endl;
                ostream.close();
            }
        }
        catch (std::ios_base::failure& fb)
        {
            std::cout << "Failure: " << fb.what() << std::endl;
            char errmsg[2048];
            strerror_s(errmsg, 2048, errno);
            std::cout << "Error (" << errno << "): " << errno << std::endl;
        }
    }
#包括
#包括
int main()
{
char errmsg[2048];
std::流奥斯特雷姆;
异常(std::ios_base::badbit);
尝试
{
ostream.open(“LS22731.json”,std::fstream::ate | std::fstream::in);
strerror_s(errmsg,2048,errno);

std::cout如果打开文件进行读取,则无法设置文件的写入头

您正在使用
std::ofstream
ios::in
模式,我不确定该模式是否有效。但是
std::ofstream
必须使用
ios::out
ios::app
打开。当您覆盖默认值时,还应提供默认值

如果需要打开文件进行读写操作,则应使用
std::fstream

另一个问题是,您试图在文本文件中间添加一些字符串,这不是一个好主意,它与在记事本打开时在文本文件中粘贴一些字符串是不一样的。您必须用一个长度相同的另一节替换一个部分,推一些字符串不会将其余的数据向前移动。


我认为最简单的方法是将整个JSON读取到内存中,通过添加或删除一些数据进行处理,最后将整个JSON重写到文件中。

好吧,JSON文件是错误的……顺序文本文件。这意味着文件包含代表JSON内容的字节流。而且,没有文件系统提供在t中插入数据的功能他在一个连续文件的中间。最简单的方法是:

  • 复制到临时文件的插入点
  • 写入新数据
  • 添加原始文件中的剩余数据
  • 将旧文件重命名为备份名称
  • 使用原始名称重命名临时文件
  • (可选)删除备份文件

勇敢的方法是从结尾开始以块的形式移动第二部分,以创建一个EMPLE位置,将数据写入新的数据在该位置,并在整个操作过程中祈求在中间没有问题,因为文件将被不可挽回地损坏。 这两种方法可以处理任意大小的文件。对于小文件,您可以加载内存中的所有内容,在插入点写入新数据,并在新数据之后重写其余数据。您只需使用默认的

fstream
,并且既不使用
ate
也不使用
trunc
out
并不意味着删除所有文件内容。您只需在写入位置替换原始字节

因此,您应该使用:

ostream.open("LS22731.json", std::fstream::out | std::fstream::in);
然后你:

  • 读取到插入点并丢弃数据
  • tellp
  • 读取文件的结尾并保存它
  • 转到插入点
  • 写入新数据
  • 写入保存的数据
  • 关闭小溪

以下是对先前算法的修改。注意事项如下:

  • 您必须在
    std::fstream::out | std::fstream::in
    模式下使用
    fstream
    ,才能读取和写入文件。文件必须存在,并且您将首先定位在文件的开头
  • 为了能够可靠地计算位置,您必须以二进制模式(
    std::fstream::binary
    )打开文件(应该可以在文本模式下打开,但我找不到我的方式…)
下面是代码的一个近似改编:它打开文件,搜索第一个结束括号(
]
),并在前面插入
,“h”
,以模拟向列表中添加值

...
std::fstream ostream;

ostream.exceptions(std::ios_base::badbit);

try
{
    // use binary mode to ba able to relyably seek the file.
    ostream.open("LS22731.json",
                 std::fstream::out | std::fstream::in | std::fstream::binary);
    strerror_s(errmsg, 2048, errno);
    std::cout << "Error (" << errno << "): " << errmsg << std::endl;
    if (ostream && ostream.is_open())
    {
        std::streampos ppos;
        // search the first ]
        ostream.ignore(std::numeric_limits<std::streamsize>::max(), ']');
        // we want to insert just before it
        ppos = ostream.tellg() - std::streampos(1);
        ostream.seekg(ppos);    // prepare to read from the ]
        std::string old = "", tmp;
        // save end of file, starting at the ]
        while (std::getline(ostream, tmp)) {
            old += tmp + "\n";
        }
        ostream.clear();                    // clear eof indicator
        ostream.seekp(ppos, std::ios::beg); // go back to the insertion point
        ostream << ",\"h\"";                // add some data
        ostream << old;                     // add the remaining of the original data
        ostream.close();
    }
...
。。。
std::fstream-ostream;
异常(std::ios_base::badbit);
尝试
{
//使用二进制模式可以可靠地查找文件。
ostream.open(“LS22731.json”,
std::fstream::out | std::fstream::in | std::fstream::binary);
strerror_s(errmsg,2048,errno);

std::我必须说,你可以用一种非常迂回的方式来解决这个问题。使用
JSON
库(比如或举几个例子)若要将文件读入内存,请操作内容,然后将结果转储到文件。从一个文件中读取并输出到另一个文件如何。或者根据文件大小,将文件读入字符串流,并在需要的位置输入内容,然后覆盖原始文件。但如@TEDLYGMO所述。如果问题是如何操作正确地说,您可能应该使用lib:p谢谢您的评论@TEDLYNMO我会试试。谢谢您的评论@Lasersköld这是一个大文件,并且随着时间的推移越来越大。这是一个机器的物联网数据。@OrkunKasapoglu不客气!如果您的文件很大,而物联网机器中的内存有限,您可能不想将整个文档读入内存使用事件驱动的方法,比如使用JSON库的SAX接口。谢谢@SHR。是的,我知道,但这是使用
std::ofstream
移动文件光标/指针的唯一方法。我可以处理删除问题,因为它只是一个
]
。但它是一个用于大数据的JSON,当它长大后,读起来就不好了整个文档的电子书写。感谢您的回答。当我同时使用
std::fstream::out | std::fstream::in
时,它不会覆盖我的文件吗?因为当我使用
std::fstream::out
tellp()
第一次打开时返回0,文件大小在文件资源管理器中直接变为0KB。我刚刚测试过,在一个16字节的文件中只能重写2字节。嘿,Serge,感谢您的测试,但我在尝试使用
s时无法找到最后一个位置