C++ Get All Bytes of a File in to a Char Array

C++ Get all bytes of a file in to a char array?

Note: Start with Remy Lebeau's answer. For general file reading, this answer covers the hard way to do the job; it better matched the specific needs of this specific asker, but won't necessarily meet your needs as well as the std::vector and std::istreambuf_iterator approach Remy outlines.


Most of the time they are right about getline, but when you want to grab the file as a stream of bytes, you want ifstream::read().

//open file
std::ifstream infile("C:\\MyFile.csv");

//get length of file
infile.seekg(0, std::ios::end);
size_t length = infile.tellg();
infile.seekg(0, std::ios::beg);

// don't overflow the buffer!
if (length > sizeof (buffer))
{
length = sizeof (buffer);
}

//read file
infile.read(buffer, length);

Docs for ifstream::seekg()

Docs for ifstream::tellg()

NOTE: seekg() and tellg() to get the size of the file falls into the category of "usually works". This is not guaranteed. tellg() only promises a number that can be used to return to a particular point. That said...

Note: The file was not opened in binary mode. There can be some behind-the-scenes character translations, for example the Windows newline of \r\n being converted to the \n used by C++. length can be greater than the number of characters ultimately placed in buffer.

2019 rethink

size_t chars_read;
//read file
if (!(infile.read(buffer, sizeof(buffer)))) // read up to the size of the buffer
{
if (!infile.eof()) // end of file is an expected condition here and not worth
// clearing. What else are you going to read?
{
// something went wrong while reading. Find out what and handle.
}
}
chars_read = infile.gcount(); // get amount of characters really read.

If you're looping on buffered reads until you consume the whole file, you'll want some extra smarts to catch that.

If you want to read the whole file in one shot, and can afford to use resizable buffers, take the advice in Remy Lebeau's answer.

Reading from memory and getting in char array.. What if a char in that contains 1 byte that suppose to be a 1 byte length and length is a number

But in C number is int or long.

char is an integral type which can be used to represent numbers, the same as short, int or long.

It has a maximum value of CHAR_MAX.

One problem is that the signedness of char is implementation-defined. When in doubt, be explicit with signed char (SCHAR_MAX) or unsigned char (UCHAR_MAX).

Alternatively, use fixed width integer types to make it easier to reason about the byte width of the data you are working with.

The fields in the EPS table are denoted as being of size BYTE, WORD, and DWORD. These can be represented by uint8_t, uint16_t, and uint32_t respectively, as you almost certainly want unsigned integers.


This code

char x1[3];
memcpy(x1,&mem[4],2);
x1[2]='\0';
long v=strtol(x1,'\0',16);

printf("max size %lx\n",v);

that attempts to parse the Maximum Structure Size as if it were a number represented by two characters is incorrect. The Maximum Structure Size is a 16-bit integer.

mem=mem+length; does not make much sense, as this would place you in memory beyond the table. I am not sure what the two printf calls that follow are trying to print.

Additionally, your example includes some errant code (unused variables: i, y, j).

Everything else is more-or-less correct, if messy.


Below is a simple example that seemingly works on my machine, using the smbios_entry_point table file. You should be able to use it as reference to adjust your program accordingly.

$ uname -rmo
5.14.21-210.current x86_64 GNU/Linux
#include <fcntl.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define EPS_SIZE 31
#define TARGET_FILE "/sys/firmware/dmi/tables/smbios_entry_point"

void print_buffer(uint8_t *eps) {
printf("Anchor string: %c%c%c%c\n", eps[0], eps[1], eps[2], eps[3]);
printf("Checksum: %02Xh\n", eps[4]);
printf("Entry point length: %02Xh\n", eps[5]);
printf("Major version: %02Xh\n", eps[6]);
printf("Minor version: %02Xh\n", eps[7]);

uint16_t mss;
memcpy(&mss, eps + 8, sizeof mss);
printf("Maximum structure size: %" PRIu16 " bytes\n", mss);

printf("Entry point revision: %02Xh\n", eps[10]);
printf("Formatted area: %02Xh %02Xh %02Xh %02Xh %02Xh\n",
eps[11], eps[12], eps[13], eps[14], eps[15]);
printf("Intermediate anchor string: %c%c%c%c%c\n",
eps[16], eps[17], eps[18], eps[19], eps[20]);
printf("Intermediate checksum: %02Xh\n", eps[21]);

uint16_t stl;
memcpy(&stl, eps + 22, sizeof stl);
printf("Structure table length: %" PRIu16 " bytes \n", stl);

uint32_t sta;
memcpy(&sta, eps + 24, sizeof sta);
printf("Structure table address: 0x%08x\n", sta);

uint16_t nsmbs;
memcpy(&nsmbs, eps + 28, sizeof nsmbs);
printf("Number of SMBIOS structures: %" PRIu16 "\n", nsmbs);

printf("SMBIOS BCD revision: %02Xh %02Xh\n",
eps[30] >> 4, eps[30] & 0x0f);
}

