Click here to Skip to main content
14,984,043 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I have been contemplating this issue a few days.
Binary files created on Windows are read on Linux. It is handled normally on Windows.
But not on Linux.

To check more
I checked the file values ​​with a function like this:

File_*fp = open(dir, "rb+,ccs=UNICODE");
    
	if (fp == NULL)
	{
		fprintf(stderr, "Couldn't open file for reading\n");
		exit(1);
	};
    fseek(fp, 0, SEEK_END);
    long esize = ftell(fp);
    cout << "filesize: " <<  esize << endl;
    rewind(fp);


I think there is no problem with reading the file as the exact file size value is calculated.
As you can see in the results below, it reads the file size exactly.
I also looked at the binary data with the bitset operator.
bitset<8> a(CTE.Version);

The results are below.
Why can't Linux read files?
Thanks for your time!

What I have tried:

#pragma pack(push, 1)
typedef struct _CTE_
{ 
	unsigned short Version;
	unsigned short Signature;
	unsigned short core;
	unsigned short editmode
} CTE;
#pragma pack(pop) t

#pragma pack(push, 1)
typedef struct _GTE_
{
	unsigned char LTL : 1;
	unsigned char trans : 1;
	uint_least8_t wcountry;
	uint_least8_t wlanguage;
	unsigned int count; 
	int WIDTH;
	int HEIGHT;	
} GTE;
#pragma pack(push, 1)

class WXR
{
    _CTE_ cte;
    _GTE_ gte;
public:
    WXR();
    ~WXR();
	const void OpenFile(const int id);
	const void LoadCTE(FILE *hFile);
    const void LoadGTE(FILE *hFile);
}
WXR::WXR() :
cte{1, 42,10, 0},	
gte{1, 1, 9, 142, 0, 1920, 1080 }
{
}

WXR::~WXR()
{
	cte = {};
	gte = {};
}

const void WXR::OpenFile(const int id)
{
	const char *dir = NULL;

	if (id == 1)
	{
		dir = "data/1.pro/Project.txt";
	}
	else if (id == 2)
	{
		dir = "data/2.pro/Project.txt";
	}
	else if (id == 3)
	{
		dir = "data/3.pro/Project.txt";
	}
	else if (id == 4)
	{
		dir = "data/4.pro/Project.txt";
	}
	else
	{
		cout << "error file" << endl;
		return;
	}

	File_*fp = open(dir, "rb+,ccs=UNICODE");    
	if (fp == NULL)
	{
		fprintf(stderr, "Couldn't open file for reading\n");
		exit(1);
	};
    fseek(fp, 0, SEEK_END);
    long esize = ftell(fp);
    cout << "filesize: " <<  esize << endl;
    rewind(fp);

	LoadCTE(fp);
	LoadGTE(fp);
	delete fp;
}

const void WXR::LoadCTE(FILE *hFile)
{
    cout << __LINE__ << hFile << endl;
	cout << "CTe: " << sizeof(struct _CTE_) << endl;
	fread(&cte, sizeof(struct _CTE_), 1, hFile);
    bitset<8> a(cte.Version);
    bitset<8> b(cte.Signature);
    bitset<8> c(cte.core);
    bitset<8> d(cte.editmode);

	cout << __LINE__ << " " << a << endl;
	cout << __LINE__ << " " << b << endl;
	cout << __LINE__ << " " << c << endl;
	cout << __LINE__ << " " << d << endl;
}

const void WXR::LoadGTE(FILE *hFile)
{
	cout << __LINE__ << hFile << endl;
    cout << "gte: " << sizeof(struct GTE) << endl;
	fread(>e, sizeof(struct _GTE_), 1, hFile);
    bitset<8> a(gte.LTL);
    bitset<8> b(gte.trans);
    bitset<8> c(gte.wcountry);
    bitset<8> d(gte.wlanguage);
    bitset<8> e(gte.count);
    bitset<16> f(gte.WIDTH);
    bitset<16> g(gte.HEIGHT);

	cout << __LINE__ << " " << a << endl;
	cout << __LINE__ << " " << b << endl;
	cout << __LINE__ << " " << c << endl;
	cout << __LINE__ << " " << d << endl;
	cout << __LINE__ << " " << e << endl;
	cout << __LINE__ << " " << f << endl;
	cout << __LINE__ << " " << g << endl;
}

 =====================================================================================
