2016-08-10 10 views
0

これは、すべての行をdiskData.datファイルから24HrDiskData.datファイルにコピーするプログラムです。今のところ、私はdiskData.datから24HrDiskData.dat期待最後のn行をあるファイルから別のファイルに書き込む

#include <iostream> 
#include <stdio.h> 
#include <fstream> 
#include <stdlib.h> 

using namespace std; 

int main(int argc, char *argv[]) { 
    FILE *HrData; 
    char tempData[1024]; 
    int flag = 0; 
    ofstream fout; 

    fout.open("24HrDiskData.dat", ios::app); // open file for appending 
    assert (!fout.fail()); 

    if ((HrData = fopen("/home/xvishuk/diskData.dat", "r")) == NULL) { 
     printf("\nFile cannot be opened"); 
    } 
    while (fgets(tempData, 1024, HrData) != NULL) { 
     fout << tempData; // write the data to the file 
    } 

    return 0; 
} 

区切られたデータのサンプルパターン

|Sat Mar 26 18:47:57 2016|1|1|182|60.66|3|30|4782|31|68|4|3467750|110|43.1562|64| 
|Sat Mar 26 19:01:49 2016|1|1|140|46.26|3.03|30|4782|30|68|4|3467764|96|43.1562|64| 
|Sat Mar 26 19:15:40 2016|1|1|184|61.07|3.01|30|4782|30|68|4|3467777|112|43.1562|64| 
|Sat Mar 26 19:29:30 2016|1|1|180|59.91|3|30|4782|32|68|4|3467791|98|43.1562|64| 
|Sat Mar 26 19:43:20 2016|1|1|194|64.61|3|30|4782|32|68|4|3467805|114|43.1562|64| 
|Sat Mar 26 19:57:17 2016|1|1|170|56.62|3|30|4782|30|68|4|3467818|102|43.1562|64| 
|Sat Mar 26 20:11:14 2016|1|1|140|46.32|3.02|30|4782|30|68|4|3467832|118|43.1562|64| 
|Sat Mar 26 20:25:12 2016|1|1|176|58.35|3.02|30|4782|30|68|4|3467846|104|43.1562|64| 
|Sat Mar 26 20:39:10 2016|1|1|202|66.9|3.02|30|4782|30|68|4|3467859|120|43.1562|64| 
|Sat Mar 26 20:53:11 2016|1|1|198|65.85|3.01|30|4782|31|68|4|3467873|106|43.1562|64| 
|Sat Mar 26 21:07:12 2016|1|1|184|60.97|3.02|30|4782|32|68|4|3467887|92|43.1562|64| 
|Sat Mar 26 21:21:11 2016|1|1|152|50.28|3.02|30|4782|31|68|4|3467901|108|43.1562|64| 
|Sat Mar 26 21:35:16 2016|1|1|168|55.77|3.01|30|4782|30|68|4|3467915|94|43.1562|64| 
|Sat Mar 26 21:49:20 2016|1|1|172|57.03|3.02|30|4782|31|68|4|3467928|112|43.1562|64| 
|Sat Mar 26 22:03:26 2016|1|1|152|50.56|3.01|30|4782|33|68|4|3467942|98|43.1562|64| 
|Sat Mar 26 22:17:32 2016|1|1|174|57.86|3.01|30|4782|31|68|4|3467956|114|43.1562|64| 
|Sat Mar 26 22:31:38 2016|1|1|156|51.86|3.01|30|4782|30|68|4|3467970|100|43.1562|64| 
|Sat Mar 26 22:45:44 2016|1|1|202|66.57|3.03|30|4782|30|68|4|3467984|116|43.1562|64| 
|Sat Mar 26 22:59:55 2016|1|1|188|62.4|3.01|30|4782|31|68|4|3467998|102|43.1562|64| 
|Sat Mar 26 23:14:06 2016|1|1|164|53.95|3.04|30|4782|32|68|4|3468012|118|43.1562|64| 
|Sat Mar 26 23:28:17 2016|1|1|168|55.78|3.01|30|4782|31|68|4|3468026|104|43.1562|64| 
|Sat Mar 26 23:42:28 2016|1|1|176|58.33|3.02|30|4782|30|68|4|3468040|120|43.1562|64| 
|Sat Mar 26 23:56:39 2016|1|1|170|55.76|3.05|30|4782|30|68|4|3468053|106|43.1562|64| 
|Sun Mar 27 00:10:54 2016|1|1|172|56.97|3.02|30|4782|31|68|4|3468067|92|43.1562|64| 
|Sun Mar 27 00:25:13 2016|1|1|184|61.23|3.01|30|4782|33|68|4|3468081|108|43.1562|64| 
|Sun Mar 27 00:39:26 2016|1|1|188|62.12|3.03|30|4782|31|68|4|3468096|94|43.1562|64| 
|Sun Mar 27 00:53:42 2016|1|1|170|56.42|3.01|30|4782|30|68|4|3468110|110|43.1562|64| 
|Sun Mar 27 01:07:58 2016|1|1|174|57.8|3.01|30|4782|31|68|4|3468124|96|43.1562|64| 

への最後ののn行をコピーしたい別のファイルからすべての行をコピーしています出力

最後の10レコード。