int main(void) {
uint8_t buf[EPS_SIZE];
int fd = open(TARGET_FILE, O_RDONLY);

read(fd, buf, sizeof buf);
close(fd);

print_buffer(buf);
}

stdout:

Anchor string: _SM_
Checksum: C2h
Entry point length: 1Fh
Major version: 02h
Minor version: 07h
Maximum structure size: 184 bytes
Entry point revision: 00h
Formatted area: 00h 00h 00h 00h 00h
Intermediate anchor string: _DMI_
Intermediate checksum: DCh
Structure table length: 2229 bytes
Structure table address: 0x000ed490
Number of SMBIOS structures: 54
SMBIOS BCD revision: 02h 07h

You may also be interested in dmidecode and its source code.

Copying all file contents into a char array with fread

There may be a problem in the part of your code you didn't show.

This works:

#include <stdio.h>
#include <stdlib.h>

void main()
{
FILE *fp;

if (fopen_s(&fp, "somepdfile.pdf", "rb"))
{
printf("Failed to open file\n");
exit(1);
}

fseek(fp, 0, SEEK_END);
int size = ftell(fp);
rewind(fp);

char *buffer = (char*)malloc(sizeof(char)*size);
if (!buffer)
{
printf("Failed to malloc\n");
exit(1);
}

int charsTransferred = fread(buffer, 1, size, fp);
printf("charsTransferred = %d, size = %d\n", charsTransferred, size);

fclose(fp);
free(buffer);
}

How to read 16 bytes from a file at a time and store them into an array

How to read 16 bytes from a file at a time and store them into an array (?)

Code is doing that part just fine.

Assuming it is a string, would the code I have work? Because I am getting a stack buffer overflow error when I run it. For example I am reading from a text file containing 'AAAABBBBCCCCDDDDE', and the password is 'passwordpassword'

The assumption is incorrect.

Consider why code is plaintext[] size 17, yet never assigned plaintext[16] and only reading 16. Code is not reading 'AAAABBBBCCCCDDDDE', but only 'AAAABBBBCCCCDDDD' and the last (17th) character of plaintext[] is never assigned.

Try char plaintext[17]; = { 0 }; to initialize the array. Then character plaintext[16] will be a null character and after a successful fread(plaintext, 16, 1, input_stream), plainttext[] will be a string suitable for shift_encrypt(plaintext, password).

How can bytes in char array represent integers?

I have char array that I read from binary file (like ext2 formatted filesystem image file).

Open the file in binary mode

const char *file_name = ...;
FILE *infile = fopen(file_name, "rb"); // b is for binary
if (infile == NULL) {
fprintf(stderr, "Unable to open file <%s>.\n", file_name);
exit(1);
}

I need to read integer starting at offset byte 1024 ...

long offset = 1024; 
if (fseek(infile, offset, SEEK_SET)) {
fprintf(stderr, "Unable to seek to %ld.\n", offset);
exit(1);
}

So I believe can be represented in integer size of 4 byte on my system

Rather than use int, which may differ from 4-bytes, consider int32_t from <stdint.h>.

int32_t data4;
if (fread(&data4, sizeof data4, 1, infile) != 1) {
fprintf(stderr, "Unable to read data.\n");
exit(1);
}

Account for Endian.

As file data is little-endian, convert to native endian. See #include <endian.h>.

data4 = le32toh(data4);

Clean up when done

// Use data4

fclose(infile);


believe I need to use strtol like

No. strtol() examines a string and returns a long. File data is binary and not a string.

Reading the whole text file into a char array in C

FILE *fp;
long lSize;
char *buffer;

fp = fopen ( "blah.txt" , "rb" );
if( !fp ) perror("blah.txt"),exit(1);

fseek( fp , 0L , SEEK_END);
lSize = ftell( fp );
rewind( fp );

/* allocate memory for entire content */
buffer = calloc( 1, lSize+1 );
if( !buffer ) fclose(fp),fputs("memory alloc fails",stderr),exit(1);

/* copy the file into the buffer */
if( 1!=fread( buffer , lSize, 1 , fp) )
fclose(fp),free(buffer),fputs("entire read fails",stderr),exit(1);

/* do your work here, buffer is a string contains the whole text */

fclose(fp);
free(buffer);


Related Topics



Leave a reply



Submit