Вместо использования .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
и проверьте, равен ли по модулю вашего счетчика строк ноль. Если это так, создайте ваше следующее имя выходного файла, сбросьте нулевой счетчик строк, проверьте, открыт ли ваш выходной файл, и если это так, закройте его, затем откройте выходной файл, используя новое имя выходного файла, подтвердите, что он открыт, тогда это просто записать строку в выходной файл и увеличить счетчик строк, например,
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
строк в каждом. Посмотрите вещи и дайте мне знать, если у вас есть какие-либо вопросы.