Store contents of text file in a char* array in C++ - c++

I have to read the contents of a file, and store them in a char* array. I have the following, but when I output my char* array I don't get the full output of the file I read in. Am I incorrectly calculating the file size of my output array?
Note: I must use POSIX calls to read the contents of the file.
#include "iostream"
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
using namespace std;
int main() {
const char* name = "test.txt";
int fd = open(name, O_RDONLY);
off_t length = lseek(fd, 0, SEEK_END);
cout << "file size: " << length << endl;
char* array = new char[length];
lseek(fd, 0, SEEK_SET); // resets position to 0
read(fd, array, sizeof(array)-1);
cout << array << "finished" << endl;
close(fd);
delete[] array;
return 0;
}
Contents of test.txt are This is a string of sample text
But this is my output when running:
file size: 34
This isfinished

Related

Using read() to store data into a char array

I'm working on a project where I need to read a binary file and then operate on the data(count how many times 3 appears). My approach was to use read() to store data into a char buffer. Then operate on the buffer. My biggest issue is using read() correctly, I don't believe it is storing any data into char buffer. char buffer remains empty after read() is called.
// Program reads how many times the integer 3 occurs in a binary file
#include <iostream>
#include <fstream> // needed to use files
using namespace std;
int main()
{
int count = 0;
char buffer[32];
int size = sizeof(buffer) / sizeof(buffer[0]);
// open file "example.bin"
fstream file("example.bin", ios::in | ios::ate | ios::binary);
if(!file)
{
cout << "Error opening file" << endl;
return 0;
}
cout << "opened file" << endl;
// reading the data into memory
file.read(reinterpret_cast<char *>(buffer), sizeof(buffer));
for(int i = 0; i < size; i++)
{
if (buffer[i] == '3')
count++;
}
cout << "There exists " << count << " threes in this file." << endl;
// close file
file.close();
return 0;
}

Write vector of unsigned char to binary file c++

I am reading binary file cmd.exe into unsigned chars array. Total bytes read into bytes_read are 153. I converted it to base64 string and then decode this string back (code from 2nd answer base64 decode snippet in c++) into vector<'BYTE>. Here BYTE is unsigned char.
decodedData.size() is also 153. But when I write this vector to file in binary mode to get my cmd.exe file again I get only 1 KB file. What thing I missed?
// Reading size of file
FILE * file = fopen("cmd.exe", "r+");
if (file == NULL) return 1;
fseek(file, 0, SEEK_END);
long int size = ftell(file);
fclose(file);
// Reading data to array of unsigned chars
file = fopen("cmd.exe", "r+");
unsigned char * myData = (unsigned char *)malloc(size);
int bytes_read = fread(myData, sizeof(unsigned char), size, file);
fclose(file);
std::string encodedData = base64_encode(&myData[0], bytes_read);
std::vector<BYTE> decodedData = base64_decode(encodedData);
////write data to file
ofstream outfile("cmd.exe", ios::out | ios::binary);
outfile.write((const char *)decodedData.data(), decodedData.size());
Update:
Thanks #chux for suggesting "r+" --> "rb+" Problem resolved.
You marked this as C++.
This is one C++ approach using fstream to read a binary file. To simplify for this example, I created a somewhat bigger m_buff than needed. From the comments, it sounds like your fopen("cmd.exe", "r+") was in error, so I'm only providing a C++ binary read.
Method tReader() a) opens a file in binary mode, b) reads the data into m_buff, and c) captures gCount for display.
It also demonstrates one possible use of chrono to measure duration.
#include <chrono>
// 'compressed' chrono access --------------vvvvvvv
typedef std::chrono::high_resolution_clock HRClk_t;
typedef HRClk_t::time_point Time_t;
typedef std::chrono::microseconds US_t;
using namespace std::chrono_literals; // suffixes 100ms, 2s, 30us
#include <iostream>
#include <fstream>
#include <cassert>
class T516_t
{
enum BuffConstraints : uint32_t {
Meg = (1024 * 1024),
END_BuffConstraints
};
char* m_buff;
int64_t m_gCount;
public:
T516_t()
: m_buff (nullptr)
, m_gCount (0)
{
m_buff = new char[Meg];
}
~T516_t() = default;
int exec()
{
tReader();
return(0);
}
private: // methods
void tReader()
{
std::string pfn = "/home/dmoen/.wine/drive_c/windows/system32/cmd.exe";
// open file in binary mode
std::ifstream sIn (pfn, std::ios_base::binary);
if (!sIn.is_open()) {
std::cerr << "UNREACHABLE: unable to open sIn " << pfn
<< " priviledges? media offline?";
return;
}
Time_t start_us = HRClk_t::now();
do
{
// perform read
sIn.read (m_buff, Meg);
// If the input sequence runs out of characters to extract (i.e., the
// end-of-file is reached) before n characters have been successfully
// read, buff contains all the characters read until that point, and
// both eofbit and failbit flags are set
m_gCount = sIn.gcount();
if(sIn.eof()) { break; } // exit when no more data
if(sIn.failbit ) {
std::cerr << "sIn.faileBit() set" << std::endl;
}
}while(1);
auto duration_us = std::chrono::duration_cast<US_t>(HRClk_t::now() - start_us);
sIn.close();
std::cout << "\n " << pfn
<< " " << m_gCount << " bytes"
<< " " << duration_us.count() << " us"
<< std::endl;
} // int64_t tReader()
}; // class T516_t
int main(int , char**)
{
Time_t start_us = HRClk_t::now();
int retVal = -1;
{
T516_t t516;
retVal = t516.exec();
}
auto duration_us = std::chrono::duration_cast<US_t>(HRClk_t::now() - start_us);
std::cout << " FINI " << duration_us.count() << " us" << std::endl;
return(retVal);
}
One typical output on my system looks like:
/home/dmoen/.wine/drive_c/windows/system32/cmd.exe 722260 bytes 1180 us
FINI 1417 us
Your results will vary.
Your ofstream use looks good (so did not replicate).

