0

そこで、簡単なテストアプリケーションを作成しました。目的は、テキストファイルの読み取りまたは書き込みのいずれかです。文字列「Firmware:」を探しています。アイデアは、デバイスにパッケージが転送されて保存され、アクティブ化されるというものです。そのパッケージの名前(例:Update1)を保存したいのですが、必要に応じてクエリを実行し、パッケージ名を取得します(ファイルから読み取ります)。

問題1:ファイルに書き込んでいないようです。 問題2:ファイルに書き込むときに、「ファームウェア:pkgName」という行が存在する場合、pkgNameを新しいパッケージ名に置き換えるにはどうすればよいですか?

このプログラムは実行およびコンパイルされるので、IDEまたはテキストエディタに自由に入れてください。私が望むことを完全には実行できません。読み取るサンプルファイルとしてlog.txtを使用しています。これを行うにはもっと簡単な方法があると確信しています。私はしばらくこれにいて、困惑しました。

助けてくれてありがとう!

#include <cstdlib>
#include <iostream>
#include <string>
#include <fstream>

using namespace std;

int writeFile(string filename, string pkgName);
int readFile(string filename);

int main(void) {
    string filename = "log.txt", userInput, pkgName;
    system("touch log.txt");

    while (true) {
        cout << "Write or Read?\n>>>";
        cin >> userInput;

        if (userInput == "Write") {
            cout << "What's your package name?\n>>>";
            cin >> pkgName;
            writeFile(filename, pkgName);
        } else if (userInput == "Read") {
            readFile(filename);
        } else {
            cout << "Invalid Input";
        }
    }
}

int writeFile(string filename, string pkgName) {
    bool found, exists = true;
    string line, word;
    fstream firmwareFile;
    int pos, size, num = 1;
    firmwareFile.open(filename.c_str(), ios::in | ios::out | ios::app);
    //firmwareFile << "This is a test.";
    if (firmwareFile.is_open()) {
        while (!found) {
            getline(firmwareFile, line);
            pos = line.find("Firmware: ");
            if (pos != string::npos) {
                //Found It
                found = true;
                exists = true;
                size = line.size();
                word = line.substr(10, ((size - pos) + 10));
                cout << word << " is the old package name" << endl;
                //TODO - Replace that with the new package name
                firmwareFile.close();
            } else if (firmwareFile.eof()) {
                //Doesn't Exist
                found = true;
                exists = false;
                cout << "No last firmware package available.\n";
            } else {
                //Still Looking
                found = false;
                cout << "Searching line #" << num <<  endl;
            }
            num++;
            if (!exists) {
                firmwareFile << endl << "Firmware: " << pkgName << endl;
                cout << "Wrote package name to file\n" << endl;
            }
            firmwareFile.close();
        }   
    } else {
        cout << "Unable to open file";
    }
}

int readFile(string filename) {
    bool found;
    string line, word;
    fstream firmwareFile;
    int pos, size, num = 1;
    firmwareFile.open(filename.c_str(), ios::in | ios::out | ios::app);
    if (firmwareFile.is_open()) {
        while (!found) {
            getline(firmwareFile, line);
            pos = line.find("Firmware: ");
            if (pos != string::npos) {
                found = true;
                size = line.size();
                word = line.substr(10, ((size - pos) + 10));
                cout << word << endl;
            } else if (firmwareFile.eof()) {
                found = true;
                cout << "No last firmware package available.\n";
                firmwareFile << endl << "Firmware: ";
            } else {
                cout << "Searching line #" << num << endl;
            }
            num++;
        }
        firmwareFile.close();
    } else {
        cout << "Unable to open file";
        firmwareFile.close();
    }
    firmwareFile.close();
}

これが私のlog.txtファイルの内容です(「ファームウェア:」を含む行以外はすべて些細なことです)

You
Think
It's
Here
But
It's
Not
So
That
Sucks
Doesn't
It
?
Firmware: Update1
I
Hope
You
Caught
It
!
4

4 に答える 4

2

@jrokはあなたの問題2に答えましたが、foundが初期化されておらず、したがって未定義であるため、コードが毎回書き込まれないと思われます。そのため、whileループの半分の時間(約)はまったく実行されません。次のように、見つかったものと存在するものの両方を初期化する必要があります。bool found = false, exists = true;

于 2012-08-02T19:58:10.483 に答える
2

上手。最初の質問ですが、関数書き込みファイルにはfound、while条件でテストする変数がありますwhile (!found) { ... }。問題は、この変数を最初にテストするときに、値を設定していないことです。したがって、そこには未定義の動作があります。残りのコードを見ると、whileループではなくdowhileループを使用する必要があると思いますdo { ... } while (!found);。readFileでも同じ問題があるようです。

2番目の質問は私が恐れている悪いニュースです。まったく同じ長さの文字列に置き換える場合を除いて、ファイル内の文字列を置き換えることはできません。これは、ファイルがディスク上で編成される方法の単なる制限です。置換を実行できる唯一の方法は、ファイル全体をメモリに読み込み、メモリ内で置換を行ってから、ファイル全体をディスクに書き戻すことです。

于 2012-08-02T19:57:03.997 に答える
0

関連する行だけを変更して別のファイルを作成すると、作業を簡略化できます。

std::ifstream cfg("log.txt");
std::ofstream tmp("log.tmp");
std::string line;
std::string pkgName;

while(std::getline(cfg, line)) {
    if (line.find("Firmware:") != std::string::npos) {
        line = "Firmware: " + pkgName; 
    }
    tmp << line << '\n';
}

現在、ファイルの名前変更と削除はプラットフォーム固有です。ポータブルなソリューションが必要な場合は、Boostファイルシステムライブラリを調べることをお勧めします。

于 2012-08-02T20:12:12.310 に答える
0

ファイルの内容を元の場所に置き換える必要がある場合(別のファイルを削除したり名前を変更したりする必要はありません)、ファイル全体を読み込み、メモリ内のファイルに必要な変更を加えてから、を書き出す必要があります。インメモリファイルの内容全体をオンディスクファイルに上書きします。

ソースファイルの削除が許可されている場合は、これらの変換を行う方がはるかに簡単です。ソースファイルを読み込み、一時ファイルを開いて書き出すだけで、必要な変更をその場で行うことができます。ソースファイルの処理が完了したら、それを削除し、新しいファイルの名前を元のソースファイルと同じ名前に変更します。

于 2012-08-02T20:05:44.253 に答える