逐行从文件读入 vector<T> 对于二进制数据 C++ 不正确
Reading from file into vector<T> line by line works incorrect for binary data C++
有一个模板可以从文件中填写vector <T>
:
template<typename T, typename A>
void fill_vector_from_file(const std::string &filePath, std::vector<T, A> & target)
{
std::ifstream is(filePath, std::ifstream::in);
is.seekg(0, std::ifstream::end);
std::size_t size = is.tellg();
is.seekg(0, std::ifstream::beg);
target.reserve(size);
std::string line;
while (std::getline(is, line))
{
std::istringstream line_in(line);
while (line_in)
{
T val = 0;
if (line_in >> val)
{
target.push_back(val);
}
}
}
is.close();
文件中的数据可以是整数或二进制,每行存储一个数字,例如:
对于 int:
2
-3
4
对于二进制:
010
111
001
当我用 std::vector<int> v1
检查模板的整数时
和 std::vector<unsigned char> v2
, v2[0]
的结果是 0
而不是 010
.
(我想,我应该使用 unsigned char 来存储二进制文件)
问题:有没有办法修改模板,这样v2[0]
的结果就如预期的那样(010
)。
此代码有很多错误,但您的原始问题有以下答案:
将 0-1 ASCII 字符串转换为整数。 您的代码 line_in >> val
for val 类型 unsigned char
读取单个字符,例如 '0 '和'1'。您想要将由“0”和“1”组成的 ASCII 字符串(形成以 2 为基数的数字)转换为整数。
在这个 SO answer 中,您会发现 val = std::stoi(line, nullptr, 2);
会为您做到这一点。
因此,“-3”和“101”都不是 整数,而是 字符串,表示以 10 为底和以 10 为底的整数2,并且 stoi() 为您转换为整数。然而,在 base-10 的情况下,iostream operator>>()
也可以工作。 (您也可以查看 std::setbase()
。)
第二个文件似乎包含二进制格式的字符串。假设它们总是 3 位长,在这种情况下,如果您使用 std::bitset<3>
,您将完整读取每个数字。如果你使用 unsigned char
那么你一次只能读一个数字。这是您的功能,通过读取不同文件的示例稍作修改(我想您事先知道的格式)。作为奖励,还有如何将 std::bitset
向量转换为 unsigned char
的示例,如果您需要的话。
#include <vector>
#include <iostream>
#include <string>
#include <fstream>
#include <bitset>
#include <algorithm> // std::transform
template<typename T, typename A>
void fill_vector_from_file(std::string const &filePath, std::vector<T, A> &vec)
{
std::ifstream ifs(filePath);
T val;
while (ifs >> val)
vec.push_back(val);
}
int main()
{
// make sample files
std::ofstream ofs("myfile.txt");
ofs << "2\n" << "-3\n" << "4\n";
ofs.close();
ofs.open("myfile2.txt");
ofs << "010\n" << "111\n" << "001\n";
ofs.close();
// fill <int> vector
std::vector<int> vi;
fill_vector_from_file("myfile.txt", vi);
// print int vector
for (auto n : vi)
std::cout << n << std::endl;
// fill <bitset> vector
std::vector<std::bitset<3>> vbs;
fill_vector_from_file("myfile2.txt", vbs);
// print bitset vector
for (auto n : vbs)
std::cout << n << std::endl;
// [OPTIONAL] convert to vector <unsigned char>
std::vector<unsigned char> vuc(vbs.size());
std::transform(vbs.begin(), vbs.end(), vuc.begin(),
[](std::bitset<3> const &bs) -> unsigned char { return static_cast<unsigned char>(bs.to_ulong()); });
// print vector <unsigned char>
for (auto n : vuc)
std::cout << int(n) << std::endl;
return 0;
}
工作演示:http://coliru.stacked-crooked.com/view?id=42aa04e34e4194c1
2
-3
4
010
111
001
2
7
1
有一个模板可以从文件中填写vector <T>
:
template<typename T, typename A>
void fill_vector_from_file(const std::string &filePath, std::vector<T, A> & target)
{
std::ifstream is(filePath, std::ifstream::in);
is.seekg(0, std::ifstream::end);
std::size_t size = is.tellg();
is.seekg(0, std::ifstream::beg);
target.reserve(size);
std::string line;
while (std::getline(is, line))
{
std::istringstream line_in(line);
while (line_in)
{
T val = 0;
if (line_in >> val)
{
target.push_back(val);
}
}
}
is.close();
文件中的数据可以是整数或二进制,每行存储一个数字,例如:
对于 int:
2
-3
4
对于二进制:
010
111
001
当我用 std::vector<int> v1
检查模板的整数时
和 std::vector<unsigned char> v2
, v2[0]
的结果是 0
而不是 010
.
(我想,我应该使用 unsigned char 来存储二进制文件)
问题:有没有办法修改模板,这样v2[0]
的结果就如预期的那样(010
)。
此代码有很多错误,但您的原始问题有以下答案:
将 0-1 ASCII 字符串转换为整数。 您的代码 line_in >> val
for val 类型 unsigned char
读取单个字符,例如 '0 '和'1'。您想要将由“0”和“1”组成的 ASCII 字符串(形成以 2 为基数的数字)转换为整数。
在这个 SO answer 中,您会发现 val = std::stoi(line, nullptr, 2);
会为您做到这一点。
因此,“-3”和“101”都不是 整数,而是 字符串,表示以 10 为底和以 10 为底的整数2,并且 stoi() 为您转换为整数。然而,在 base-10 的情况下,iostream operator>>()
也可以工作。 (您也可以查看 std::setbase()
。)
第二个文件似乎包含二进制格式的字符串。假设它们总是 3 位长,在这种情况下,如果您使用 std::bitset<3>
,您将完整读取每个数字。如果你使用 unsigned char
那么你一次只能读一个数字。这是您的功能,通过读取不同文件的示例稍作修改(我想您事先知道的格式)。作为奖励,还有如何将 std::bitset
向量转换为 unsigned char
的示例,如果您需要的话。
#include <vector>
#include <iostream>
#include <string>
#include <fstream>
#include <bitset>
#include <algorithm> // std::transform
template<typename T, typename A>
void fill_vector_from_file(std::string const &filePath, std::vector<T, A> &vec)
{
std::ifstream ifs(filePath);
T val;
while (ifs >> val)
vec.push_back(val);
}
int main()
{
// make sample files
std::ofstream ofs("myfile.txt");
ofs << "2\n" << "-3\n" << "4\n";
ofs.close();
ofs.open("myfile2.txt");
ofs << "010\n" << "111\n" << "001\n";
ofs.close();
// fill <int> vector
std::vector<int> vi;
fill_vector_from_file("myfile.txt", vi);
// print int vector
for (auto n : vi)
std::cout << n << std::endl;
// fill <bitset> vector
std::vector<std::bitset<3>> vbs;
fill_vector_from_file("myfile2.txt", vbs);
// print bitset vector
for (auto n : vbs)
std::cout << n << std::endl;
// [OPTIONAL] convert to vector <unsigned char>
std::vector<unsigned char> vuc(vbs.size());
std::transform(vbs.begin(), vbs.end(), vuc.begin(),
[](std::bitset<3> const &bs) -> unsigned char { return static_cast<unsigned char>(bs.to_ulong()); });
// print vector <unsigned char>
for (auto n : vuc)
std::cout << int(n) << std::endl;
return 0;
}
工作演示:http://coliru.stacked-crooked.com/view?id=42aa04e34e4194c1
2
-3
4
010
111
001
2
7
1