Replace QByteArray with std C++ functions - c++

I'm writing a simple binary file that must contain the contents of another binary file and a string name of this (another) file at the end.
I found this sample code that uses QByteArray from the Qt library. My question is: is it possible to do the same with std c++ functions?
char buf;
QFile sourceFile( "c:/input.ofp" );
QFileInfo fileInfo(sourceFile);
QByteArray fileByteArray;
// Fill the QByteArray with the binary data of the file
fileByteArray = sourceFile.readAll();
sourceFile.close();
std::ofstream fout;
fout.open( "c:/test.bin", std::ios::binary );
// fill the output file with the binary data of the input file
for (int i = 0; i < fileByteArray.size(); i++) {
buf = fileByteArray.at(i);
fout.write(&buf, 1);
}
// Fill the file name QByteArray
QByteArray fileNameArray = fileInfo.fileName().toLatin1();
// fill the end of the output binary file with the input file name characters
for ( int i = 0; i < fileInfo.fileName().size();i++ ) {
buf = fileNameArray.at(i);
fout.write( &buf, 1 );
}
fout.close();

Open your files in binary mode and copy in "one shot" via rdbuf:
std::string inputFile = "c:/input.ofp";
std::ifstream source(input, std::ios::binary);
std::ofstream dest("c:/test.bin", std::ios::binary);
dest << source.rdbuf();
Then write filename at the end:
dest.write(input.c_str(), input.length());
You can find more ways here.

Yes, refer to fstream / ofstream. You could do it like this:
std::string text = "abcde"; // your text
std::ofstream ofstr; // stream object
ofstr.open("Test.txt"); // open your file
ofstr << text; // or: ofstr << "abcde"; // append text

Related

C++ can't create, read or write a file

std::string uncomment(std::ifstream& infile)
{
std::fstream outfile;
std::string buffer;
std::string tmp;
while(getline(infile, buffer)) {
if(!(buffer[0] == '#')) {
buffer += tmp;
}
}
return buffer;
}
int main(int argc, char const *argv[])
{
std::string filename = argv[1];
std::ifstream infile(filename);
std::fstream outfile("outfile.txt");
std::string buffer = uncomment(infile);
std::cout << buffer << std::endl;
outfile << buffer << std::endl;
outfile.close();
infile.close();
}
Why this code does not produce a new file "outfile.txt"?
Why this code does not print uncommented string on line 22?
I am not sure what std::fstream does but I think you want to use std::ofstream instead.
Looking quickly at docs your outfile constructor is using the default fstream constructor and you don't specify the mode (http://www.cplusplus.com/reference/fstream/fstream/fstream/)
Have you tried using an ofstream constructor since this is an output file?
To create file (if not exist) with fstream you need to pass std::ios::out as open mode to your fstream constructor. like this
std::fstream outfile("outfile.txt", std::ios::out);
Note : Here you don't specified the path to your desired outfile.txt, so it will be generate in your project directory, make sure you check there.
First of all you need to use std::ofstream object to create output file. Or you need to use something like this
std::fstream fs;
fs.open ("outfile.txt", std::fstream::out);

Reading any file as binary in C++?

How might I read any file type as binary in C++? So far, I've been able to read .txt files in binary using std::bitset like so:
std::ifstream myfile;
myfile.open("example.txt", std::ios::binary);
while (getline (myfile, line) ) {
for (std::size_t i = 0; i<line.size(); ++i) {
std::bitset<8> a = std::bitset<8>(line[i]); //convert every character to binary, save it in a
std::cout<<((char)std::bitset<8>(a).to_ulong())<<'\n';
}
}
In the first line, how might I read a file like sound.mp3 or word.docx as a binary file? I understand that in they really just are binary files, but how can I read them as such?
Thanks!
By casting from a block of memory of chars to binary, you can read a file as binary.
std::streampos size;
char * memblock;
std::ifstream myfile ("sound.mp3", std::ios::in|std::ios::binary|std::ios::ate);
//ios::ate puts the reader at the end of the file
if (file.is_open())
{
size = myfile.tellg();
memblockChar = new char [size];
myfile.seekg (0, std::ios::beg);
myfile.read (memblockChar, size);
myfile.close();
for (int i = 0; i<size; i++) {
std::cout << (((std::bitset<8>)memblockChar[i]).to_ulong()) << '\n';
}
delete[] memblockChar;
}
else std::cout<<"Unable to open file"<<std::endl;
This could be used in a main method, or anywhere else.

saving text file in binary

I have a project witch I have to back up my text files in binary mode with the destination that is getting from the user.
I was thinking to open my text files in binary and close them in the address that I have got from the user. but I don't know how to do that.
is there a way to close the files in a new address(saving them where ever I want) and not set an address directly because it's suppose to set by the user
Here is sample code to save the file:
#include <fstream>
int main () {
std::ofstream ofs;
ofs.open ("test.txt", std::ofstream::out | std::ofstream::binary | std::ofstream::trunc);
ofs << " data goes here";
ofs.close();
return 0;
}
The following is sample code to copy files:
ifstream source("from.txt", ios::binary);
ofstream dest("to.txt", ios::binary);
source.seekg(0, ios::end);
ifstream::pos_type size = source.tellg(); // file size
source.seekg(0);
char* buffer = new char[size]; // allocate memory for buffer
// copy file
source.read(buffer, size);
dest.write(buffer, size);
// clean up
delete[] buffer;
source.close();
dest.close();

