0

I want to save the received recoded data to another file so that it can be decoded back.

But for now I want to encode a jpg image to the same jpg format without changing the ascii code

As a result, I want to get the same image even though it was passed through encoding and saved separately.

here's my code:

static constexpr int64_t ascii_encoding[] {
    0, 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, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
    91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
    121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150,
    151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
    181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
    211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240,
    241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
};


std::filesystem::path filename = "test.jpg";
std::ifstream in(filename, std::ios::binary);


for (unsigned char c; in.get((char&)c);) {

    std::cout << (int)ascii_encoding[c] << " | " << c << " | " << (int)c << std::endl
}

It is also necessary that the data can be stored above 255 for further decoding. For example, I can change ASCII number 104 to 777 and save.

Charlie
  • 3
  • 3
  • 1
    So what is the question? Are you asking how to open a file and write data to it? – john Aug 11 '20 at 06:32
  • @john Yes, that's right, the main thing is that the file was not damaged – Charlie Aug 11 '20 at 06:38
  • 1
    What does your C++ book say about file operations? – Stephen Newell Aug 11 '20 at 06:42
  • What purpose does this array serve? It's a bunch of sequential numbers. Are any of these different in that they might perform an actual conversion? – tadman Aug 11 '20 at 06:44
  • @tadman no it is not different there everything is the same as in ascii now so the conversion must be performed one to one. – Charlie Aug 11 '20 at 06:51
  • That makes no sense to me. Why not just cast it if you're not doing any conversion? `(int64_t) c` is sufficient if the look-up table doesn't actually do anything, though I'm not sure why you're using `int64_t` for characters. Expecting to use UTF-64? – tadman Aug 11 '20 at 06:52
  • @tadman I did this on the off chance that I could figure out how to decode the values of a number greater than 255 – Charlie Aug 11 '20 at 06:57
  • Not sure how a single byte will have a value > 255 as it is, on any computer you're likely to use, going to be 8 bits and 8 bits only. Are you expecting to have to decode UTF-8 characters? That's not part of the [JPEG standard file format](https://en.wikipedia.org/wiki/JPEG). – tadman Aug 11 '20 at 06:58
  • @tadman I don't understand what you are writing about, I haven't thought about UTF-8 yet, I just wanted to encode any files. – Charlie Aug 11 '20 at 07:03
  • Can you explain better what "encode files" means in this particular context? You're referencing a JPEG file, but you're just dumping out the bytes for unexplained reasons. – tadman Aug 11 '20 at 07:04
  • @tadman Yes, I am currently getting bytes from a file, and I want to save them to a separate file. Then when I get bytes I will change them and save the file with other bytes. And then I'll figure out how to decode them back. – Charlie Aug 11 '20 at 07:13
  • I'm still at a complete loss as to what this means. Do you mean to "encrypt" the file somehow, as in change the bytes in a reversible way? Is this look-up table the start of something like a [substitution cipher](https://en.wikipedia.org/wiki/Substitution_cipher)? If so, think about working on the file in chunks of some size, like 1K or 10K and doing the substitutions on the raw buffer. Reading one character at a time is *excruciatingly* slow. A buffer is literally thousands of times faster. – tadman Aug 11 '20 at 07:14
  • @tadman it will be more difficult with the buffer, for now I want to implement a primitive form of encryption. – Charlie Aug 11 '20 at 07:21
  • Then do it with a buffer. It is not more difficult. It is a simple `for` loop over the contents. 1. Read into buffer. 2. Transform buffer. 3. Write buffer into output file. Repeat for each chunk as necessary, or if you're feeling bold, set your buffer size to the size of the file and read it in all at once. – tadman Aug 11 '20 at 07:22
  • Focus on the encoding part using something really, really, *really* simple, like `std::string encode(const std::string& input)` and build up from there. I think you're trying to tackle too many steps at once here. – tadman Aug 11 '20 at 07:30
  • @tadman I'm not sure yet if this will work, for now let it be as I intended, without a buffer. – Charlie Aug 11 '20 at 07:46
  • Not sure how you're writing out 777 as a `char`. – tadman Aug 11 '20 at 18:32

2 Answers2

0

So I'm not clear why you can't figure out the file output operations when you clearly have the file input operations. But anyway here is the code

std::ifstream in("test.jpg", std::ios::binary);
std::ofstream out("test.jpg.out", std::ios::binary);
for (unsigned char c; in.get((char&)c);) {
    std::cout << (int)ascii_encoding[c] << " | " << c << " | " << (int)c << std::endl;
    out.put((char)ascii_encoding[c]);
}

That's it. One line of code to open the output file, and one line of code to output the encoded value.

EDIT

It seems that you want to output int64_t values to your file. That can be done as follows

    out.write((char*)&ascii_encoding[c], sizeof ascii_encoding[c]);

Be aware that this code is platform specific, if you use this code on one platform you might have trouble reading the codes back on a different platform.

john
  • 85,011
  • 4
  • 57
  • 81
  • I thought I would be offered another option to save files with a code above 255. Your version works as long as the ascii code does not exceed 255 although I do not deny that it is possible that this cannot be done – Charlie Aug 11 '20 at 08:11
  • I need to think about how to ask the question more correctly – Charlie Aug 11 '20 at 08:17
  • @Charlie That wasn't clear from the original question. I'll edit the answer. – john Aug 11 '20 at 08:23
  • Added a description if you can show it will be super. – Charlie Aug 11 '20 at 08:28
  • @Charlie My latest code can handle numbers above 255. – john Aug 11 '20 at 08:42
  • you can show another example of how to watch this code, as I understand if the number is less than `255` there are `zeros` everywhere, if more zeros `(x8 the number of zeros)` are filled with other bytes. – Charlie Aug 11 '20 at 08:49
  • `in.read((char*)&ascii_encoding[c], sizeof ascii_encoding[c]);` not working yet I must be doing something wrong. – Charlie Aug 11 '20 at 08:58
  • @Charlie that is null padding which you can remove by setting a buffer size of 1 at a time. –  Aug 11 '20 at 08:59
  • @Charlie That code is wrong in a couple of ways. Most fundamentally you can't use the encoding array to do decoding. You need a separate data structure for that. `encoding_array` maps bytes to their encoded values. If you are going to decode you need something which maps encoded values to bytes. It's the other way around. – john Aug 11 '20 at 11:08
0

I find fread and fwrite much more intuitive when dealing with binary files. The following code takes a png file (format doesn't matter though. You may remove the extension and it will still work.) & makes a copy of it.

If the original data doesn't have anything beyond the limit of 255 that you say, this code won't modify the copy at all.

Though TOTAL and buf_size can be handled in a better way.

#include <iostream>
#include <fstream>
#include <cstdio>
#include <vector>

const int TOTAL = 58393 * 4;
// Keep buffer a multiple of TOTAL.
const int buf_size = TOTAL / 4;
const std::string infilepath = "png.png";
const std::string outfilepath = "pngcopy.png";

#define FOR_ALL_OF_THEM for (int i = 0; i < TOTAL; ++i)

void read_bin(std::vector<int> &all_of_them)
{
  FILE *infile = fopen(infilepath.c_str(), "rb");
  FOR_ALL_OF_THEM
  {
    fread(&all_of_them[i], sizeof(int), buf_size, infile);
    i += buf_size - 1;
  }
}

void write_bin(const std::vector<int> &all_of_them)
{
  FILE *outfile = fopen(outfilepath.c_str(), "wb");
  FOR_ALL_OF_THEM
  {
    fwrite(&all_of_them[i], sizeof(int), buf_size, outfile);
    i += buf_size - 1;
  }
  fclose(outfile);
}

int main()
{
  std::vector<int> all_of_them(TOTAL);
  read_bin(all_of_them);
  write_bin(all_of_them);
}

  • and where is ascii so that I can change bytes? – Charlie Aug 11 '20 at 08:54
  • Isn't it guaranteed that the incoming data doesnt exceed 255? Even if it doesnt, this makes an exact copy. So you don't have to worry about what the original data is. But still if you ask for it, change the data type of the `Vector` or use casts while writing. I suggest you open a binary file in an editor like SublimeText to see what's inside it. –  Aug 11 '20 at 08:57
  • can you show how you can encrypt data with your characters and decrypt it? your code seems interesting – Charlie Aug 11 '20 at 09:07
  • ` FILE* outfile = fopen(outfilepath.c_str(), "wb");` for some reason this line doesn't work for me – Charlie Aug 11 '20 at 09:13
  • _CRT_SECURE_NO_WARNINGS – Charlie Aug 11 '20 at 09:14
  • @Charlie "*can you show how you can encrypt data with your characters*"The whole code is in front of you. I read data 4 bytes at a time, and write it back 4 bytes at a time. You may use `char` as type and read/write the data character by character. That doesnt change the data. Only the amount by which it is being read. –  Aug 11 '20 at 09:15
  • "*`FILE* outfile = fopen(outfilepath.c_str(), "wb");`*" Make sure that outfilepath is absolute full path to the destination file. Also change this in VS to stop the warning https://stackoverflow.com/questions/22450423/how-to-use-crt-secure-no-warnings –  Aug 11 '20 at 09:16
  • I understood :) – Charlie Aug 11 '20 at 09:19