write corrupts data

So, i'm trying to copy data and add 32kb of 00 between every 32kb (don't ask why)
However, the data gets corrupted after the first 32kb, so the first 32kb from the input file get copied correctly to the output, but the next 32kb get all corrupted (except for a few bytes at the start...)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include "stdafx.h"
#include <iostream>
#include <fstream>
using namespace std;

typedef unsigned int word;
typedef unsigned long int dword;

const word bank (32768);
const word mb (1048576);
char * empty_bank;
char * input;
dword address (0);

///Fill
template<class _copybytes>
_copybytes fill(int _start, int _end, const int _value)
{
	for (; _start != _end; ++_start)
	{
		*_start (_value);
	}
} 
//Main
int main(int argc, char* argv[]) //_TCHAR*
{
	//open files
	ifstream rom (argv[1], ios::ate | ios::binary);
	ofstream out ("out.put", ios::binary);
	//allocate memory
	empty_bank = new char [bank];
	input = new char [bank];

	//fill them with 00
	fill(empty_bank + 0, empty_bank + bank, 0);
	fill(input + 0, input + bank, 0);
	//get size of file
	dword size = rom.tellg();
	//go to beginning
	rom.seekg(address, ios::beg);

	//loop!
	while (address != size * 2)
	{	
		//go there and get stuff =P
		rom.seekg(address);
		//read 32kb
		rom.read(input, bank);
		//go to that there and put stuff over there
		out.seekp(address);
		//write an empty bank
		out.write(empty_bank, bank);
		//write input bank
		out.write(input, bank);
		//increment get position
		address = address+bank+bank;
	}
	//release memory and close the files.
	delete[] empty_bank, input;
	out.close();
	rom.close();
	int code = 0;
	}
	return code;
}


So, it copies 32kb of 00, then 32kb of original file, then 32kb of 00, then the next 32kb of the original file, and so on. The first 32kb copy correctly, but the next don't. And also, is there any way of using NULL or something like that in write instead of having to fill an array with 00? And if I try using rom.is_open() and I don't specify anything in the command line, it anyway returns true. So if I don't specify anything, it will never stop copying 00...
And why can't I get rid of stdafx.h?

It's my first program (why do a Hello World if you can look at its code?) so probably many things are done totally wrong, but please, HELP!!!!
Last edited on
1. There is already an STL fill and fill_n function that does what your fill does.
2. You are probably best off filling an array with zeroes and writing it that way.
3. I don't know if it's your problem, but line 50 is not needed since you are
only ever writing to the end of the file anyway.
4. Check if( rom ) instead of is_open().
5. Line 59 does not do what you think it does; split it into two lines.
6. Because you are using a microsoft compiler, and those compilers get
nervous when they don't see a stdafx.h....
7. Lines 62/64 look a little strange with a brace between them.
8. Line 21 looks weird, *start = value instead, though use std::fill anyway.
1. There is already an STL fill and fill_n function that does what your fill does.
2. You are probably best off filling an array with zeroes and writing it that way.
3. I don't know if it's your problem, but line 50 is not needed since you are
only ever writing to the end of the file anyway.
4. Check if( rom ) instead of is_open().
5. Line 59 does not do what you think it does; split it into two lines.
6. Because you are using a microsoft compiler, and those compilers get
nervous when they don't see a stdafx.h....
7. Lines 62/64 look a little strange with a brace between them.
8. Line 21 looks weird, *start = value instead, though use std::fill anyway.


1 & 2. OK, thanks!
3. I put that later because I thought that without it it was causing the corruption. I got the same output, but forgot to delete it.
4. I'll try that when I have time. EDIT: Worked. I don't understand why, though.
5. I just switched from Visual C++ to Code::Blocks and GCC warned me about that. Stupid Visual C++.
6. I don't use it anymore.
7. Sorry, I had an if ( rom.is_open() ) and didn't delete that brace.
8. Just got rid of it, and for some reason, GCC didn't let me have *start = value, it would force me to start = value ...

But, that hasn't fixed the corruption of data...
Last edited on
You'll want to change the parameters of your fill function to char* from int. That will fix #8.

Is the file you are reading exactly a multiple of 32K in size? I ask because you don't check to see how many bytes you actually read.

I just got rid of that fill function.

And yes, the file is exactly a multiple of 32KB (512KB).
Can you post your new code?
main.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>
#include <fstream>
#include "main.hpp"

char * empty_bank;
char * input;

