我有一个由换行符分隔的整数文件。
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比仅逐行查找要容易。该解决方案完全可以满足我现在需要做的事情。
而不是使用.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
的八个文件各一个。仔细检查一下,如果您有任何问题,请告诉我。