C++ input and output files - c++

So im writing c++ program, that takes a integer from input file, multiply it with 2 and outputs it on output file. So the code is -
#include <stdio.h>
#include <iostream>
using namespace std;
int main() {
int n;
FILE * inFile;
FILE * outFile;
inFile = fopen ("reiz.in","r");
outFile = fopen ("reiz.out","r+");
fscanf (inFile, "%s", n);
int m = n * 2;
fprintf (outFile, "%n", n);
fclose (inFile);
fclose (outFile);
return 0;
}
But something is wrong. in reiz.in file there is number 2, after running program it should output 4 in reiz.out, but it just shows don't send error. What exactly is wrong with my script?
Best regards,
Y2oK
EDIT 1: Ok now it looks like this -
#include <stdio.h>
#include <iostream>
using namespace std;
int main() {
int n;
FILE * inFile;
FILE * outFile;
inFile = fopen ("reiz.in","r");
outFile = fopen ("reiz.out","r+");
fscanf (inFile, "%d", &n);
int m = n * 2;
fprintf (outFile, "%d", m);
fclose (inFile);
fclose (outFile);
return 0;
}
but still it gives same don't send error when running reiz.exe file, and it doesn't write anything on output file
I'm now a little bit confused, and don't know who to chose as best answer, so I will chose the one who got most "+1". But thanks to all!

This a C-program (apart from the using namespace std;). In C++ you should use streams and formatted I/O, like this:
#include <fstream>
int main() {
std::ifstream input_file("reiz.in");
int n;
input_file >> n; // read one integer
std::ostream output_file("reis.out");
output_file << n * 2 << std::endl; // calculate n * 2 and write the result
// to a file. std::endl adds a newline and
// flushes the buffer
return 0;
}