How to write a non-English string to a file and read from that file with C++?

I want to write a std::wstring onto a file and need to read that content as std:wstring. This is happening as expected when the string as L"<Any English letter>". But the problem is happening when we have character like Bengali, Kannada, Japanese etc, any kind of non English letter. Tried various options like:
Converting the std::wstring to std::string and write onto the file and reading time read as std::string and convert as std::wstring
Writing is happening (I could see from edito) but reading time getting wrong character
Writing std::wstring onto wofstream, this is also not helping for
native language character letters like std::wstring data = L"হ্যালো ওয়ার্ল্ড";
Platform is mac and Linux, Language is C++
Code:
bool
write_file(
const char* path,
const std::wstring data
) {
bool status = false;
try {
std::wofstream file(path, std::ios::out|std::ios::trunc|std::ios::binary);
if (file.is_open()) {
//std::string data_str = convert_wstring_to_string(data);
file.write(data.c_str(), (std::streamsize)data.size());
file.close();
status = true;
}
} catch (...) {
std::cout<<"exception !"<<std::endl;
}
return status;
}
// Read Method
std::wstring
read_file(
const char* filename
) {
std::wifstream fhandle(filename, std::ios::in | std::ios::binary);
if (fhandle) {
std::wstring contents;
fhandle.seekg(0, std::ios::end);
contents.resize((int)fhandle.tellg());
fhandle.seekg(0, std::ios::beg);
fhandle.read(&contents[0], contents.size());
fhandle.close();
return(contents);
}
else {
return L"";
}
}
// Main
int main()
{
const char* file_path_1 = "./file_content_1.txt";
const char* file_path_2 = "./file_content_2.txt";
//std::wstring data = L"Text message to write onto the file\n"; // This is happening as expected
std::wstring data = L"হ্যালো ওয়ার্ল্ড";
// Not happening as expected.
// Lets write some data
write_file(file_path_1, data);
// Lets read the file
std::wstring out = read_file(file_path_1);
std::wcout<<L"File Content: "<<out<<std::endl;
// Let write that same data onto the different file
write_file(file_path_2, out);
return 0;
}
How a wchar_t is output depends on the locale. The default
locale ("C") generally doesn't accept anything but ASCII
(Unicode code points 0x20...0x7E, plus a few control
characters.)
Any time a program handles text, the very first statement in
main should be:
std::locale::global( std::locale( "" ) );
If the program uses any of the standard stream objects, the code
should also imbue them with the global locale, before any
input or output.
To read and write unicode files (assuming you want to write unicode characters) you can try fopen_s
FILE *file;
if((fopen_s(&file, file_path, "w,ccs=UNICODE" )) == NULL)
{
fputws(your_wstring().c_str(), file);
}
One possible problem may be when you read the string back, because you set the length of the string to the number of bytes in the file and not the number of characters. This means that you attempt to read past the end of the file, and also that the string will contain trash at the end.
If you're dealing with text files, why not simply use the normal output and input operators << and >> or other textual functions like std::getline?
Later edit: this is for Windows (since no tag was present at the time of the answer)
You need to set the stream to a locale that supports those characters . Try something like this (for UTF8/UTF16):
std::wofstream myFile("out.txt"); // writing to this file
myFile.imbue(std::locale(myFile.getloc(), new std::codecvt_utf8_utf16<wchar_t>));
And when you read from that file you have to do the same thing:
std::wifstream myFile2("out.txt"); // reading from this file
myFile2.imbue(std::locale(myFile2.getloc(), new std::codecvt_utf8_utf16<wchar_t>));
Do not use wstring or wchar_t. On non-Windows platforms wchar_t is pretty much worthless these days.
Instead you should use UTF-8.
bool
write_file(
const char* path,
const std::string data
) {
try {
std::ofstream file(path, std::ios::out | std::ios::trunc | std::ios::binary);
file.exceptions(true);
file << data;
return true;
} catch (...) {
std::cout << "exception!\n";
return false;
}
}
// Read Method
std::string
read_file(
const char* filename
) {
std::ifstream fhandle(filename, std::ios::in | std::ios::binary);
if (fhandle) {
std::string contents;
fhandle.seekg(0, std::ios::end);
contents.resize(fhandle.tellg());
fhandle.seekg(0, std::ios::beg);
fhandle.read(&contents[0], contents.size());
return contents;
} else {
return "";
}
}
int main()
{
const char* file_path_1 = "./file_content_1.txt";
const char* file_path_2 = "./file_content_2.txt";
std::string data = "হ্যালো ওয়ার্ল্ড"; // linux and os x compilers use UTF-8 as the default execution encoding.
write_file(file_path_1, data);
std::string out = read_file(file_path_1);
std::wcout << "File Content: " << out << '\n';
write_file(file_path_2, out);
}