Reading Binary Files w/ ifstream

I'm trying to read in an .exe and write it back out. My code works with .txt files but for some reason it is breaking executables. What am I doing wrong?
I'm not sure if I am reading it wrong or writing it wrong..
#include <string>
#include <vector>
#include <iostream>
#include <filesystem>
#include <unordered_set>
#include <Windows.h>
unsigned char *ReadFileAsBytes(std::string filepath, DWORD &buffer_len)
{
std::ifstream ifs(filepath, std::ofstream::binary | std::ifstream::ate);
if (!ifs.is_open())
{
return(nullptr);
}
// Go To End
ifs.seekg(0, ifs.end);
// Get Position (Size)
buffer_len = static_cast<DWORD>(ifs.tellg());
// Go To Beginning
ifs.seekg(0, ifs.beg);
// Allocate New Char Buffer The Size Of File
PBYTE buffer = new BYTE[buffer_len];
ifs.read(reinterpret_cast<char*>(buffer), buffer_len);
ifs.close();
return buffer;
}
void WriteToFile(std::string argLocation, unsigned char *argContents, int argSize)
{
std::ofstream myfile;
myfile.open(argLocation);
myfile.write((const char *)argContents, argSize);
myfile.close();
}
int main()
{
// Config
static std::string szLocation = "C:\\Users\\Admin\\Desktop\\putty.exe";
static std::string szOutLoc = "C:\\Users\\Admin\\Desktop\\putty2.exe";
DWORD dwLen;
unsigned char *szBytesIn = ReadFileAsBytes(szLocation, dwLen);
std::cout << "Read In " << dwLen << " Bytes" << std::endl;
// Write To File
WriteToFile(szOutLoc, szBytesIn, dwLen);
system("pause");
}
You open input file in binary mode, but in this code
std::ofstream myfile;
myfile.open(argLocation);
you open output file without binary mode. And there is no reason to call open separately:
std::ofstream myfile( argLocation, std::ios::out | std::ios::binary | std::ios::trunc);

Size is always zero when reading DRM EDID file

I tried to read the EDID of my monitor connected to LVDS1. I use ArchLinux and C++/clang. My problem is: the file size always returns 0. I don't know if this is a programming problem or something OS specific, other files return a proper file size. Is it a special file? Is the symlink directory /sys/class/drm/card0-DP-1 the problem?
file: /sys/class/drm/card0-LVDS-1/edid
code:
#include <fstream>
#include <iostream>
using namespace std;
typedef unsigned char BYTE;
long
get_file_size(FILE *f)
{
long pos_cursor, pos_end;
pos_cursor = ftell(f);
fseek(f, 0, 2);
pos_end = ftell(f);
fseek(f, pos_cursor, 0);
return pos_end;
}
int
main()
{
const char *filepath = "/sys/class/drm/card0-LVDS-1/edid";
FILE *file = NULL;
if((file = fopen(filepath, "rb")) == NULL)
{
cout << "file could not be opened" << endl;
return 1;
}
else
cout << "file opened" << endl;
long filesize = get_file_size(file);
cout << "file size: " << filesize << endl;
fclose(file);
return 0;
}
output:
file opened
file size: 0
===
as suggested by MSalters, I tried stat for the file size. Also returns 0. I assume the code is correct, so it is somehow just not possible to access the file?
I also tried the symlink target path (/sys/devices/pci0000:00/0000:00:02.0/drm/card0/card0-LVDS-1/edid), just in case that was the problem - but still 0.
code:
#include <iostream>
#include <sys/stat.h>
using namespace std;
int
main()
{
const char *filepath = "/sys/class/drm/card0-LVDS-1/edid";
struct stat results;
if (stat(filepath, &results) == 0)
cout << results.st_size << endl;
else
cout << "error" << endl;
return 0;
}
output
0
===
I tried other files in the same directory (dpms edid enabled i2c-6 modes power status subsystem uevent). They all return a filesize of 4096 except edid.
I suspect that fseek(f, 0, 2); might mean fseek(f, 0, SEEK_CUR); which obviously doesn't do anything. You'd want SEEK_END which isn't portable, but then again /sys/ isn't either. (Of course, do #include <stdio.h>)
But considering it's already Linux-specific, why not use stat ?

fwrite fails on big data

Hey just try to compile an image in code and put it out as jpg again but fwrite returns 0 and img.jpg keeps empty :(
#include <stdio.h>
#include <string>
#include <iostream>
size_t count = 76830;//=length of data
const uint8_t data[] = {0xff,0xd8,0xff,0xe0,0x0,0x10,0x4a,0x46,0x49,0x46.....
0x0,0x7f,0xff,0xd9};
using namespace std;
//use this to saveToFile...
void saveToFile(const char * filename) {
FILE * file = fopen(filename, "rb");
if (file == NULL) {
std::cout << "error opening file" << std::endl;
return;
}
cout << endl << fwrite(data, sizeof(uint8_t), sizeof(data), file); //this line returns 0!!!
fclose(file);
}
int main () {
saveToFile("img.jpg");
}
fopen(filename, "rb");
This opens the file for reading, not writing. You want
fopen(filename, "wb");
// ^