|Sat Mar 26 22:45:44 2016|1|1|202|66.57|3.03|30|4782|30|68|4|3467984|116|43.1562|64| 
|Sat Mar 26 22:59:55 2016|1|1|188|62.4|3.01|30|4782|31|68|4|3467998|102|43.1562|64| 
|Sat Mar 26 23:14:06 2016|1|1|164|53.95|3.04|30|4782|32|68|4|3468012|118|43.1562|64| 
|Sat Mar 26 23:28:17 2016|1|1|168|55.78|3.01|30|4782|31|68|4|3468026|104|43.1562|64| 
|Sat Mar 26 23:42:28 2016|1|1|176|58.33|3.02|30|4782|30|68|4|3468040|120|43.1562|64| 
|Sat Mar 26 23:56:39 2016|1|1|170|55.76|3.05|30|4782|30|68|4|3468053|106|43.1562|64| 
|Sun Mar 27 00:10:54 2016|1|1|172|56.97|3.02|30|4782|31|68|4|3468067|92|43.1562|64| 
|Sun Mar 27 00:25:13 2016|1|1|184|61.23|3.01|30|4782|33|68|4|3468081|108|43.1562|64| 
|Sun Mar 27 00:39:26 2016|1|1|188|62.12|3.03|30|4782|31|68|4|3468096|94|43.1562|64| 
|Sun Mar 27 00:53:42 2016|1|1|170|56.42|3.01|30|4782|30|68|4|3468110|110|43.1562|64| 
+2

あなたは 'tail'プログラムが既にこの正確な振る舞いで存在していることに気付きましたか? –

+0

投稿された予想出力は、las 10のレコードではなく**ですか? – chqrlie

+0

ありがとうございました! @BenVoigt私は同意しますが、私はC++プログラムを使用してそれをする必要があります – user1885183

答えて

4

避けるために、モジュール式のインデックスを使用して、最後のnラインを作成するには、n文字列の配列を割り当てることができ、あなたは、配列が一杯になった場合にのみ、最後のnを保ち、それらを読んで、それに行を保存します不要なコピー。

ファイルの最後に達したら、配列から行を出力します。

また、CとC++の混在は避けてください。 <stdio.h>または<iostream>を使用してください。両方を同時に使用すると、エラーが発生しやすくなり、控えめです。

#include <errno.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#define N 100 

int main(void) { 
    char line[1024]; 
    char *stash[N] = { NULL }; 
    int i, j; 
    FILE *HrData, *fout; 

    if ((fout = fopen("24HrDiskData.dat", "a")) == NULL) { 
     fprintf(stderr, "cannot open 24HrDiskData.dat for appending: %s\n", 
       strerror(errno)); 
     return 1; 
    } 
    if ((HrData = fopen("/home/xvishuk/diskData.dat", "r")) == NULL) { 
     fprintf(stderr, "cannot open input file: %s\n", 
       strerror(errno)); 
     return 1; 
    } 
    for (i = 0; fgets(line, 1024, HrData) != NULL;) { 
     free(stash[i]); 
     stash[i] = strdup(line); 
     i = (i + 1) % N; 
    } 
    fclose(HrData); 
    for (j = i;;) { 
     if (stash[i]) 
      fputs(stash[i], fout); 
     i = (i + 1) % N; 
     if (i == j) 
      break; 
    } 
    fclose(fout); 
    return 0; 
} 
+0

好奇心のために、なぜメモリに行を保存する必要がありますか?行を格納するのに十分なメモリがありますか? –

+0

@ThomasMatthews:メモリに行を格納するのが最も簡単な方法です。入力ファイルがデバイスまたはパイプであっても動作します。入力にシークすることはできません。現代のコンピュータは、最も合理的な 'n 'の値と入力ファイルの種類のために十分なRAMを持っています。 – chqrlie

+0

より良い方法は、動的に割り当てるので、 'std :: string'を使うことです。 'std :: getline'を' std :: ifstream'と一緒に使うことができます。 –

2

二つのパス:ここ

はCでの単純な実装です。

最初のパスで行を数え、ファイルの位置を保存します。

2回目のパスで、コピーを開始する行番号を計算します。コンテナ内のファイルの位置を調べます。ファイル位置を探します。コピーを開始します。

編集1:サンプルコード

#include <iostream> 
#include <fstream> 
#include <string> 
#include <vector> 

int main(void) 
{ 
    std::string text_line; 
    std::vector<std::streampos> file_positions; 
    std::ifstream input_file("my_file.txt"); 
    file_positions.push_back(input_file.tellg()); 
    while (std::getline(input_file, text_line)) 
    { 
     file_positions.push_back(input_file.tellg()); 
    } 
    // The total lines is file_positions.size(). 
    // Return the last 13 lines 
    const unsigned int total_lines = file_positions.size(); 
    std::streampos seek_position = 0; 
    unsigned int index = 0U; 
    if (total_lines > 13U) 
    { 
     index = total_lines - 13U; 
    } 
    input_file.clear(); 
    input_file.seekg(file_positions[index]); 
    // Copy text lines to output file... 
    return 0; 
} 

編集2 - より効率的な方法
ファイルを読みとしてあなたはNテキスト行のコンテナを維持することができます。

#include <deque> 
//... 
int main(void) 
{ 
    std::deque<std::string> text_lines(N); 
    while (std::getline(input_file, text_line)) 
    { 
    if (text_lines.size() == N) 
    { 
     text_lines.pop_front(); 
    } 
    text_lines.push_back(text_line); 
    } 
    // Now copy the text lines from the `std::deque` to the output file. 
    //... 
    return 0; 
} 
+0

なぜ2回のパスを使用するのですか?とにかく行ごとにファイルを読み込まなければならないので、1回のパスですべてを行なわないでください。 – NathanOliver

+1

1つで、ファイル内にいくつの行があるのか​​わかりません。第2に、ファイル全体を格納するのに十分なメモリがない可能性があります。 –

+0

これは、入力ファイルがパイプまたはデバイスの場合、またはOPファイルが読み込んでいるようなログファイルの場合のように、入力ファイルがシークバック中に変更された場合は機能しません。 – chqrlie

関連する問題