Reading and writing binary file

I'm trying to write code to read a binary file into a buffer, then write the buffer to another file. I have the following code, but the buffer only stores a couple of ASCII characters from the first line in the file and nothing else.
int length;
char * buffer;
ifstream is;
is.open ("C:\\Final.gif", ios::binary );
// get length of file:
is.seekg (0, ios::end);
length = is.tellg();
is.seekg (0, ios::beg);
// allocate memory:
buffer = new char [length];
// read data as a block:
is.read (buffer,length);
is.close();
FILE *pFile;
pFile = fopen ("C:\\myfile.gif", "w");
fwrite (buffer , 1 , sizeof(buffer) , pFile );
If you want to do this the C++ way, do it like this:
#include <fstream>
#include <iterator>
#include <algorithm>
int main()
{
std::ifstream input( "C:\\Final.gif", std::ios::binary );
std::ofstream output( "C:\\myfile.gif", std::ios::binary );
std::copy(
std::istreambuf_iterator<char>(input),
std::istreambuf_iterator<char>( ),
std::ostreambuf_iterator<char>(output));
}
If you need that data in a buffer to modify it or something, do this:
#include <fstream>
#include <iterator>
#include <vector>
int main()
{
std::ifstream input( "C:\\Final.gif", std::ios::binary );
// copies all data into buffer
std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(input), {});
}
Here is a short example, the C++ way using rdbuf. I got this from the web. I can't find my original source on this:
#include <fstream>
#include <iostream>
int main ()
{
std::ifstream f1 ("C:\\me.txt",std::fstream::binary);
std::ofstream f2 ("C:\\me2.doc",std::fstream::trunc|std::fstream::binary);
f2<<f1.rdbuf();
return 0;
}
sizeof(buffer) == sizeof(char*)
Use length instead.
Also, better to use fopen with "wb"....
sizeof(buffer) is the size of a pointer on your last line NOT the actual size of the buffer.
You need to use "length" that you already established instead
You should pass length into fwrite instead of sizeof(buffer).
Here is implementation of standard C++ 14 using vectors and tuples to Read and Write Text,Binary and Hex files.
Snippet code :
try {
if (file_type == BINARY_FILE) {
/*Open the stream in binary mode.*/
std::ifstream bin_file(file_name, std::ios::binary);
if (bin_file.good()) {
/*Read Binary data using streambuffer iterators.*/
std::vector<uint8_t> v_buf((std::istreambuf_iterator<char>(bin_file)), (std::istreambuf_iterator<char>()));
vec_buf = v_buf;
bin_file.close();
}
else {
throw std::exception();
}
}
else if (file_type == ASCII_FILE) {
/*Open the stream in default mode.*/
std::ifstream ascii_file(file_name);
string ascii_data;
if (ascii_file.good()) {
/*Read ASCII data using getline*/
while (getline(ascii_file, ascii_data))
str_buf += ascii_data + "\n";
ascii_file.close();
}
else {
throw std::exception();
}
}
else if (file_type == HEX_FILE) {
/*Open the stream in default mode.*/
std::ifstream hex_file(file_name);
if (hex_file.good()) {
/*Read Hex data using streambuffer iterators.*/
std::vector<char> h_buf((std::istreambuf_iterator<char>(hex_file)), (std::istreambuf_iterator<char>()));
string hex_str_buf(h_buf.begin(), h_buf.end());
hex_buf = hex_str_buf;
hex_file.close();
}
else {
throw std::exception();
}
}
}
Full Source code can be found here
There is a much simpler way. This does not care if it is binary or text file.
Use noskipws.
char buf[SZ];
ifstream f("file");
int i;
for(i=0; f >> noskipws >> buffer[i]; i++);
ofstream f2("writeto");
for(int j=0; j < i; j++) f2 << noskipws << buffer[j];
Or you can just use string instead of the buffer.
string s; char c;
ifstream f("image.jpg");
while(f >> noskipws >> c) s += c;
ofstream f2("copy.jpg");
f2 << s;
normally stream skips white space characters like space or new line, tab and all other control characters.
But noskipws makes all the characters transferred.
So this will not only copy a text file but also a binary file.
And stream uses buffer internally, I assume the speed won't be slow.
It can be done with simple commands in the following snippet.
Copies the whole file of any size. No size constraint!
Just use this. Tested And Working!!
#include<iostream>
#include<fstream>
using namespace std;
int main()
{
ifstream infile;
infile.open("source.pdf",ios::binary|ios::in);
ofstream outfile;
outfile.open("temppdf.pdf",ios::binary|ios::out);
int buffer[2];
while(infile.read((char *)&buffer,sizeof(buffer)))
{
outfile.write((char *)&buffer,sizeof(buffer));
}
infile.close();
outfile.close();
return 0;
}
Having a smaller buffer size would be helpful in copying tiny files. Even "char buffer[2]"
would do the job.