C ++文件的32K整数用换行符分隔。我需要创建8个较小的文件,每个文件包含4096个int

问题描述 投票:-1回答:1

我有一个由换行符分隔的整数文件。

324872
27
256230
0
45767
276143
4
258283
189
153812
214521

文件大小为32768行。我需要将其分成4096行的8个较小的文件。我使用fstream将原始文件流式传输到char缓冲区中:

std::string fileOfInts(".txt");
char *buffer = new char[BUFFER_SIZE];
std::ifstream inputFromOrigin("origin.txt");
int fileIndex = 0;
while (inputFromOrigin)
{
    inputFromOrigin.read(buffer, BUFFER_SIZE);
    size_t count = inputFromOrigin.gcount();
    if (!count)
        break;

    std::ofstream createRunSizeFile;
    createRunSizeFile.open("fileOfInts" + std::to_string(fileIndex) + fileOfInts);
    int value;
    if (createRunSizeFile) {
        for (size_t i = 0, bufferSize = sizeof(buffer); i < bufferSize; i += sizeof(int)) {
            value = (int)buffer[i];
            createRunSizeFile << value << std::endl;
        }
    }
    createRunSizeFile.close();
    fileIndex++;
}
inputFromOrigin.close();
delete[] buffer;

但是当我从char缓冲区中提取int时,它一次只能读取两位数字,并将这两位数字放在一个文件中,所以我最终得到54个文件,每个文件都包含一个int:

32

UPDATE:

当我更改用于将缓冲区中的值分配给此的for循环时:

for (int i = 0; i < BUFFER_SIZE; i++)

我每个文件得到4096个唯一行,而不是传入的具有相同值的8个文件,而是得到53个文件,每行有两位数字:

10
49
57
57
54
48
50

我如何解析char缓冲区以将4096个唯一整数放入每个文件中?

更新-解决方案:

对于将来可能遇到此挑战的其他人,这是我如何将David的解决方案调整为现有代码的方法:

int fileIndex = 1;
int lineIndex = 0;
std::string line = "";
std::ofstream createRunSizeFile;
// loop through origin file line by line
while (getline(inputFromOrigin, line)) {
    // when file is 0 or 4066 lines long create a new file
    if (lineIndex % RUN == 0) {
        createRunSizeFile.open("fileOfInts" + std::to_string(fileIndex) + fileOfInts);
        lineIndex = 0;
        if (createRunSizeFile.is_open()) {
            createRunSizeFile.close();
        }
        // open new run size file and increment file counter
        createRunSizeFile.open("fileOfInts" + std::to_string(fileIndex++) + fileOfInts);
        if (!createRunSizeFile.good()) {
            std::cerr << "Error: Run Size File Failed to Open" << std::endl;
            return 1;
        }
    }
    // assign line from origin to the run size file
    createRunSizeFile << line << std::endl;
    lineIndex++;
}
inputFromOrigin.close();

我做出了错误的假设,即从char缓冲区中提取int比仅逐行查找要容易。该解决方案完全可以满足我现在需要做的事情。

c++ arrays fstream
1个回答
1
投票

而不是使用.read,只需使用getline即可将包含整数的行读入字符串。然后,只需保留一个行计数器,然后想出一些方案来为输出文件名写一个后缀,然后打开输出文件,然后将4096行写入文件,重置行计数器,然后打开下一个文件并重复,直到用完所有要读取的行。

您可以为每个子文件的行数使用#define常量,也可以声明一个常量,然后声明您的计数器(在fileno下面仅用作子文件后缀),声明一个字符串以用作缓冲区以保存从输入读取的行,然后保存两个文件-打开输入文件:

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

#define NLINES 4096     /* constant no. of lines for output subfiles */

int main (int argc, char **argv) {

    if (argc < 2) { /* validate at least 1 argument for filename */
        std::cerr << "usage: " << argv[0] << " filename\n";
        return 1;
    }

    size_t  n = 0,              /* line counter */
            fileno = 1;         /* output file suffix */
    std::string s {};           /* string to use as buffer */
    std::ifstream f (argv[1]);  /* open input file stream */
    std::ofstream subf;         /* output file stream */

    if (!f.good()) { /* validate input file stream stat/e good */
        std::cerr << "error: input file open failed.\n";
        return 1;
    }

要分割文件,只需将每一行读入s并检查行计数器的modulo是否为零。如果是这样,请创建下一个输出文件名,将行计数器重置为零,检查是否已打开输出文件,如果是,请关闭它,然后使用新的输出文件名打开输出文件,验证它是否已打开,然后就很简单了。将字符串写入输出文件并增加行数计数器,例如

    while (getline (f, s)) {        /* read each line from input file into s */
        if (n % NLINES == 0) {      /* if 0 or 4096 */
            /* create output filename "subfile_X" */
            std::string fname = { "subfile_" + std::to_string(fileno++) };
            n = 0;                  /* reset line count 0 */
            if (subf.is_open())     /* if output file open - close it */
                subf.close();
            subf.open (fname);      /* open new output file */
            if (!subf.good()) {     /* validate output file stream state good */
                std::cerr << "error: file open failed '" << fname << "'.\n";
                return 1;
            }
        }
        subf << s << '\n';      /* write s to output file */
        n++;                    /* increment line count */
    }

这确实是您所需要的。将零件缝在一起将给出完整的程序:

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

#define NLINES 4096     /* constant no. of lines for output subfiles */

int main (int argc, char **argv) {

    if (argc < 2) { /* validate at least 1 argument for filename */
        std::cerr << "usage: " << argv[0] << " filename\n";
        return 1;
    }

    size_t  n = 0,              /* line counter */
            fileno = 1;         /* output file suffix */
    std::string s {};           /* string to use as buffer */
    std::ifstream f (argv[1]);  /* open input file stream */
    std::ofstream subf;         /* output file stream */

    if (!f.good()) { /* validate input file stream stat/e good */
        std::cerr << "error: input file open failed.\n";
        return 1;
    }

    while (getline (f, s)) {        /* read each line from input file into s */
        if (n % NLINES == 0) {      /* if 0 or 4096 */
            /* create output filename "subfile_X" */
            std::string fname = { "subfile_" + std::to_string(fileno++) };
            n = 0;                  /* reset line count 0 */
            if (subf.is_open())     /* if output file open - close it */
                subf.close();
            subf.open (fname);      /* open new output file */
            if (!subf.good()) {     /* validate output file stream state good */
                std::cerr << "error: file open failed '" << fname << "'.\n";
                return 1;
            }
        }
        subf << s << '\n';      /* write s to output file */
        n++;                    /* increment line count */
    }
}

带有32k整数的示例输入文件

$ wc -l < dat/32kint.txt
32768

示例使用

不是很退出:

$ ./bin/filesplit dat/32kint.txt

结果子文件

$ for i in subfile*; do printf "%s - " "$i"; wc -l < "$i"; done
subfile_1 - 4096
subfile_2 - 4096
subfile_3 - 4096
subfile_4 - 4096
subfile_5 - 4096
subfile_6 - 4096
subfile_7 - 4096
subfile_8 - 4096

4096的八个文件各一个。仔细检查一下,如果您有任何问题,请告诉我。

© www.soinside.com 2019 - 2024. All rights reserved.