How to write vector<uint_8> to a file in c++? - c++

I have vector<uint_8> data filled and want to write this data into a file using c++? Tried out but didn't find any reference.
const std::vector<uint8_t> buffer; // let's assume that i'ts filled with values
std::ofstream out("file.txt", std::ios::out | std::ios::binary);
out.write(&buffer, buffer.size());
but not successfull. Also is it correct to open file in binary mode for this?

You can cast the data pointer as recommended by others:
#include <vector>
#include <fstream>
int main()
{
std::vector<uint8_t> temp;
temp.push_back(97);
temp.push_back(98);
temp.push_back(99);
const std::vector<uint8_t> buffer(temp); // let's assume that i'ts filled with values
std::ofstream out("file.txt", std::ios::out | std::ios::binary);
out.write(reinterpret_cast<const char*>(buffer.data()), buffer.size());
out.close();
}
Output: file.txt
abc
If you're viewing this via a text file containing binary data (uint8_t), you'll expect to see the following in the file where each uint8_t corresponds with an ascii symbol:
https://www.asciitable.com/
If your intention is to write the integer values to the file instead of the raw binary data, then you would do this instead:
#include <vector>
#include <fstream>
#include <string>
int main()
{
std::vector<uint8_t> temp;
temp.push_back(97);
temp.push_back(98);
temp.push_back(99);
const std::vector<uint8_t> buffer(temp); // let's assume that i'ts filled with values
std::ofstream out("file.txt", std::ios::out | std::ios::binary);
for (auto v : buffer)
{
std::string str = std::to_string(v);
out.write(str.c_str(), str.length());
}
out.close();
}
Output: file.txt
979899

Related

writting a binary in c++

So i have this program that supposedly reads any file (e.g images, txt) and get its data and creates a new file with that same data. The problem is that i want the data in an array and not in a vector and when i copy that same data to char array, whenever i try to write those bits into a file it doesnt write the file properly.
So the question is how can i get the data from std::ifstream input( "hello.txt", std::ios::binary ); and save it an char array[] so that i can write that data into a new file?
Program:
#include <stdlib.h>
#include <string.h>
#include <fstream>
#include <iterator>
#include <vector>
#include <iostream>
#include <algorithm>
int main()
{
FILE *newfile;
std::ifstream input( "hello.txt", std::ios::binary );
std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(input), {});
char arr[buffer.size()];
std::copy(buffer.begin(), buffer.end(), arr);
int sdfd;
sdfd = open("newhello.txt",O_WRONLY | O_CREAT);
write(sdfd,arr,strlen(arr)*sizeof(char));
close(sdfd);
return(0);
}
Try this:
(It basically uses a char*, but it's an array here. You probably can't have an array in the stack in this case)
#include <iostream>
#include <fstream>
int main() {
std::ifstream input("hello.txt", std::ios::binary);
char* buffer;
size_t len; // if u don't want to delete the buffer
if (input) {
input.seekg(0, input.end);
len = input.tellg();
input.seekg(0, input.beg);
buffer = new char[len];
input.read(buffer, len);
input.close();
std::ofstream fileOut("newhello.txt");
fileOut.write(buffer, len);
fileOut.close();
// delete[] buffer; u may delete the buffer or keep it for further use anywhere else
}
}
This should probably solve your problem, remember to always have the length (len here) of the buffer if you don't want to delete it.
More here

Is there a way I can write a string into a FILE?