Result:
                    windows(vscode)    |     Linux 
filesize:                                 38706097(correct)
 *fp               000002990A254F80         0x66f1a10
 hFile             000002990A3307A0         0x66f1a10
 headsize: (size)         8                     8
                       00000001             00000000
                       00101010             00000000
                       00001010             00000000
                       00000001             00000000

 hFile: (size)     000002990A3307A0         0x66f1a10
 properties                15                  15
                       00000001             00000000
                       00000001             00000000
                       00001001             00000000
                       10001110             00000000
                   0000000000010111      0000000000000000
                   0000011110000000      0000000000000000
                   0000010000111000      0000000000000000
Posted
Updated 10-Apr-21 6:38am
Comments
Rick York 10-Apr-21 0:09am
   
I would start by using a debugger and verifying the fread calls are loading the data into the structure. If you can't see the data in a debugger then consider writing a hex dumping function for yourself and dumping the data read from the file. It's really pretty easy. Once you have that verified then make sure the bitset calls are working correctly. You have to take it one step at a time.
Chopin2001 10-Apr-21 9:51am
   
I want to do that. I can find the problem in more detail.
Thanks.
Dave Kreskowiak 10-Apr-21 0:35am
   
You keep saying "read binary files", but all of your code screams that you're handling them as text files. Why would you even specify UNICODE handling for a binary file? You wouldn't.
Chopin2001 10-Apr-21 9:49am
   
I was thought that the name of the file to be loaded could be written in several languages. I found this to do the processing for that part.
However, after reading your comments, I found out that I was in the wrong idea. Thank you. I've been misunderstanding so far.
As soon as I corrected the point You pointed out, the program improved. Thank you very much.

You make the following call:
C++
File_*fp = open(dir, "rb+,ccs=UNICODE");

but that is not standard C. What is File_ and where is the code for open? It is also unclear why you are specifying a character encoding to read a binary file. Also the output that you are displaying does not match the code in your question.

You could test the integrity of your file by getting rid of your complicated class and simply coding the following:
C++
 	FILE* fp = fopen(dir, "rb"); // read binary data
	if (fp == NULL)
	{
		fprintf(stderr, "Couldn't open file for reading\n");
		exit(1);
	};
    fseek(fp, 0, SEEK_END);
    long esize = ftell(fp);
    cout << "filesize: " <<  esize << endl;
	int nbytes = fread(&cte, sizeof(struct _CTE_), 1, hFile);
	if (nbytes != sizeof(struct _CTE_))
	{
		fprintf(stderr, "Incorect file content\n");
		exit(1);
	};
// dump the content of cte



[EDIT]
I have just tested the following code that reads the header information of a Windows .exe file, and it produces the correct (i.e the same) results on Windows and on Linux.
C++
#define _CRT_SECURE_NO_WARNINGS
#include <cstdlib>
#include <cstdio>
#include <iostream>

using namespace std;

int main()
{
	struct
	{
		unsigned short	machineType;
		short			noSections;
		unsigned int	timeStamp;
		int				symbolTable;
		int				noSymbols;
		short			optionalHeader;
		short			characterstics;
	} coffHeader;

	FILE* fp = fopen("cp.exe", "rb");
	cout << "            fp: " << fp << endl;

	if (fp == NULL)
	{
		fprintf(stderr, "Couldn't open file for reading\n");
		exit(1);
	}

	cout << "   header size: " << sizeof(coffHeader) << endl;
	size_t freadSize = fread(&coffHeader, sizeof(coffHeader), 1, fp);
	cout << "     freadSize: " << freadSize << endl << endl;
	cout << "   machineType: " << coffHeader.machineType << endl;
	cout << "    noSections: " << coffHeader.noSections << endl;
	cout << "     timeStamp: " << coffHeader.timeStamp << endl;
	cout << "   symbolTable: " << coffHeader.symbolTable << endl;
	cout << "     noSymbols: " << coffHeader.noSymbols << endl;
	cout << "optionalHeader: " << coffHeader.optionalHeader << endl;
	cout << "characterstics: " << coffHeader.characterstics << endl;
}