Pass the address of n to fscanf() (and it's an integer not a string):
fscanf (inFile, "%d", &n);
All that stuff is a bit long in the tooth, unless you are actually writing 'C'. Look at the iostream family of classes if you are writing 'C++'

There are multiple issues with your code:
#include <stdio.h>
This is a C include, not a C++ include. Instead, you should use:
#include <cstdio>
fscanf (inFile, "%s", n);
The format %s is for strings, of type char*. You want to read a decimal number, so use %d instead. Furthermore, you have to pass the address of the destination:
fscanf (inFile, "%d", &n);
fprintf (outFile, "%n", n);
The format %n is used to query the number of bytes written so far, and requires a pointer. Since you want to write a decimal number, use %d again:
fprintf (outFile, "%d", n);

There are two problems with fscanf. First, your format string is wrong -- you're taking a string, where you should be taking a (signed?) decimal. Second, you are passing n by-value, but you should be passing a pointer to n instead:
fscanf (inFile, "%d", &n);
You are also #includeing the now-deprecated <stdio.h> file. You should:
#include <cstdio>
Finally, you claim to be writing C++ code, but the code you actually wrote is decidedly not C++-ish, which is to say it is type-unsafe. I'd recommend you either go C++, or don't -- don't pussyfoot around.
Here is a more C++ way of doing what you're trying to do (you should add error-checking and writing to the output file):
#include <cstdio>
#include <iostream>
#include <fstream>
using namespace std;
int main() {
ifstream in("reiz.in", std::ios::in);
int n = 0;
in >> n;
return 0;
}

There are several issues which will prevent your code from working properly.
There is no need to open outfile as r+. You can just open it with mode w.
outFile = fopen ("reiz.out","w");
When you read from the file with fscanf, you are passing the integer n instead of the pointer to the integer n. fscanf is expecting to receive the location to write the integer it read. You are passing the integer itself (which will, in the best case, crash your program. Worst case, weird stuff will start happening).
fscanf (inFile, "%s", &n);
You are using %n when writing to outfile. This does not print the integer n but rather it reads the number of bytes written so far. You want to use %d instead.
fprintf (outFile, "%d", m);
Also, as a side-note, you seem to be using C instead of C++. In C++, you would usually use file stream objects, like ifstream and ofstream, to read from and write to files. You are using things like fopen which are decidedly more C-like.
This code should work better:
#include <stdio.h>
int main() {
int n;
FILE * inFile;
FILE * outFile;
inFile = fopen ("reiz.in","r");
outFile = fopen ("reiz.out","w");
fscanf (inFile, "%d", &n);
int m = n * 2;
fprintf (outFile, "%d\n", m);
fclose (inFile);
fclose (outFile);
return 0;
}

Go use iostream (Bjorns answer)
But I think
outFile = fopen ("reiz.out","r+");
should be
outFile = fopen ("reiz.out","w+");
Also
fscanf (inFile, "%d", n);
should be
fscanf (inFile, "%d", &n);
For ease of reference, a fully working (C) program:
#include <stdio.h>
int main() {
int n;
FILE * inFile;
FILE * outFile;
inFile = fopen ("reiz.in","r");
outFile = fopen ("reiz.out","w+");
fscanf (inFile, "%d", &n);
int m = n * 2;
fprintf (outFile, "%i", m);
fclose (inFile);
fclose (outFile);
return 0;
}

Related

C++ ofstream Binary Mode - Written file still looks like plain text

I have an assignment that wants plain text data to be read in from a file, and then outputted to a separate binary file. With that being said, I expect to see that the contents of the binary file not to be intelligible for human reading. However, when I open the binary file the contents are still appearing as plain text. I am setting the mode like this _file.open(OUTFILE, std::ios::binary). I can't seem to figure out what I'm missing. I've followed other examples with different methods of implementation, but there's obviously something I'm missing.
For the purpose of posting, I created a slimmed down test case to demonstrate what I'm attempting.
Thanks in advance, help is greatly appreciated!
Input File: test.txt
Hello World
main.cpp
#include <iostream>
#include <fstream>
using namespace std;
#define INFILE "test.txt"
#define OUTFILE "binary-output.dat"
int main(int argc, char* argv[]) {
char* text = nullptr;
int nbytes = 0;
// open text file
fstream input(INFILE, std::ios::in);
if (!input) {
throw "\n***Failed to open file " + string(INFILE) + " ***\n";
}
// copy from file into memory
input.seekg(0, std::ios::end);
nbytes = (int)input.tellg() + 1;
text = new char[nbytes];
input.seekg(ios::beg);
int i = 0;
input >> noskipws;
while (input.good()) {
input >> text[i++];
}
text[nbytes - 1] = '\0';
cout << "\n" << nbytes - 1 << " bytes copied from file " << INFILE << " into memory (null byte added)\n";
if (!text) {
throw "\n***No data stored***\n";
} else {
// open binary file for writing
ofstream _file;
_file.open(OUTFILE, std::ios::binary);
if (!_file.is_open()) {
throw "\n***Failed to open file***\n";
} else {
// write data into the binary file and close the file
for (size_t i = 0U; i <= strlen(text); ++i) {
_file << text[i];
}
_file.close();
}
}
}
As stated here, std::ios::binary isn't actually going to write binary for you. Basically, it's the same as std::ios::out except things like \n aren't converted to line breaks.
You can convert text to binary by using <bitset>, like this:
#include <iostream>
#include <vector>
#include <bitset>
int main() {
std::string str = "String in plain text";
std::vector<std::bitset<8>> binary; // A vector of binaries
for (unsigned long i = 0; i < str.length(); ++i) {
std::bitset<8> bs4(str[i]);
binary.push_back(bs4);
}
return 0;
}
And then write to your file.
In simplest terms, the flag std::ios::binary means:
Do not make any adjustments to my output to aid in readability or conformance to operating system standards. Write exactly what I send.
In your case, you are writing readable text and the file contains exactly what you sent.
You could also write bytes that are unintelligible when viewed as text. In that case, your file would be unintelligible when viewed as text.

I/O ascii codes to foreign characters

Using cout << "\n\u00f3\n << endl, I can print ó with newlines at the Unix command line. Once I start attempting to read files and print strings containing the characters, I see the literal output instead \n\u00f3\n.
I am not sure if this is because the file read techniques use character arrays or if there is some other nuance I do not know.
Any ideas?
Thanks!
const char *filename ="spanish_project_sample1.txt";
FILE *file = fopen(filename, "r");
int c;
char *data;
data = " ";
while ((c=fgetc(file)) != EOF) {
data = appendCharToCharArray(data, c);
}
printf("%s", data);
I looked at the JavaScript solutions to a similar problem (e.g. FromCharCode) and found this code online:
https://ideone.com/Udo3hN
#include <cstdarg>
#include <iostream>
using namespace std;
string FromCharCode ( int num, ... )
{
va_list arguments;
char ch;
string s;
va_start ( arguments, num );
for ( int x = 0; x < num; x++ )
{
ch = va_arg ( arguments, int );
s = s + ch;
}
va_end ( arguments );
return s;
}
int main()
{
cout<<FromCharCode (10,73,78,68,69,83,73,71,78,33,33) ;//<<endl;
return 0;
}
Specifically, it looks like reading in the characters is the issue because at runtime instead of reading '\n' as value 10 for example, the character array would actually record two ints [92,110].
Using a hardcoded string, the compiler parses the escaped characters as the desired values.
Any suggestions or solutions still welcome.
The C++ idiom for reading a file line by line is:
#include <fstream>
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
string line;
ifstream ifs;
ifs.open(argv[1]);
while(getline(ifs, line))
cout << line << endl;
}
Try that.
Your problem is probably one of interpretation though. If you have "\n\u00f3\n" in a file, that is what it reads and prints. If you have "ó" in the file, which is stored as \u00f3 in UTF-16, you will get what you want. The i/o routines don't do any conversion.
You also need to know if your file is in UTF-8 or UTF-16 so that you can read it properly.

