i am trying to write content of a very large char array to the hard disk.
I have the following array(actually the size of it is going to be very large)
I am using the array as a bit array and after inserting a specified number of bits into it I have to copy its content to another array and write this copy into hard disk. I then empty the content of the array by assigning it 0 for further use.
unsigned char bit_table_[ROWS][COLUMNS];
Use ofstream, copy and ostream_iterator to leverage the power of STL:
#include <algorithm>
#include <fstream>
#include <iterator>
#include <iostream>
#include <vector>
using namespace std;
int main() {
unsigned char bit_table_[20][40];
for (int i = 0 ; i != 20 ; i++)
for (int j = 0 ; j != 40 ; j++)
bit_table_[i][j] = i^j;
ofstream f("c:/temp/bit_table.bin", ios::binary | ios::out);
unsigned char *buf = &bit_table_[0][0];
copy(buf, buf+sizeof(bit_table_), ostream_iterator<unsigned char>(f, ""));
return 0;
}
You should open a file for writing, and then write the array to it:
FILE * f;
f = fopen(filepath, "wb"); // wb -write binary
if (f != NULL)
{
fwrite(my_arr, sizeof(my_arr), 1, f);
fclose(f);
}
else
{
//failed to create the file
}
References: fopen, fwrite, fclose
Use a file or a database...
a file is simple to create :
FILE * f;
int i,j;
f = fopen("bit_Table_File", "w");
for (i = 0 , i< ROWS , i++)
{
for (j = 0 , j < COLUMNS , j++)
{
fprintf(f, "%2x", bit_table_[i][j]);
}
}
to read the contents of the file, you can use fscanf starting from the beginning of the file :
FILE* f = fopen("myFile","r");
for (i = 0 , i< ROWS , i++)
{
for (j = 0 , j < COLUMNS , j++)
{
fscanf(f, "%2x", &(bit_table_[i][j]));
}
}
whereas you have to install a database (and number of tables needed) and use specific instructions to write to it.
You can Store the value of array in file
so you need
include the fstream header file and using std::ostream;
declare a variable of type ofstream
open the file
check for an open file error
use the file
close the file when access is no longer needed
#include <fstream>
using std::ofstream;
#include <cstdlib>
int main()
{
ofstream outdata;
int i; // loop index
int array[5] = {4, 3, 6, 7, 12};
outdata.open("example.dat"); // opens the file
if( !outdata ) { // file couldn't be opened
cerr << "Error: file could not be opened" << endl;
exit(1);
}
for (i=0; i<5; ++i)
outdata << array[i] << endl;
outdata.close();
return 0;
}
Related
I am trying to read a .ply file with c++ and save the geometric information in vectors (The border points are floats and the border triangles are int's. The code works under Linux but when I try to use it under Windows it doesn't behave as intended.
Here is a trimmed down version of the code:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
using namespace std;
string FilenamePLY;
int NumberBorderPoint = 1572866;
int BorderNumberTriangle = 3145728;
char numFloat;
char numInt;
int main(int argc, char** argv)
{
FilenamePLY = "file_test.ply";
ifstream fin(FilenamePLY.c_str());
for (int i = 0; i < NumberBorderPoint; i++){
fin.read(&numFloat, sizeof(float));
for (int j = 0; j < 3; j++) {
fin.read(&numFloat, sizeof(float));
}
}
cout << fin.gcount() << endl;
for (int i = 0; i<BorderNumberTriangle; i++){
fin.read(&numInt, sizeof(int));
for (int j = 0; j<3; j++) {
fin.read(&numInt, sizeof(int));
}
}
cout << fin.gcount() << endl;
return 0;
}
The code compiled and executed under Windows outputs:
0
0
Whereas under Linux the output is:
4
4
My feeling is that the read function doesn't get the correct values to separate the numbers in the binary files but sizeof(float) and sizeof(int) both have the same value under Windows and Linux (4).
Any ideas of where the problem lies ?
Thank you for your help,
Try to open the file for binary reading:
ifstream fin(FilenamePLY.c_str(), std::ios::binary );
Open the file in binary mode and verify you opened the file.
You are also currently reading data of sizeof(float) into a character - its going to overwrite other data at that point (numFloat, numInt)
I am new to C/C++ .I have 2 text files and need to combine two files contents
I executed like this g++ merge.cc -o merge and created two text files with content like this:
file1 : 1 3 5 7
file2 : 2 4 6 8
then excuted this command : ./merge 10 t1.txt t2.txt
Out came : 1 2 3 4 5 6 7 81 2 3 4 5 6 7 8
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
void combine(char s[], char t[], char result[]);
int main(int argc, char* argv[])
{
const int MAX = 20;
char inBuffer1[MAX];
char inBuffer2[MAX];
char outBuffer[MAX*2];
int max = atoi(argv[1]);
ifstream file1(argv[2]);
ifstream file2(argv[3]);
file1.getline(inBuffer1,max);
file2.getline(inBuffer2,max);
combine (inBuffer1, inBuffer2, outBuffer);
cout << outBuffer << endl;
}
void combine(char s[], char t[], char result[])
{
int i, j, k;
for (i = j = k = 0; s[i] && t[j]; k++)
{
if (s[i] <= t[j])
result[k] = s[i++];
else
result[k] = t[j++];
cout << result[k];
}
//tidy up
for (; s[i]; )
{
result[k] = s[i++];
cout << result[k++];
}
for (; t[j]; )
{
result[k] = t[j++];
cout << result[k++];
}
result[k] = 0;
}
Could you please anyone explain about this. I thave to sort files and reserve output using -c, -r commands
Thanks in advance
The c++ standard library has std::merge to do exactly what you seem to want here. Basically open the files, then do the merge from a couple of istream_iterators to an ostream_iterator.
Try the following C-program example (without combine function):
#include <stdio.h>
#include <stdlib.h>
// compare function to sort int values
int comparator(const void *p, const void *q)
{
int l = *(int*)p;
int r = *(int*)q;
return (l - r);
}
int main(int argc, char* argv[])
{
const int MAX = 20;
int buffer[MAX*2];
int cnt = 0; // numbers in buffer
// check arguments
if( argc < 3)
{
printf("Provide correct arguments: one number and two files with numbers\n");
return 1;
}
// reading from 2 files in series
FILE * f;
for(int i = 2; i <= 3; i++)
{
f = fopen(argv[i], "r");
if( f == NULL )
{
printf("File %s cannot be read!\n", argv[2]);
break;
}
while( !feof(f) && cnt < MAX*2 ) // while file is not finished and array is not full
{
if( fscanf(f, "%d", &buffer[cnt]) ) // read data
cnt++; // and if reading is successful count
}
fclose(f);
}
// sort the resulting array (instead of combine function)
qsort(buffer, cnt , sizeof(int), comparator);
// printing results
for( int i = 0; i < cnt; i++)
{
printf("%d ", buffer[i]);
}
}
This example is for cases when initial files can consist not ordered values, so all values from both files are read to memory and then sorted by standard function from stdlib.h (to use that qsort we need function comparator, read more in the references).
But for case when both input files are already arranged (sorted) program can be simpler, but you need open both files and compare values while reading to output the smallest value from two "current", and you do not need buffer array for that case (it is just a tip, try to write a program yourself).
EDIT:
It is C++ example with merge and sort from <algorithm>:
#include <iostream>
#include <fstream>
#include <algorithm>
#include <functional>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
int data; // buffer to read one value from file
ifstream file1(argv[1]);
ifstream file2(argv[2]);
vector<int> v1, v2; // vectors to store data
// reading initial data to vectors
while( !file1.eof() )
{
file1 >> data;
v1.push_back(data);
}
file1.close();
while( !file2.eof() )
{
file2 >> data;
v2.push_back(data);
}
file2.close();
// sorting (essential if files are not sorted)
sort(v1.begin(), v1.end(), less <int>());
sort(v2.begin(), v2.end(), less <int>());
// marging
vector<int> res(v1.size() + v2.size()); // vector to store result
merge(v1.begin(), v1.end(), v2.begin(), v2.end(), res.begin(), less <int>());
// printing result
for(vector<int>::iterator i = res.begin(); i != res.end(); i++)
{
cout << *i << " ";
}
}
NOTE: In this example you do not need to ask user about size of data sequence, so argv[1] is name of the first file, and argv[2] is name of the second one (add appropriate check by yourself).
The following C++ example shows usage of istream_iterator and ostream_iterator with merge method:
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
using namespace std;
int main(int argc, char* argv[])
{
// open input files
ifstream file1(argv[1]);
ifstream file2(argv[2]);
// link input streams with files
istream_iterator<int> it1(file1);
istream_iterator<int> it2(file2);
istream_iterator<int> eos; // end-of-stream iterator
// link output stream to standard output
ostream_iterator<int> oit (cout," "); // " " = usage of space as separator
// marging to output stream
merge(it1, eos, it2, eos, oit);
file1.close();
file2.close();
return 0;
}
Lets say I have a txt file list.txt
The txt file has list of integers ,
88
894
79
35
Now I am able to open the file and display the contents in it but not able to store it in an integer array.
int main()
{
ifstream fin;
fin.open("list.txt");
char ch;
int a[4],i=0;
while((!fin.eof())&&(i<4))
{
fin.get(ch);
a[i]=(int)ch;
cout<<a[i]<<"\n";
i++;
}
fin.close();
return 0;
}
Please help!!
You can use >> to read text-formatted values:
fin >> a[i]
You should check for the end of the file after trying to read, since that flag isn't set until a read fails. For example:
while (i < 4 && fin >> a[i]) {
++i;
}
Note that the bound needs to be the size of the array; yours is one larger, so you might overrun the array if there are too many values in the file.
Try the following
#include <iostream>
#include <fstream>
int main()
{
const size_t N = 4;
int a[N];
std::ifstream fin( "list.txt" );
size_t i = 0;
while ( i < N && fin >> a[i] ) i++;
while ( i != 0 ) std::cout << a[--i] << std::endl;
return 0;
}
I need to traverse a file in a vertical manner. If suppose the file contents are:
adg
beh
cfi
It should print the file as:
abc
def
ghi
The length for each line will be same(i.e. all lines will be of length 3 for above example). I have written a code but it doesn't traverse the file as required.
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int main()
{
fstream fs;
fs.open("asd.txt",ios::in);
string str;
char *ch = new char();
int lineLen = 0, k = 0;
if(getline(fs,str))
{
lineLen = str.length();
}
fs.seekg(0);
if(lineLen > 0)
{
for(int i = 0;i<lineLen;i++)
{
fs.seekg(i+k*lineLen);
while(fs.read(ch,1))
{
k++;
fs.seekg(i+k*lineLen);
cout<<*ch;
}
k = 0;
}
}
fs.close();
cin.ignore();
}
I am a bit new to file handling and couldn't find the mistake. Also, is there a better approach for this to be followed?
Pretty much your way with some little tweaks
//lines = no. of lines in file
fs.seekg(0, fs.beg);
fs.clear();
if(lineLen > 0)
{
for(int k = 0; k < lineLen; k++) {
for(int i = 0;i<lines;i++){
fs.seekg(k+i * (lineLen + 2), fs.beg); //use lines + 2
if(fs.read (ch,1));
cout << *ch;
}
cout << endl;
}
Untested pseudo-code that may give you some ideas. Basically, load the whole file into a 2d vector of characters for easy access. It will use more memory than reading directly from the file but this won't matter unless the file is very big.
vector<vector<char>> filemap;
string line;
while (getline(filestream, line))
{
filemap.push_back(vector<char>(line.begin(), line.end()));
}
for (int x = 0; x < XSIZE; x++)
{
for (int y = 0; y < YSIZE; y++)
{
filestream << filemap[y][x]; // note x/y are opposite way round in 2d vectors
}
filestream << '\n';
}
You might find this task much simpler if you were to use mmap(2). There may be a C++ equivalent or wrapper, but I'm afraid I'm not much of an expert on that front. Hopefully someone will come along with a better answer if that's the case.
Here's a quick C (not ++) example. I'll see if I can google around and C++ify it some more:
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
int main(void)
{
int fd = open("input", O_RDONLY);
struct stat s;
fstat(fd, &s);
// map the file as one big string
char *c = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0);
// calculate sizes
int columns = strchr(c, '\n') - c; // first newline delimits a row
int stride = columns + 1; // count the newline!
int rows = s.st_size / stride; // all rows are the same length
for (int x = 0; x < columns; x++)
{
for (int y = 0; y < rows; y++)
{
putchar(c[y*stride + x]);
}
putchar('\n');
}
munmap(c, s.st_size);
close(fd);
return 0;
}
Edit: A quick search around didn't turn up a much better way to handle this in C++ as far as I could tell. I mean, I can add a typecast on the mmap line and change the putchar calls to std::cout, but that doesn't really seem like it makes any difference.
Instead of trying to seek() repeatedly in the source file it is much easier and faster to simply read in the whole source file then generate output from the in-memory contents.
This sounds an awful like like a class assignment, so I won't simply write the answer for you. However this should point you in the right way -- Some PseodoCode is included
To avoid pain, it should presumably be safe to assume some upper bound on line length and max lines, i.e.,
const int MaxLines = 100;
const int MaxLength = 80;
int lineno, linelength;
// array of char pointers for each line
char *lines[] = (*lines[])malloc(Maxlines * sizeof(char*));
// ReadLoop
lineno = 0;
while (not eof)
{
getline(buffer);
if (++lineno++ == 1)
{
linelength = strlen(buffer);
}
else
{
if (linelength != strlen(buffer))
{
cout "Line # " << lineno << " does not match the expected length";
exit();
}
}
lines[lineno] = malloc(strlen(buffer)+1));
strcpy(lines[lineno], buffer);
}
int cc, linecnt = lineno;
// now all data in memory, output "vertical data"
for (cc = 0; cc < linelength; ++cc)
{
for (lineno=0; lineno<<linelength; ++lineno)
{
cout << lines[xx][yy]; // xx && yy left you to figure out
}
cout "\n";
}
Provided that your file is not enormous, there's no reason not to just slurp the whole thing into memory. There may be a more idiomatic way to do this in C++, but the following works:
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
int main(int argc, char *argv[])
{
std::fstream infile("foo.txt");
std::vector<std::string> lines;
std::string line;
while(std::getline(infile,line)) {
lines.push_back(line);
}
int m=lines.size();
int n=lines[0].length();
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
std::cout << lines[j].at(i);
}
std::cout << std::endl;
}
return 0;
}
Problems arise when all the lines in the file are not the same length, of course.
And now, a version that “doesn't use any extra memory” (of course, it does, but not much):
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <algorithm>
int main(int argc, char *argv[])
{
std::fstream infile("foo.txt");
std::vector<std::string> lines;
std::string line;
std::getline(infile, line);
int n = line.length();
int m = 1+std::count(std::istreambuf_iterator<char>(infile),
std::istreambuf_iterator<char>(), '\n');
infile.clear();
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
infile.seekg(j*m+i);
std::cout << char(infile.peek());
}
std::cout << std::endl;
}
return 0;
}
I'm trying to open a wav file, read it, convert the buffer to an integer array, then convert it back and write it.
int main(){
ifstream file ("C:\\Documents\\ParadigmE3-shortened.wav",std::ios_base::out | std::ios_base::binary);
char * header = new char[50000044];
file.read(header, 50000044);
cout << header[0] << endl;
unsigned int * header_int = new unsigned int[50000044];
for(unsigned int i = 0; i < sizeof(header); i++){
header_int[i] = header[i];
}
char * writefile = new char[50000044];
for(unsigned int i = 0; i < sizeof(header); i++){
itoa(header_int[i], &writefile[i], 10);
}
cout << writefile[0] << endl;
ofstream newfile ("C:\\Documents\\ParadigmE3-modified.wav", std::ios_base::out | std::ios_base::binary);
newfile.write(writefile, 50000044);
}
Currently, this prints:
R
8
Indicating that it changed the data in the process of converting it. How would I get this to work properly?
After some suggestions, and learning I can perform calculations on char variables, I reformulated the code, and now it is:
int main(){
// Create file variable with file
ifstream file ("C:\\Documents\\ParadigmE3-shortened.wav",std::ios_base::out | std::ios_base::binary);
// Read the first 15040512 bytes to char array pointer, called header
char * header = new char[15040512];
file.read(header, 15040512);
// Copy contents of header to writefile, after the 44'th byte, multiply the value by 2
char * writefile = new char[15040512];
for(int i = 0; i < sizeof(header); i++){
if(i<44) writefile[i] = header[i];
if(i>=44) writefile[i] = 2 * header[i];
}
// Copy the contents of writefile, but at the 44th byte, divide it by 2, returning it to its original value
for(int i = 0; i < sizeof(header); i++){
if(i<44) writefile[i] = writefile[i];
if(i>=44) writefile[i] = .5 * writefile[i];
}
// Create file to write to
ofstream newfile ("C:\\Documents\\ParadigmE3-modified.wav", std::ios_base::out | std::ios_base::binary);
// Write writefile to file
newfile.write(writefile, 15040512);
}
However, upon playing (in Windows Media Player), it does not play, so it is clearly not the original file, as I was going for.
I figured it out. A couple things I learned were that you can perform calculations on 8-bit char variables (with a max value of 255 unsigned), so I didn't need to change it to an int array, however, I did because it gave me more headroom to work with (without worrying about clipping the values at 255).
I have included the entire program (with the header include list), as I also think this is a common question, and this by far is the simplest way I've seen to do it (the other ways I couldn't figure out -- they were much more complicated than this to do the same thing).
It reads the wav file, then it performs an operation on the data portion (beginning at the 45'th byte), then it does the reverse, and writes the file, which is a copy of the original.
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <fstream>
#include <string>
#include <bitset>
#include <string.h>
using namespace std;
int main(){
ifstream file ("C:\\Documents\\ParadigmE3-shortened.wav",std::ios_base::out | std::ios_base::binary);
char * header = new char[15040512];
file.read(header, 15040512);
int * writefile = new int[15040512];
for(int i = 0; i < 15040512; i++){
if(i<44) writefile[i] = header[i];
if(i>=44) writefile[i] = 2 * header[i];
}
for(int i = 0; i < 15040512; i++){
if(i<44) header[i] = writefile[i];
if(i>=44) header[i] = .5 * writefile[i];
}
ofstream newfile ("C:\\Documents\\ParadigmE3-modified.wav", std::ios_base::out | std::ios_base::binary);
newfile.write(header, 15040512);
}