I'm trying to write a string into a file, but I don't know how to do it, I have tried to use wstring instead of string in my randomString() string function, and other things just to write a string to a file.
The if condition is checking if file is created, and if yes, write to it.
fopen is used to open the file, path1 variable is the path to my file, and the "w" is equal to write.
randomString() is a string function.
char buffer[100] = { randomString() };
FILE* file;
file = fopen(path1, "w");
if (file) {
fwrite(buffer, sizeof(char), sizeof(buffer), file);
fclose(file);
}
return;
If you're using a new-ish compiler you can try std::filesystem
#include <iostream>
#include <fstream>
#include <filesystem>
namespace fs = std::filesystem;
int main() {
auto directoryToWriteTo = fs::current_path(); // returns a fs::path object
std::ofstream fileStream(directoryToWriteTo.string() + "/nameOfYourFile.txt");
if(fileStream.is_open())
fileStream << "Whatever string you want to write to a file\n";
}
std::filesystem isn't needed for writing to one file, but it does make things like iterating over all files in a directory easy, as adapted from the cppreference.com examples.
#include <fstream>
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main() {
auto directoryToTraverse = fs::current_path();
for(auto& p: fs::directory_iterator(directoryToTraverse)){
if(fs::is_regular_file(p)){
std::ofstream tmpStream(p,std::ios_base::app); //open file in append mode
tmpStream << "Append a string to each regular file in your directory\n";
}
}
}
It also allows one to change file permissions programmatically with standard c++.
If you are just trying to print out to a file the contents of a string, using fwrite, then you need to do something like the following
std::string str = randomString();
if ( file ) {
fwrite( str.c_str(), sizeof( char ), str.size(), file );
fclose( file );
}
Since fwrite expects the first parameter to be void *, an std::string is not compatible; however, a char * is. By calling .c_str() on the string, you would have a char * to work with. The second parameter is the size of the type, which for a std::string is char, so sizeof( char ) gives the size (which is 1). The third parameter is the count (number of characters to write), which can easily be gotten from str.size().

C++ - Read from file to std vector with vector<>.data() using file.read()