How to read a .txt file using c-strings?

I'm working on a project for school and I need to read in text from a file.
Sounds easy peasy, except my professor put a restriction on the project: NO STRINGS
("No string data types or the string library are allowed.")
I've been getting around this problem by using char arrays; however, I'm not sure how to use char arrays to read in from a file.
This is an example from another website on how to read in a file with strings.
// reading a text file
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main () {
string line;
ifstream myfile ("example.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
cout << line << '\n';
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
The important line here is while ( getline (myfile,line) );
getline accepts an ifstream and a string (not char array).
Any help is appreciated!
Use cin.getline. Refer to this site for the format: cin.getline.
You can write something like this:
ifstream x("example.txt");
char arr[105];
while (x.getline(arr,100,'\n')){
cout << arr << '\n';
}
ifstream has a method named get() that reads the contents of the file into a char array. get() takes, as parameters, a pointer to the array, and the size of the array; then fills the array up to the given size, if possible.
After get() returns, use the gcount() method to determine how many characters have been read.
You can use then, and a simple logical loop, to repeatedly read the contents of the file, in size-chunks, into an array, and collect all the chunks read into a single array, or a std::vector.
You can use the int i = 0; while (scanf("%c", &str[i ++]) != EOF) to judge the end of text input. str is the char array include newline which you wanted, and i is the input size.
You can also use while(cin.getline()) to read per line every loop in C++ style:
istream& getline (char* s, streamsize n, char delim ); just like below:
const int SIZE = 100;
const int MSIZE = 100;
int main() {
freopen("in.txt", "r", stdin);
char str[SIZE][MSIZE];
int i = -1;
while (cin.getline(str[++ i], MSIZE)) {
printf("input string is [%s]\n", str[i]);
}
}

How can I convert a text file with numbers in it into a binary file?

So I have made a program that opens up a text file using ifstream. Now I want to make it so it outputs this file in binary. I have tried ofstream and using .write() but when I do the program crashes. I set it up correctly when using .write() as I have seen online but I haven't seen anyone do it with what I was working with. Anybody have a solution to this? Also, I do not know why 'InputFile' and 'OutputFile' are both highlighted blue like that.
#include <iostream>
#include <fstream>
#include <string>
#include <bitset>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int main(int argc, char* argv[])
{
if (argc < 2)
{
cout << "Error 1";
return 0;
}
else
{
int WIDTH, HEIGHT;
ifstream InputFile;
InputFile.open(argv[1], ios::in);
ofstream OutputFile;
OutputFile.open("OUTPUT.raw", ios::binary | ios::app);
cout << "Enter Width" << endl;
WIDTH = cin.get();
HEIGHT = WIDTH;
for (int x = 0; x < WIDTH; x++)
{
for (int y = 0; y < HEIGHT; y++)
{
OutputFile.write((char*)InputFile.get(), sizeof(InputFile));
}
}
}
//cout << bitset<8>(txt[i]);
return 0;
};
OutputFile.write((char*)InputFile.get(), sizeof(InputFile));
First, istream::get() extracts one characters from the stream and returns its value casted to an integer. The result is a temporary, which you cast to a pointer to char! It compiles, because the C-style cast basically tells the compiler "shoosh, I know what I'm doing!", but it will certainly do weird things at run-time. You need to get an adress of some object where the value you want to write is stored in, and cast that adress.
The second thing, sizeof(InputFile) returns size of ifstream class that manages the file stream. It's not in any way related to how many data is in the stream's buffer.
If you open a stream in text mode, then the correct way to extract data from it is to use extraction operator (>>). Then it's pretty simple:
std::ifstream in_file("numbers.txt");
std::ofstream out_file("numbers.bin", std::ios::binary);
int i;
while (in_file >> i)
out_file.write(reinterpret_cast<char*>(&i), sizeof(int));
The above snippet will work with an input text file like this: -4 21 1990 5425342 -3432 0 100.
You will have to parse your text file to get int for every string in file and just create a new file and write your binary data with fputc() or fwrite() functions.

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.