将最后n行从一个文件写入另一个文件

时间:2016-08-10 15:01:45

标签: c++ unix

这是我编写的程序,它将diskData.dat文件中的所有行复制到24HrDiskData.dat文件。截至目前,我正在将所有行从一个文件复制到另一个文件我希望将最后一行 n 行从diskData.dat复制到24HrDiskData.dat

#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|

预期输出

最近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 个答案:

答案 0 :(得分:3)

要仅写入最后n行,您可以分配一个n字符串数组,并在读取时将行存储到其中,只保留数组中的最后n行填写,使用模块化索引,以避免不必要的复制。

当你到达文件末尾时,输出数组中的行。

同时避免混合使用C和C ++。使用<stdio.h><iostream>,但同时使用两者都容易出错且不够优雅。

这是C中的一个简单实现:

#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;
}

答案 1 :(得分:1)

两次通过。

首先传递,计算线条并存储它们的文件位置。

第二遍,计算您要开始复制的行号。在容器中查找其文件位置。寻找档案位置。开始复制。

编辑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;
}