I am trying to read data from a file and put it into a vector<unsigned char> using the file.read() method, but something goes wrong.
typedef unsigned char BYTE;
#include <fstream>
#include <string.h>
#include <vector>
#include <iostream>
#include <iterator>
class ROM{
private:
std::vector<BYTE> RomName;
public:
ROM (const char* t_RomFileName){
std::ifstream ROMFile(t_RomFileName, std::ifstream::ate | std::ifstream::binary);
RomName.reserve(16);
if (ROMFile.is_open()){
size = ROMFile.tellg();
ROMFile.seekg (80, ROMFile.beg);
ROMFile.read((char*)RomName.data(), 16);
for(std::vector<BYTE>::iterator it = RomName.begin(); it != RomName.end(); ++it ){
std::cout << *it;
}
...
}
};
Nothing is printed on the screen and the RomName.size() returns 0. Also, the file pointer moved of 16 bytes. I tried with char* test = new char[16] and reading in it all works. Where I wrong?

resize file after certain condition. c++ resize_file not work in loop

i don't know whats the problem with filesystem resize_file standart c++ 17 in visual studio. when i test the STL with manual. it can resize as expect. when using in conditional. its like a bug. the result output is split 2 parts. i test it a file 2MB size. the result i should expected is input file should be resize to 0 byte in the end.
std::ifstream input("D:/input.exe", std::ios::binary);
if (input.is_open())
{
std::ofstream output("D:/output.exe", std::ios::binary | std::ios::ate | std::ios::app);
auto p = std::filesystem::path("D:/input.exe");
std::vector<char> buffer(1048576);
do
{
long long setPosition;
if (std::filesystem::file_size(p) > buffer.size())
{
setPosition = (std::filesystem::file_size(p) - buffer.size());
input.seekg(setPosition);
}
else
{
input.seekg(0);
}
input.read(buffer.data(), buffer.size());
std::streamsize dataSize = input.gcount();
if (dataSize)
{
output.seekp(0);
output.write(buffer.data(), dataSize);
long long resizeFile = (std::filesystem::file_size(p) - dataSize);
std::filesystem::resize_file(p, resizeFile);
}
else
{
output.close();
input.close();
break;
}
} while (true);
}
else
{
std::cout << "File is not exist";
}
What you are trying to do will not work. resize_file will truncate the file at the end of the file, so when you read X bytes from the start of the file and then truncate the file, you will chop off X bytes at the end of the file. You will probably end up with both input.exe and output.exe containing the beginning of the original input.exe. What you should do is to truncate the file after you've read it. The below will make output.exe a copy of the original input.exe and input.exe will be 0 bytes.
#include <iostream>
#include <fstream>
#include <filesystem>
int main() {
auto p = std::filesystem::path("D:/input.exe");
std::ifstream input(p, std::ios::binary);
if (input)
{
std::ofstream output("D:/output.exe", std::ios::binary);
std::vector<char> buffer(1048576);
while (true) {
input.read(buffer.data(), buffer.size());
std::streamsize dataSize = input.gcount();
if (dataSize==0) break;
output.write(buffer.data(), dataSize);
}
std::filesystem::resize_file(p, 0);
}
else
{
std::cout << "File does not exist";
}
}

Combine big files

I'm trying to join two big files (like the UNIX cat command: cat file1 file2 > final) in C++.
I don't know how to do it because every method that I try it's very slow (for example, copy the second file into the first one line by line)
¿What is the best method for do that?
Sorry for being so brief, my english is not too good
If you're using std::fstream, then don't. It's intended primarily for formatted input/output, and char-level operations for it are slower than you'd expect. Instead, use std::filebuf directly. This is in addition to suggestions in other answers, specifically, using the larger buffer size.
Use binary-mode in the standard streams to do the job, don't deal with it as formatted data.
This is a demo if you want transfer the data in blocks:
#include <fstream>
#include <vector>
std::size_t fileSize(std::ifstream& file)
{
std::size_t size;
file.seekg(0, std::ios::end);
size = file.tellg();
file.seekg(0, std::ios::beg);
return size;
}
int main()
{
// 1MB! choose a conveinent buffer size.
const std::size_t blockSize = 1024 * 1024;
std::vector<char> data(blockSize);
std::ifstream first("first.txt", std::ios::binary),
second("second.txt", std::ios::binary);
std::ofstream result("result.txt", std::ios::binary);
std::size_t firstSize = fileSize(first);
std::size_t secondSize = fileSize(second);
for(std::size_t block = 0; block < firstSize/blockSize; block++)
{
first.read(&data[0], blockSize);
result.write(&data[0], blockSize);
}
std::size_t firstFilerestOfData = firstSize%blockSize;
if(firstFilerestOfData != 0)
{
first.read(&data[0], firstFilerestOfData);
result.write(&data[0], firstFilerestOfData);
}
for(std::size_t block = 0; block < secondSize/blockSize; block++)
{
second.read(&data[0], blockSize);
result.write(&data[0], blockSize);
}
std::size_t secondFilerestOfData = secondSize%blockSize;
if(secondFilerestOfData != 0)
{
second.read(&data[0], secondFilerestOfData);
result.write(&data[0], secondFilerestOfData);
}
first.close();
second.close();
result.close();
return 0;
}
Using plain old C++:
#include <fstream>
std::ifstream file1("x", ios_base::in | ios_base::binary);
std::ofstream file2("y", ios_base::app | ios_base::binary);
file2 << file1.rdbuf();
The Boost headers claim that copy() is optimized in some cases, though I'm not sure if this counts:
#include <boost/iostreams/copy.hpp>
// The following four overloads of copy_impl() optimize
// copying in the case that one or both of the two devices
// models Direct (see
// http://www.boost.org/libs/iostreams/doc/index.html?path=4.1.1.4)
boost::iostreams::copy(file1, file2);
update:
The Boost copy function is compatible with a wide variety of types, so this can be combined with Pavel Minaev's suggestion of using std::filebuf like so:
std::filebuf file1, file2;
file1.open("x", ios_base::in | ios_base::binary);
file2.open("y", ios_base::app | ios_base::binary);
file1.setbuf(NULL, 64 * 1024);
file2.setbuf(NULL, 64 * 1024);
boost::iostreams::copy(file1, file2);
Of course the actual optimal buffer size depends on many variables, 64k is just a wild guess.
As an alternative which may or may not be faster depending on your file size and memory on the machine. If memory is tight, you can make the buffer size smaller and loop over the f2.read grabbing the data in chunks and writing to f1.
#include <fstream>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
ofstream f1("test.txt", ios_base::app | ios_base::binary);
ifstream f2("test2.txt");
f2.seekg(0,ifstream::end);
unsigned long size = f2.tellg();
f2.seekg(0);
char *contents = new char[size];
f2.read(contents, size);
f1.write(contents, size);
delete[] contents;
f1.close();
f2.close();
return 1;
}