[/EDIT]
   
v2
Comments
Chopin2001 10-Apr-21 9:30am
   
I'm so sorry. By default it writes file_ptr. You may have seen it in my previous post.

This is the way Bjarne Stroustrup recommended in the C++ programming language book.
It is made to prevent the code from getting longer. Of course this is also tested.
My mistake.
Richard MacCutchan 10-Apr-21 9:36am
   
I am not sure what that has to do with your problem. As you can see from the code above there is no problem reading a file on Linux that was created in Windows. You need to do some serious debugging of your code, because that is obviously where the problem lies.
Chopin2001 10-Apr-21 10:17am
   
I've applied your edits and it works now.
"rb+,CCS=UNICODE"

This is what I misunderstood. File titles are written in several languages. I found out to write unicode to handle it. This was very misunderstood.
FILE *fp = fopen(dir, "rb");

I have confirmed that I am reading the correct data now. Thank you very much for your interest and advice.
Richard MacCutchan 10-Apr-21 10:21am
   
Glad you fixed it.
Chopin2001 10-Apr-21 10:31am
   
i really appreciate your help thank you
Richard MacCutchan 10-Apr-21 10:38am
   
You are welcome.
If you're writing C++, why not use C++ I/O, rather than using the older C stdio based I/O? Still, you should be able to write binary data on Windows and read it on Linux, with only a little effort.

Windows program to write some binary data:
C++
#include <iostream>
#include <fstream>

struct CTE {
	unsigned short Version;
	unsigned short Signature;
	unsigned short core;
	unsigned short edition;
};

struct GTE {
	unsigned char LTL : 1;
	unsigned char trans : 1;
	uint_least8_t wcountry;
	uint_least8_t wlanguage;
	unsigned int count;
	int WIDTH;
	int HEIGHT;
};

int main()
{
	std::cout << "size of cte = " << sizeof(CTE) << '\n';
	std::cout << "sizeof gte = " << sizeof(GTE) << '\n';

	std::fstream data("C:\\tmp\\chopin.dat", std::ios::out | std::ios::binary);
	
	CTE cte{ 1, 15, 32, 1 };
	GTE gte{ 0, 1, 111, 222, 0, 456, 123 };
	
	data.write(reinterpret_cast<char*>(&cte), sizeof cte);
	for (size_t i = 1; i < 11; ++i) {
		gte.count = i;
		data.write(reinterpret_cast<char*>(>e), sizeof gte);
	}

	std::cout << "gte: "
		<< +gte.LTL << ' '
		<< +gte.trans << ' '
		<< +gte.wcountry << ' '
		<< +gte.wlanguage << ' '
		<< gte.count << ' '
		<< gte.WIDTH << ' '
		<< gte.HEIGHT << '\n';

	return 0;
}
Compiling and running this produces:
size of cte = 8
sizeof gte = 16
gte: 0 1 111 222 10 456 123


Linux program to read data:
//compiled with g++ -Wall -Wextra -mms-bitfields
#include <iostream>
#include <fstream>

struct CTE {
        unsigned short Version;
        unsigned short Signature;
        unsigned short core;
    unsigned short editmode;
}  __attribute__((ms_struct));

struct GTE {
        unsigned char LTL : 1;
        unsigned char trans : 1;
        uint_least8_t wcountry;
        uint_least8_t wlanguage;
        unsigned int count;
        int WIDTH;
        int HEIGHT;
} __attribute__((ms_struct));

