I am trying to read a binary file consisting of signed 16 bit integers and there are exactly 51840000 of them. The code in C that accomplishes this looks like this:
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
int main()
{
int16_t *arr = malloc(51840000*sizeof(int16_t));
FILE *fp;
fp = fopen("LDEM_45N_400M.IMG", "rb");
if(fp == NULL)
{
printf("Error opening file\n");
exit(1);
}
printf("Testing fread() function: \n\n");
fread(arr, sizeof(*arr), 51840000, fp);
fclose(fp);
printf("%d \n", arr[51840000-2]);
free(arr);
return 0;
}
How would i read such a file in Fortran? IO in Fortran has always been very mysterious to me.
Use access="stream" and you can read it the same way. Declare your integers as integer(int16) and use the iso_fortran_env module.
use iso_fortran_env
integer :: ierr, n = 51840000
integer(int16) :: arr(n)
open(newunit=iu,file="LDEM_45N_400M.IMG", access="stream", status="old", action="read",iostat=ierr)
if (ierr/=0) stop "Error opening the file."
read(iu, iostat=ierr) arr
if (ierr/=0) stop "Error reading the array."
close(iu)
Related
I am trying to read a file from my .cpp file. I am using C libraries, so do not confuse on that.
So the problem is as clear as what I said in the title. fgets method can read the first line but when it comes to the second line, it cannot read neither the second line nor the rest of the file (since it exits when a problem occurs).
You can find the associated part of code:
void read_input()
{
int i = 0, N = 5;
char str[STR_SIZE], line[STR_SIZE];
FILE *fp;
fp = fopen("out", "r");
if (!fp)
{
fprintf(stderr, "error: file could not be opened\n");
exit(1);
}
for (i = 0; i<2; i++)
{
if (fgets(str, STR_SIZE, fp) == NULL)
{
fprintf(stderr, "error: failed at file reading\n");
exit(1);
}
if (feof(fp))
{
fprintf(stderr, "error: not enough lines in file\n");
exit(1);
}
if ((sscanf(str, "%s", line) != 1) )
{
fprintf(stderr, "error: invalid file format\n");
exit(1);
}
printf("%d\t%s\n", i, line);
fclose(fp);
}
}
I believe, the problem is there, because you've used fclose(fp); inside the loop. So, after the very first iteration, the fp is passed to fclose() and for any recurring use of fp in any further iteration will invoke undefined behavior as the fp is not valid anymore.
Solution: Move the fclose(fp); outside the loop.
You are closing the file in the loop! Put the fclose function outside of the loop.
for (i = 0; i<2; i++)
{
....
printf("%d\t%s\n", i, line);
fclose(fp); // <-- here, move out of the loop.
}
i'm new in C++ (and file input output), I learned how to use fprint to print something from a .txt in a formatted style, but how do I search for a certain value and save that value in a local variable? below is the code for save:
void savestate(state a){ //state is a struct with data I need such as position etc
FILE * save;
int data[]= { a.level, a.goalX, a.goalX, a.monX, a.monY };
save = fopen("game.txt", "wb"); // << might have to use suggestion C
fwrite(data, sizeof(int), sizeof(data), save); // is this actually the correct way to do it?
fclose(save);
}
as for load, I'm stuck with this:
void loadstate(){
FILE* save;
save = fopen("game.txt", "rb");
if(save== NULL) perror("no savegame data");
else{
// don't even know what function I should use
}
and by the way, after I activate the save function, the game.txt is not in a quite readable format. I can open in in my notepad, but it shows something like ÌÌÌÌÌÌÌÌøäÁ_ÌÌÌÌúƒ which makes no sense. any idea? :D
Use text file for this purpose, not a binary file. The saveData function
will create the data.txt file and then the function loadData reads the data from the file. I you want some more explanation leave a comment below.
#include <stdio.h>
#include <stdlib.h>
void saveData() {
FILE* f = fopen("data.txt", "w");
if(f == NULL) {
printf("cant save data");
return;
}
//write some data (as integer) to file
fprintf(f, "%d %d %d\n", 12, 45, 33);
fprintf(f, "%d %d %d\n", 1, 2, 3);
fprintf(f, "%d %d %d\n", 9, 8, 7);
fclose(f);
}
void loadData() {
int data1, data2, data3;
FILE* f = fopen("data.txt", "r");
if(f == NULL) {
printf("cant open file");
return;
}
//load data from file, fscanf return the number of read data
//so if we reach the end of file (EOF) it return 0 and we end
while(fscanf(f, "%d %d %d", &data1, &data2, &data3) == 3) {
printf("data1 = %d data2 = %d data3 = %d\n", data1, data2, data3);
}
fclose(f);
}
int main() {
saveData();
loadData();
return 0;
}
example of writing to a file:
#include<fstream>
#include<iostream>
#include<string>
using namespace std;
int main(){
int i = 78;
string word = "AWord";
ofstream fout("AFile", ios_base::out | ios_base::binary | ios_base::trunc);
fout << i;
fout << endl;
fout << word;
fout.close();
return 0
}
example of reading from a file :
#include<fstream>
#include<iostream>
#include<string>
using namespace std;
int main(){
int ix;
string wordx;
ifstream fin("AFile", ios_base::in | ios_base::binary);
fin >> ix;
while(fin.get() != '\n'){
fin.get();
}
fin >> wordx;
fin.close();
return 0
}
I need to read each line in the "test.txt" file using fscanf and print to new files using fprintf. If the read line is an integer, it is written to the integer file.
Float to the float file and string to string file respectively. However, when i try to compile it and run it, nothing happens and it goes to infinite loop.
Here is my code
#include <iostream>
#include <stdio.h>
using namespace std;
void writeFloat(){
FILE *file;
FILE *file2;
float value;
file = fopen("test.txt", "r");
file2 = fopen("float.out.txt", "w");
while(!feof(file)){
fscanf(file, "%f", &value);
fprintf(file2,"%f", value);
}
fclose(file);
fclose(file2);
}
void writeInteger(){
FILE *file;
FILE *file2;
int value;
file = fopen("test.txt", "r");
file2 = fopen("int.out.txt", "w");
while(!feof(file)){
fscanf(file, "%d", &value);
fprintf(file2, "%d", value);
}
fclose(file);
fclose(file);
}
void writeString(){
FILE *file;
FILE *file2;
char value;
file = fopen("test.txt", "r");
file2 = fopen("string.out.txt", "w");
while(!feof(file)){
fscanf(file, "%s", &value);
cout<<value<<endl;
fprintf(file2, "%s", value);
}
fclose(file);
fclose(file2);
}
int main(){
writeFloat();
writeInteger();
writeString();
return(0);
}
The test.txt file contains the values:
100
1.6E-10
hey nice to meet you.
43
56
4.5E-09
what is going on?
I don't know what wrong with my code. Please help me to achieve my requirement.
feof() is never true because fscanf in writefloat() refuses to read the first letter of "hey": It's not part of a legal number. scanf then returns with 0 ("no item could be read"). That is not EOF yet, though. But you should do something about it ;-).
Besides you must check for eof after you try to read something, before you try to use it. Not before the first failed read will the eof flag be turned on, but those variables will not be assigned.
I think, adopting a different strategy might be more appropriate for your needs.
Just have one function that reads the contents of the file line by line. It checks whether the line contains an integer or a floating point number. It line does not contain any numbers, the line is written out to "string.out.txt". If the number is an integer, it is written out to "int.out.txt". If the number is a floating point number, it is written out to "float.out.txt".
With this strategy, you have to read the contents of the input file only once and process the contents of the file only once.
It also simplifies the reading of the data and checking when you have reached EOF.
#include <stdio.h>
void writeData()
{
FILE *file1 = NULL;
FILE *file2 = NULL;
FILE *file3 = NULL;
FILE *file4 = NULL;
char value;
double realNum = 0.0;
int intNum = 0;
int n = 0;
char line[256];
file1 = fopen("test.txt", "r");
file2 = fopen("string.out.txt", "w");
file3 = fopen("int.out.txt", "w");
file4 = fopen("float.out.txt", "w");
while ( fgets(line, 255, file1) != NULL )
{
// Each line can be plain old text, a floating point number, or an
// integer.
// If the line does not contain a number, assume it is a float.
// Try to read a real number.
n = sscanf(line, "%lf", &realNum);
if ( n == 0 )
{
// The line does not have a number.
// Write the line to the text file.
fputs(line, file2);
}
else
{
// We have a real number.
// Could it be just an integer?
// Read the integer.
sscanf(line, "%d", &intNum);
// How do we decide whether the number is a real number or an
// integer?
// Is 1.0 a real number or an integer?
// Assume for now it is an integer.
if ( realNum == intNum )
{
// We have an integer.
fprintf(file3, "%d\n", intNum);
}
else
{
// We have a real number.
fprintf(file4, "%lG\n", realNum);
}
}
}
fclose(file4);
fclose(file3);
fclose(file2);
fclose(file1);
}
int main()
{
writeData();
return(0);
}
That is not the common way to open and close a file in C++. It looks like a c program. Try using functions from fstream and iostream libraries. See http://www.tutorialspoint.com/cplusplus/cpp_files_streams.htm.
I am trying to read a file of over 1GB (which has 1,157,421,364 bytes), it gives memory error when using fread() function, but works well when I use fgets() function.
Note: I have intermixed C and C++..
Can someone help me to overcome this memory error, am I doing something wrong?
Thanks in advance...
Error is "Memory Error"
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cerrno>
#include <cstring>
void read_file2(FILE* readFilePtr){
long file_size;
fseek(readFilePtr, 0L, SEEK_END);
file_size = ftell(readFilePtr);
rewind(readFilePtr);
char *buffer;
buffer = (char*) malloc (sizeof(char)*file_size);
if (buffer == NULL) {
fputs("Memory Error", stderr);
exit(2);
}
long lines = 0;
if (fread(buffer, 1, file_size, readFilePtr) != file_size){
fputs("Reading Error", stderr);
exit(1);
}
char *p = buffer;
while (p = (char*) memchr(p, '\n', (buffer + file_size) - p)){
++p;
++lines;
}
printf("Num of lines %ld\n", lines);
free(buffer);
}
int main(int argc, char** argv){
clock_t begin_time, end_time;
float time_consumed;
begin_time = clock();
FILE* inputFilePtr = fopen(argv[1], "rb");
if(inputFilePtr == NULL){
printf("Error Opening %s: %s (%u)\n", argv[1], strerror(errno), errno);
return 1;
}
read_file2(inputFilePtr);
end_time = clock();
time_consumed = ((float)end_time - (float)begin_time)/CLOCKS_PER_SEC;
printf("Time consumed is -- %f\n", time_consumed);
return 0;
}
You can read the file in chunks, instead of reading it as a whole, reading all of the file to one allocated buffer means a huge memory allocation of your application, do you really want that?. That's being said assuming you don't need to process it all in once (which is true in most cases).
You usually don't read big files in one go like that. You use something called buffered reads. Essentially you continuously call fread in a loop until there's nothing left to read.
Is there a function for FILE (fopen?) that allows me to just read one int from a binary file?
So far I'm trying this, but I'm getting some kind of error I can't see cause the program just crashes without telling me.
void opentest()
{
FILE *fp = fopen("dqmapt.mp", "r");
int i = 0;
int j = 0;
int k = 0;
int * buffer;
if (fp)
{
buffer = (int *) (sizeof(int));
i = (int) fread(buffer,1, (sizeof(int)), fp);
fscanf(fp, "%d", &j);
fclose(fp);
}
printf("%d\n", i);
printf("%d\n", j);
}
Now that you have changed your question, let me ask one. What is the format of the file you are trying to read?
For a binary file there are some changes required how you open the file:
/* C way */
FILE *fp = fopen("text.bin", "rb"); /* note the b; this is a compound mode */
/* C++ way */
std::ifstream ifs("test.txt", ios::in | ios::binary);
Reading in the contents is easy. But remember, your file has 2 integers at the begining -- width, height which determine how many more to read i.e. another width * height number of integers. So, your best bet is to read the first two integers first. You will need to use two buffers -- one for the width and height and then depending on their value another one to read the rest of the file. So, lets read in the first two integers:
char buf[ 2 * sizeof(int) ]; /* will store width and height */
Read in the two integers:
/* C way */
fread(buf, sizeof(int), 2, fp); /* the syntax changes, FILE pointer is last */
/* C++ way*/
ifs.read(buf, sizeof buf);
Now, the tricky part. You have to convert the stuff to double. This again depends on your system endianness -- whether a simple assignment works or whether a byte swapping is necessary. As another poster has pointed out WriteInt() writes integers in big-endian format. Figure out what system you are on. And then you can proceed further.
FILE is a C datastructure. It is included in C++ for C compatibility. You can do this:
/* The C way */
#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE *fp = fopen("test.txt", "r");
int i = 0;
if (fp) {
fscanf(fp, "%d", &i);
fclose(fp);
}
printf("%d\n", i);
}
You can use the std::ifstream thing to open a file for reading. You have to read in the contents using some other incantation to read the file contents and extract the desired information out of it yourself.
/* The C++ way */
#include <fstream>
#include <iostream>
int main() {
std::ifstream ifs("test.txt");
int i = 0;
if (ifs.good()) {
ifs >> i;
}
std::cout << i << std::endl;
}
Note you can use the C style functions in C++ as well, though this is the least recommended way:
/* The C way in C++ */
#include <cstdio>
#include <cstdlib>
int main() {
using namespace std;
FILE *fp = fopen("test.txt", "r");
int i = 0;
if (fp) {
fscanf(fp, "%d", &i);
fclose(fp);
}
printf("%d\n", i);
}
[Note: Both examples assume you have a text file to read from]
Do you want to read a textual representation of an int? Then you can use fscanf, it's sort of the opposite of printf
int n;
if( fscanf(filePointer, "%d", &n) == 1 )
// do stuff with n
If you want to read some binary data and treat it as an int, well that's going to depend how it was written in the first place.
I am not a Java programmer, so this is just based on what I've read in the [docs](http://java.sun.com/j2se/1.4.2/docs/api/java/io/DataOutputStream.html#writeInt(int)).
That said, it says
Writes an int to the underlying output stream as four bytes, high byte first. If no exception is thrown, the counter written is incremented by 4.
So it's a big endian four byte integer. I don't know if it's two's complement or not, but that's probably a safe assumption (and can probably be found somewhere in the java docs/spec). Big endian is the same as network byte order, so you can use ntohl to convert it the endianness of your C++ platform. Beyond that, you just need to read the four bytes, which can be done with fread.
Int represented as text or binary?
For text, use fscanf; for binary, use fread.