1
void maintainFileName ()
{
    std :: ifstream myfile;
    myfile.open ("zoomLevels.txt");

    if (myfile.is_open ())
    {
        // Move to end of the file, 
        myfile.seekg (0, std::ios::end);

        // and then six characters back to pick up the last file number.
        myfile.seekg (6, std::ios::beg);

        int len = 1;
        char *t = new char[len];

        myfile.read(t, len);
        qDebug () << "\nt: " << *t << "\n";
    }
    else
    {
        qDebug () << "\nsorry";
    }
}

ファイルにはこれが含まれています:

78.8115,29.582,1,01.rda
78.8115,29.582,2,02.rda
76.3671,30.2201,1,11.rda
76.3671,30.2201,2,12.rda
78.1908,30.3007,1,01.rda
78.1908,30.3007,2,02.rda
77.3284,29.1415,1,01.rda
77.3284,29.1415,2,02.rda
77.3064,29.1655,1,01.rda
77.3064,29.1655,2,02.rda

その関数によって返される値は ですが5、最後から 6 番目の文字は0!
どこが間違っていますか?

4

5 に答える 5

7

テキスト ファイル内の任意の位置へのシークは未定義の動作です。実際には、さまざまな Unice で動作する可能性がありますが、それ以外では動作しません。ファイルをバイナリ モードで開いた場合、シークは有効です。正式には、バイナリ モードでファイルを開くと、最後に余分な nul バイトが表示される場合がありますが、実際には、これは現在問題ではありません。ただし、バイナリ モードで開くと '\n'、データではなく別のものが表示される場合があります。たとえば、Windows では、2 つの文字シーケンスが表示されます0x0D, 0x0A

もちろん、あなたのコードでは、最後からではなく、最初からシークしています。これも未定義の動作ですが、ほとんどの場合、最初の行でシークしている限り機能します。

そして最後に、あなたが示すデータの最後から6番目の文字は、 あなたが書いたように、'2'ではなく、です。'0'しかしもちろん、Unix 以外のシステムでは、他の何か (またはエラーが発生する) を簡単に確認できます。おそらく、 '.'Windows でエラー (またはエラー (またはエラー' ')) がメインフレーム OS で発生する可能性があります。

于 2012-09-05T08:02:55.333 に答える
4
myfile.seekg (6, std::ios::beg);

ここでは、先頭に向かってではなく、先頭から6 文字移動しています。使うだけ

myfile.seekg (-6, std::ios::end);
于 2012-09-05T07:51:22.173 に答える
2

ファイルの最後にあるtellg()を使用してファイルの完全なサイズを決定し、数値を減算して、> 0に対して検証してから、もう一度シークすることができます。これを試す場合は、ファイルがバイナリモードで開かれていることも確認する必要があります(私は覚えていますが、欠陥がある可能性があります)

myfile.seekg (0, ios::end);
// You have to ensure, myfile.tellg() > 6
myfile.seekg ( myfile.tellg() - 6, ios::beg );

編集:

seekgは、タイプstd::streamoffをオフセットとして取ります。

規格(ISO / IEC 14882:2003)は、多くの人がここで議論しているこの「問題」について、いくつかの非常に興味深いことを述べています。

セクション27.2。前方宣言、streamposはクラスfposです。

さらに進んでいくと、セクション27.4.3.2でfposの要件テーブルを見つけることができます。ここで、ストリームオフタイプへのクロージャを取得できます。ここで、明示的な要件はq = p + oであるため、fposクラスは演算子+(オフセット)。fposオブジェクトは、内部型である戻り型OFF_TのO(p)も定義する必要がありますが、ステートメントもあるため、std :: streamoffは型OFF_Tであり、標準内の定義への閉ループがあります。この操作のために。

したがって、この操作は明確に定義する必要があります。

他の意見も大歓迎です。

于 2012-09-05T08:12:00.913 に答える
1

最初のシークは最後までスキップし、2 番目のシークは先頭 + 6 までスキップします。

使用する:

 myfile.seekg(-6, std::ios::end);
于 2012-09-05T07:53:09.137 に答える
0

まず、ファイルの末尾に移動してからis.seekg (0, ios::end); 、位置を保存します: file_end_position = is.tellg();。次に、その位置にジャンプします: is.seekg (file_end_position-6, ios::end);、最後から 6 番目の文字を読み取ります。is.read (buf,1);

#include <iostream>
#include <fstream>
using namespace std;

int main () {
  int file_end_position;

  ifstream is;
  is.open ("test.txt", ios::binary );

  // get size of file:
  is.seekg (0, ios::end);
  file_end_position = is.tellg();
  is.seekg (0, ios::beg);


  //go to the end  of the file -6
  is.seekg (file_end_position-6, ios::end);

  char buf[1];

  // read the 6th character from the end of the file  
  is.read (buf,1);
  is.close();



  delete[] buffer;
  return 0;
}
于 2012-09-05T10:53:59.373 に答える