int main()
{
    std::cout << "sizeof CTE " << sizeof(CTE) << '\n';
    std::cout << "sizeof GTE " << sizeof(GTE) << '\n';

    CTE cte;
    std::fstream data("chopin.dat", std::ios::in | std::ios::binary);

    data.read(reinterpret_cast<char*>(&cte), sizeof cte);
    for(size_t i = 0; i < 11; ++i) {
        GTE gte;
        data.read(reinterpret_cast<char*>(>e), sizeof gte);

        std::cout << +gte.LTL << ' '
                  << +gte.trans << ' '
                  << +gte.wcountry << ' '
                  << +gte.wlanguage << ' '
                  << gte.count << ' '
                  << gte.WIDTH << ' '
                  << gte.HEIGHT << '\n';
    }

}
This produces the expected output:
sizeof CTE 8
sizeof GTE 16
0 1 111 222 1 456 123
0 1 111 222 2 456 123
0 1 111 222 3 456 123
0 1 111 222 4 456 123
0 1 111 222 5 456 123
0 1 111 222 6 456 123
0 1 111 222 7 456 123
0 1 111 222 8 456 123
0 1 111 222 9 456 123
0 1 111 222 10 456 123
0 1 111 222 10 456 123

Notice that we don't need explicitly
C++
typedef struct _CTE_ { ... } CTE;
as C++ does that for us, for free. Also note that I'm not using #pragma pack on either side, but I am using __attribute__((ms_struct)), and compiling with -mms-bitfields. Actually, I've tried with and without both, and still get the same result, so perhaps these structs are simple enough that they map perfectly well from Windows to linux without needing compiler support.
Also, be wary of using identifiers starting with an underscore. The convention is that such identifiers are reserved for the implementation, i.e. the people writing the compiler. There is a risk that something like _GTE_ could be used by the compiler or library for some internal purpose, so if one of the #included headers has the following: #define _GTE_ 6, then your struct _GTE_ {} will fail to compile. Tracking down that mystery can take a lot of head scratching ... e.g. It compiles on OS version 7 but not on OS version 8 ... ???
   
v2
Comments
Chopin2001 10-Apr-21 11:26am
   
Wow!
I use C for religious reasons. The first thing I studied was the C language. And because I think the C primer plus written by stephan prata is the best masterpiece. (Of course the C++ Primer plus is great too.) This book has become a religious book for me :) Of course kernighan's book is good too. I'm still writing C and I still value what I've learned in this book. Another thing is that I thought C was the most portable and the best for speed and stability. C++ is now the fastest language.
So I take your advice seriously.
Thank you for making a really good point.
k5054 10-Apr-21 12:39pm
   
Seeing as you've tagged the question with C++, and used cout in your program, I hope I can be forgiven for assuming you were looking for C++ code :)

I don't actually do a lot of C++ myself - I learned C back when K&R was about the only reference there was. This was in the days of pre ANSI C so we didn't even have function prototypes, or void*. So most of my C++ tends to be C + STL, which is just fine, I think. ISTR that Stroustrup has said that C++ is a multi-paradigm language, and any way you want to use it, that's fine by him.

That being said, if you are going to be using the C++ compiler, you might as well add some of C++ goodness, like vectors and maps, ranged for loops, auto type deduction, etc. If nothing else, I think it produces somewhat easier to read code, and by pulling in the STL you've got a huge bag of tricks, written by really smart people, to rely on.
Chopin2001 10-Apr-21 13:31pm
   
That's a good point. The tag is my fault. It is correct to write code for c++ in the c++ compiler environment. I read your post and feel that the code I've written is too old-fashioned. I will improve this.
The code you uploaded is very good. If I use this without your consent, please forgive me :) And thank you. Thank you.
k5054 10-Apr-21 14:10pm
   
C++ is a superset of C (mostly), so if you're happiest writing C style code, but compiling with C++, then do so - especially if its just for your own amusement/consumption. In a work related situation, you would probably be expected to follow company guidelines and coding conventions, but that's a different kettle of fish.
I think that there's boilerplate around here that says anything posted here is considered in the Public Domain. Even if its not, the code I posted here is pretty generic. I would expect any more-or-less experienced programmer to come up with something almost identical. And, in any case, this site is supposed to be about sharing ideas, so copy away!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900