//Main
int main(int argc, char* argv[])
{
	//open rom
	ifstream rom (argv[1], ios::ate | ios::binary);
	//open out
    ofstream out (argv[2], ios::binary);
	if ( rom && out )
	{
        //allocate memory
        empty_bank = new char [bank];
        input = new char [bank];

        //fill them with 00
        fill(empty_bank, empty_bank + bank, 0);
        fill(input, input + bank, 0);

        //get size of rom
        dword size = rom.tellg();
        //go to beginning
        rom.seekg(ios::beg);

        //loop!
        while (address != size * 2)
        {
            //go there and get stuff =P
            rom.seekg(address);
            //read a bank
            rom.read(input, bank);
            //go to that there and put stuff over there
            //out.seekp(address);

            //write an empty bank
            out.write(empty_bank, bank);
            //write input bank
            out.write(input, bank);
            //increment get position
            address = address+bank+bank;
        }
        //release memory and close the files.
        delete[] empty_bank;
        delete[] input;
        out.close();
        rom.close();
        code = 0;
	}
	else
	{
	    usage (argv[0]);
	    code = 1;
	}
    return code;
}

void usage (const char* a)
{
    printf ("Usage:\n%s input.file output.file\n", a);
}
main.hpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#ifndef MAIN_HPP_INCLUDED
#define MAIN_HPP_INCLUDED
using namespace std;

typedef unsigned int word;
typedef unsigned long int dword;

const word bank = 32768;
const word mb = 1048576;
dword address = 0;
void usage (const char* a);
int code;

//Fill is already implemented in the STL
// no need for it.
/*

template<class _copybytes>
_copybytes fill(int _start, int _end, const int _value)
{
	for (; _start != _end; ++_start)
	{
		_start = _value;
	}
}

*/
#endif // MAIN_HPP_INCLUDED 


EDIT: rom && out do not work. Is there any alternative that is NOT if (rom) { if (out) { ... ?
EDIT_2: Funny, they work here but they don't work on the other program...
Last edited on
!!!!!

I made it output its get position in the loop with cout << "Current position is: " << rom.tellg() << endl; right before rom.seekg(address);
I got this:

Current position is: 0
Current position is: 32768
Current position is: 98304
Current position is: 163840
Current position is: 229376
Current position is: 294912
Current position is: 360448
Current position is: 425984
Current position is: 491520
Current position is: -1
Current position is: -1
Current position is: -1
Current position is: -1
Current position is: -1
Current position is: -1
Current position is: -1


I would expect data after 491520 to get corrupted, but since the 2nd one it's already corrupted.
And, what the heck with the -1s?
Last edited on
-1 means failure.

Why are you seeking at all?
Open the file without ios::ate.
1
2
3
4
5
6
open files
prepare 32k of filler in a buffer
while input_file
    read upto 32k from input_file
    write block to output_file
    write 32k of filler to output_file

Are you getting an infinite loop? Maybe it should be
while (address != size * 2 -1)
Ok, it is beginning to look stupid. But I can't try anything cause my computerjust stopped working.
OK, thanks everyone.

I just rewrote it on my laptop (which is slow as hell) on Ubuntu 8.10, but it should work with Windows.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>
#include <fstream>
#define BANK 32768
using namespace std;
char* input;
char* empty;

int main(int argc, char* argv[])
{
	//allocate memory
	input = new char[BANK];
	empty = new char[BANK];
	//fill 'empty' with 00
	fill(empty, empty+BANK, 0);
	//open files
	ifstream rom(argv[1], ios::binary);
	ofstream out(argv[2], ios::binary);
	//check if they're open
	if( rom && out )
	{
		while ( rom.tellg() != -1 )
		{
			//Display current position in hex
			cout.flags(ios::hex);
			cout << "Current position: " << rom.tellg() << endl;
			//Read 32KB
			rom.read(input, BANK);
			//Write 64KB
			out.write(empty, BANK);
			out.write(input, BANK);
		}
		rom.close();
		out.close();
		delete[] input;
		delete[] empty;
		return 0;
	}
	else if ( argc < 3 )
	{
		//Print usage
		cout << "Usage:" << endl << argv[0] << " input output" << endl;
		return 1;
	}
	else
	{
		//I'm guessing if it wasn't the wrong syntax, there was an error accessing files.
		cout << "File I/O error!" << endl;
		return 2;
	}
}


Much cleaner.
@kbw: While waiting for an answer, I found that. But thanks :D. And, is that AppleScript? It looks like the source of command-line frontends for OSX written in Applescript O_O
Last edited on
That was an attempt at psuedo-code.
Topic archived. No new replies allowed.